dolibarr 20.0.5
html.form.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
5 * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
6 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
7 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com>
8 * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
9 * Copyright (C) 2006 Marc Barilley/Ocebo <marc@ocebo.com>
10 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerker@telenet.be>
11 * Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
12 * Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
13 * Copyright (C) 2010-2021 Philippe Grand <philippe.grand@atoo-net.com>
14 * Copyright (C) 2011 Herve Prot <herve.prot@symeos.com>
15 * Copyright (C) 2012-2016 Marcos García <marcosgdf@gmail.com>
16 * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
17 * Copyright (C) 2012-2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
18 * Copyright (C) 2014-2023 Alexandre Spangaro <aspangaro@open-dsi.fr>
19 * Copyright (C) 2018-2022 Ferran Marcet <fmarcet@2byte.es>
20 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
21 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
22 * Copyright (C) 2018 Christophe Battarel <christophe@altairis.fr>
23 * Copyright (C) 2018 Josep Lluis Amador <joseplluis@lliuretic.cat>
24 * Copyright (C) 2023 Joachim Kueter <git-jk@bloxera.com>
25 * Copyright (C) 2023 Nick Fragoulis
26 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
27 *
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation; either version 3 of the License, or
31 * (at your option) any later version.
32 *
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
37 *
38 * You should have received a copy of the GNU General Public License
39 * along with this program. If not, see <https://www.gnu.org/licenses/>.
40 */
41
55class Form
56{
60 public $db;
61
65 public $error = '';
66
70 public $errors = array();
71
72 // Some properties used to return data by some methods
74 public $result;
76 public $num;
77
78 // Cache arrays
79 public $cache_types_paiements = array();
80 public $cache_conditions_paiements = array();
81 public $cache_transport_mode = array();
82 public $cache_availability = array();
83 public $cache_demand_reason = array();
84 public $cache_types_fees = array();
85 public $cache_vatrates = array();
86 public $cache_invoice_subtype = array();
87
88
94 public function __construct($db)
95 {
96 $this->db = $db;
97 }
98
115 public function editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata = 'string', $moreparam = '', $fieldrequired = 0, $notabletag = 0, $paramid = 'id', $help = '')
116 {
117 global $langs;
118
119 $ret = '';
120
121 // TODO change for compatibility
122 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;/', $typeofdata)) {
123 if (!empty($perm)) {
124 $tmp = explode(':', $typeofdata);
125 $ret .= '<div class="editkey_' . $tmp[0] . (!empty($tmp[1]) ? ' ' . $tmp[1] : '') . '" id="' . $htmlname . '">';
126 if ($fieldrequired) {
127 $ret .= '<span class="fieldrequired">';
128 }
129 if ($help) {
130 $ret .= $this->textwithpicto($langs->trans($text), $help);
131 } else {
132 $ret .= $langs->trans($text);
133 }
134 if ($fieldrequired) {
135 $ret .= '</span>';
136 }
137 $ret .= '</div>' . "\n";
138 } else {
139 if ($fieldrequired) {
140 $ret .= '<span class="fieldrequired">';
141 }
142 if ($help) {
143 $ret .= $this->textwithpicto($langs->trans($text), $help);
144 } else {
145 $ret .= $langs->trans($text);
146 }
147 if ($fieldrequired) {
148 $ret .= '</span>';
149 }
150 }
151 } else {
152 if (empty($notabletag) && $perm) {
153 $ret .= '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
154 }
155 if ($fieldrequired) {
156 $ret .= '<span class="fieldrequired">';
157 }
158 if ($help) {
159 $ret .= $this->textwithpicto($langs->trans($text), $help);
160 } else {
161 $ret .= $langs->trans($text);
162 }
163 if ($fieldrequired) {
164 $ret .= '</span>';
165 }
166 if (!empty($notabletag)) {
167 $ret .= ' ';
168 }
169 if (empty($notabletag) && $perm) {
170 $ret .= '</td>';
171 }
172 if (empty($notabletag) && $perm) {
173 $ret .= '<td class="right">';
174 }
175 if ($htmlname && GETPOST('action', 'aZ09') != 'edit' . $htmlname && $perm) {
176 $ret .= '<a class="editfielda reposition" href="' . $_SERVER["PHP_SELF"] . '?action=edit' . $htmlname . '&token=' . newToken() . '&' . $paramid . '=' . $object->id . $moreparam . '">' . img_edit($langs->trans('Edit'), ($notabletag ? 0 : 1)) . '</a>';
177 }
178 if (!empty($notabletag) && $notabletag == 1) {
179 if ($text) {
180 $ret .= ' : ';
181 } else {
182 $ret .= ' ';
183 }
184 }
185 if (!empty($notabletag) && $notabletag == 3) {
186 $ret .= ' ';
187 }
188 if (empty($notabletag) && $perm) {
189 $ret .= '</td>';
190 }
191 if (empty($notabletag) && $perm) {
192 $ret .= '</tr></table>';
193 }
194 }
195
196 return $ret;
197 }
198
222 public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 1, $formatfunc = '', $paramid = 'id', $gm = 'auto', $moreoptions = array(), $editaction = '')
223 {
224 global $conf, $langs;
225
226 $ret = '';
227
228 // Check parameters
229 if (empty($typeofdata)) {
230 return 'ErrorBadParameter typeofdata is empty';
231 }
232 // Clean parameter $typeofdata
233 if ($typeofdata == 'datetime') {
234 $typeofdata = 'dayhour';
235 }
236 $reg = array();
237 if (preg_match('/^(\w+)\‍((\d+)\‍)$/', $typeofdata, $reg)) {
238 if ($reg[1] == 'varchar') {
239 $typeofdata = 'string';
240 } elseif ($reg[1] == 'int') {
241 $typeofdata = 'numeric';
242 } else {
243 return 'ErrorBadParameter ' . $typeofdata;
244 }
245 }
246
247 // When option to edit inline is activated
248 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;|day|datepicker|dayhour|datehourpicker/', $typeofdata)) { // TODO add jquery timepicker and support select
249 $ret .= $this->editInPlace($object, $value, $htmlname, $perm, $typeofdata, $editvalue, $extObject, $custommsg);
250 } else {
251 if ($editaction == '') {
252 $editaction = GETPOST('action', 'aZ09');
253 }
254 $editmode = ($editaction == 'edit' . $htmlname);
255 if ($editmode) { // edit mode
256 $ret .= "\n";
257 $ret .= '<form method="post" action="' . $_SERVER["PHP_SELF"] . ($moreparam ? '?' . $moreparam : '') . '">';
258 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
259 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
260 $ret .= '<input type="hidden" name="' . $paramid . '" value="' . $object->id . '">';
261 if (empty($notabletag)) {
262 $ret .= '<table class="nobordernopadding centpercent">';
263 }
264 if (empty($notabletag)) {
265 $ret .= '<tr><td>';
266 }
267 if (preg_match('/^(string|safehtmlstring|email|phone|url)/', $typeofdata)) {
268 $tmp = explode(':', $typeofdata);
269 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($editvalue ? $editvalue : $value) . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
270 } elseif (preg_match('/^(integer)/', $typeofdata)) {
271 $tmp = explode(':', $typeofdata);
272 $valuetoshow = price2num($editvalue ? $editvalue : $value, 0);
273 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . $valuetoshow . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
274 } elseif (preg_match('/^(numeric|amount)/', $typeofdata)) {
275 $tmp = explode(':', $typeofdata);
276 $valuetoshow = price2num($editvalue ? $editvalue : $value);
277 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($valuetoshow != '' ? price($valuetoshow) : '') . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
278 } elseif (preg_match('/^(checkbox)/', $typeofdata)) {
279 $tmp = explode(':', $typeofdata);
280 $ret .= '<input type="checkbox" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($value ? $value : 'on') . '"' . ($value ? ' checked' : '') . (empty($tmp[1]) ? '' : $tmp[1]) . '/>';
281 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) { // if wysiwyg is enabled $typeofdata = 'ckeditor'
282 $tmp = explode(':', $typeofdata);
283 $cols = (empty($tmp[2]) ? '' : $tmp[2]);
284 $morealt = '';
285 if (preg_match('/%/', $cols)) {
286 $morealt = ' style="width: ' . $cols . '"';
287 $cols = '';
288 }
289 $valuetoshow = ($editvalue ? $editvalue : $value);
290 $ret .= '<textarea id="' . $htmlname . '" name="' . $htmlname . '" wrap="soft" rows="' . (empty($tmp[1]) ? '20' : $tmp[1]) . '"' . ($cols ? ' cols="' . $cols . '"' : 'class="quatrevingtpercent"') . $morealt . '" autofocus>';
291 // textarea convert automatically entities chars into simple chars.
292 // So we convert & into &amp; so a string like 'a &lt; <b>b</b><br>é<br>&lt;script&gt;alert('X');&lt;script&gt;' stay a correct html and is not converted by textarea component when wysiwyg is off.
293 $valuetoshow = str_replace('&', '&amp;', $valuetoshow);
294 $ret .= dol_htmlwithnojs(dol_string_neverthesehtmltags($valuetoshow, array('textarea')));
295 $ret .= '</textarea><div class="clearboth"></div>';
296 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
297 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
298 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
299 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
300 $ret .= $this->selectDate($value, $htmlname, 0, 0, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
301 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
302 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
303 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
304 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
305 $ret .= $this->selectDate($value, $htmlname, 1, 1, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
306 } elseif (preg_match('/^select;/', $typeofdata)) {
307 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
308 $arraylist = array();
309 foreach ($arraydata as $val) {
310 $tmp = explode(':', $val);
311 $tmpkey = str_replace('|', ':', $tmp[0]);
312 $arraylist[$tmpkey] = $tmp[1];
313 }
314 $ret .= $this->selectarray($htmlname, $arraylist, $value);
315 } elseif (preg_match('/^link/', $typeofdata)) {
316 // TODO Not yet implemented. See code for extrafields
317 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
318 $tmp = explode(':', $typeofdata); // Example: ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols:uselocalbrowser
319 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
320 $doleditor = new DolEditor($htmlname, ($editvalue ? $editvalue : $value), (empty($tmp[2]) ? '' : $tmp[2]), (empty($tmp[3]) ? '100' : $tmp[3]), (empty($tmp[1]) ? 'dolibarr_notes' : $tmp[1]), 'In', (empty($tmp[5]) ? 0 : $tmp[5]), (isset($tmp[8]) ? ($tmp[8] ? true : false) : true), true, (empty($tmp[6]) ? '20' : $tmp[6]), (empty($tmp[7]) ? '100' : $tmp[7]));
321 $ret .= $doleditor->Create(1);
322 } elseif ($typeofdata == 'asis') {
323 $ret .= ($editvalue ? $editvalue : $value);
324 }
325 if (empty($notabletag)) {
326 $ret .= '</td>';
327 }
328
329 // Button save-cancel
330 if (empty($notabletag)) {
331 $ret .= '<td>';
332 }
333 //else $ret.='<div class="clearboth"></div>';
334 $ret .= '<input type="submit" class="smallpaddingimp button' . (empty($notabletag) ? '' : ' ') . '" name="modify" value="' . $langs->trans("Modify") . '">';
335 if (preg_match('/ckeditor|textarea/', $typeofdata) && empty($notabletag)) {
336 $ret .= '<br>' . "\n";
337 }
338 $ret .= '<input type="submit" class="smallpaddingimp button button-cancel' . (empty($notabletag) ? '' : ' ') . '" name="cancel" value="' . $langs->trans("Cancel") . '">';
339 if (empty($notabletag)) {
340 $ret .= '</td>';
341 }
342
343 if (empty($notabletag)) {
344 $ret .= '</tr></table>' . "\n";
345 }
346 $ret .= '</form>' . "\n";
347 } else { // view mode
348 if (preg_match('/^email/', $typeofdata)) {
349 $ret .= dol_print_email($value, 0, 0, 0, 0, 1);
350 } elseif (preg_match('/^phone/', $typeofdata)) {
351 $ret .= dol_print_phone($value, '_blank', 32, 1);
352 } elseif (preg_match('/^url/', $typeofdata)) {
353 $ret .= dol_print_url($value, '_blank', 32, 1);
354 } elseif (preg_match('/^(amount|numeric)/', $typeofdata)) {
355 $ret .= ($value != '' ? price($value, 0, $langs, 0, -1, -1, $conf->currency) : '');
356 } elseif (preg_match('/^checkbox/', $typeofdata)) {
357 $tmp = explode(':', $typeofdata);
358 $ret .= '<input type="checkbox" disabled id="' . $htmlname . '" name="' . $htmlname . '" value="' . $value . '"' . ($value ? ' checked' : '') . ($tmp[1] ? $tmp[1] : '') . '/>';
359 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) {
361 } elseif (preg_match('/^(safehtmlstring|restricthtml)/', $typeofdata)) { // 'restricthtml' is not an allowed type for editfieldval. Value is 'safehtmlstring'
363 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
364 $ret .= '<span class="valuedate">' . dol_print_date($value, 'day', $gm) . '</span>';
365 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
366 $ret .= '<span class="valuedate">' . dol_print_date($value, 'dayhour', $gm) . '</span>';
367 } elseif (preg_match('/^select;/', $typeofdata)) {
368 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
369 $arraylist = array();
370 foreach ($arraydata as $val) {
371 $tmp = explode(':', $val);
372 $arraylist[$tmp[0]] = $tmp[1];
373 }
374 $ret .= $arraylist[$value];
375 if ($htmlname == 'fk_product_type') {
376 if ($value == 0) {
377 $ret = img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
378 } else {
379 $ret = img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
380 }
381 }
382 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
383 $tmpcontent = dol_htmlentitiesbr($value);
384 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
385 $firstline = preg_replace('/<br>.*/', '', $tmpcontent);
386 $firstline = preg_replace('/[\n\r].*/', '', $firstline);
387 $tmpcontent = $firstline . ((strlen($firstline) != strlen($tmpcontent)) ? '...' : '');
388 }
389 // We don't use dol_escape_htmltag to get the html formatting active, but this need we must also
390 // clean data from some dangerous html
392 } else {
393 if (empty($moreoptions['valuealreadyhtmlescaped'])) {
394 $ret .= dol_escape_htmltag($value);
395 } else {
396 $ret .= $value; // $value must be already html escaped.
397 }
398 }
399
400 // Custom format if parameter $formatfunc has been provided
401 if ($formatfunc && method_exists($object, $formatfunc)) {
402 $ret = $object->$formatfunc($ret);
403 }
404 }
405 }
406 return $ret;
407 }
408
420 public function widgetForTranslation($fieldname, $object, $perm, $typeofdata = 'string', $check = '', $morecss = '')
421 {
422 global $conf, $langs, $extralanguages;
423
424 $result = '';
425
426 // List of extra languages
427 $arrayoflangcode = array();
428 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
429 $arrayoflangcode[] = getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE');
430 }
431
432 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
433 if (!is_object($extralanguages)) {
434 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
435 $extralanguages = new ExtraLanguages($this->db);
436 }
437 $extralanguages->fetch_name_extralanguages('societe');
438
439 if (!is_array($extralanguages->attributes[$object->element]) || empty($extralanguages->attributes[$object->element][$fieldname])) {
440 return ''; // No extralang field to show
441 }
442
443 $result .= '<!-- Widget for translation -->' . "\n";
444 $result .= '<div class="inline-block paddingleft image-' . $object->element . '-' . $fieldname . '">';
445 $s = img_picto($langs->trans("ShowOtherLanguages"), 'language', '', false, 0, 0, '', 'fa-15 editfieldlang');
446 $result .= $s;
447 $result .= '</div>';
448
449 $result .= '<div class="inline-block hidden field-' . $object->element . '-' . $fieldname . '">';
450
451 $resultforextrlang = '';
452 foreach ($arrayoflangcode as $langcode) {
453 $valuetoshow = GETPOSTISSET('field-' . $object->element . "-" . $fieldname . "-" . $langcode) ? GETPOST('field-' . $object->element . '-' . $fieldname . "-" . $langcode, $check) : '';
454 if (empty($valuetoshow)) {
455 $object->fetchValuesForExtraLanguages();
456 //var_dump($object->array_languages);
457 $valuetoshow = $object->array_languages[$fieldname][$langcode];
458 }
459
460 $s = picto_from_langcode($langcode, 'class="pictoforlang paddingright"');
461 $resultforextrlang .= $s;
462
463 // TODO Use the showInputField() method of ExtraLanguages object
464 if ($typeofdata == 'textarea') {
465 $resultforextrlang .= '<textarea name="field-' . $object->element . "-" . $fieldname . "-" . $langcode . '" id="' . $fieldname . "-" . $langcode . '" class="' . $morecss . '" rows="' . ROWS_2 . '" wrap="soft">';
466 $resultforextrlang .= $valuetoshow;
467 $resultforextrlang .= '</textarea>';
468 } else {
469 $resultforextrlang .= '<input type="text" class="inputfieldforlang ' . ($morecss ? ' ' . $morecss : '') . '" name="field-' . $object->element . '-' . $fieldname . '-' . $langcode . '" value="' . $valuetoshow . '">';
470 }
471 }
472 $result .= $resultforextrlang;
473
474 $result .= '</div>';
475 $result .= '<script nonce="' . getNonce() . '">$(".image-' . $object->element . '-' . $fieldname . '").click(function() { console.log("Toggle lang widget"); jQuery(".field-' . $object->element . '-' . $fieldname . '").toggle(); });</script>';
476 }
477
478 return $result;
479 }
480
494 protected function editInPlace($object, $value, $htmlname, $condition, $inputType = 'textarea', $editvalue = null, $extObject = null, $custommsg = null)
495 {
496 $out = '';
497
498 // Check parameters
499 if (preg_match('/^text/', $inputType)) {
500 $value = dol_nl2br($value);
501 } elseif (preg_match('/^numeric/', $inputType)) {
502 $value = price($value);
503 } elseif ($inputType == 'day' || $inputType == 'datepicker') {
504 $value = dol_print_date($value, 'day');
505 }
506
507 if ($condition) {
508 $element = false;
509 $table_element = false;
510 $fk_element = false;
511 $loadmethod = false;
512 $savemethod = false;
513 $ext_element = false;
514 $button_only = false;
515 $inputOption = '';
516 $rows = '';
517 $cols = '';
518
519 if (is_object($object)) {
520 $element = $object->element;
521 $table_element = $object->table_element;
522 $fk_element = $object->id;
523 }
524
525 if (is_object($extObject)) {
526 $ext_element = $extObject->element;
527 }
528
529 if (preg_match('/^(string|email|numeric)/', $inputType)) {
530 $tmp = explode(':', $inputType);
531 $inputType = $tmp[0];
532 if (!empty($tmp[1])) {
533 $inputOption = $tmp[1];
534 }
535 if (!empty($tmp[2])) {
536 $savemethod = $tmp[2];
537 }
538 $out .= '<input id="width_' . $htmlname . '" value="' . $inputOption . '" type="hidden"/>' . "\n";
539 } elseif ((preg_match('/^day$/', $inputType)) || (preg_match('/^datepicker/', $inputType)) || (preg_match('/^datehourpicker/', $inputType))) {
540 $tmp = explode(':', $inputType);
541 $inputType = $tmp[0];
542 if (!empty($tmp[1])) {
543 $inputOption = $tmp[1];
544 }
545 if (!empty($tmp[2])) {
546 $savemethod = $tmp[2];
547 }
548
549 $out .= '<input id="timestamp" type="hidden"/>' . "\n"; // Use for timestamp format
550 } elseif (preg_match('/^(select|autocomplete)/', $inputType)) {
551 $tmp = explode(':', $inputType);
552 $inputType = $tmp[0];
553 $loadmethod = $tmp[1];
554 if (!empty($tmp[2])) {
555 $savemethod = $tmp[2];
556 }
557 if (!empty($tmp[3])) {
558 $button_only = true;
559 }
560 } elseif (preg_match('/^textarea/', $inputType)) {
561 $tmp = explode(':', $inputType);
562 $inputType = $tmp[0];
563 $rows = (empty($tmp[1]) ? '8' : $tmp[1]);
564 $cols = (empty($tmp[2]) ? '80' : $tmp[2]);
565 } elseif (preg_match('/^ckeditor/', $inputType)) {
566 $tmp = explode(':', $inputType);
567 $inputType = $tmp[0];
568 $toolbar = $tmp[1];
569 if (!empty($tmp[2])) {
570 $width = $tmp[2];
571 }
572 if (!empty($tmp[3])) {
573 $height = $tmp[3];
574 }
575 if (!empty($tmp[4])) {
576 $savemethod = $tmp[4];
577 }
578
579 if (isModEnabled('fckeditor')) {
580 $out .= '<input id="ckeditor_toolbar" value="' . $toolbar . '" type="hidden"/>' . "\n";
581 } else {
582 $inputType = 'textarea';
583 }
584 }
585
586 $out .= '<input id="element_' . $htmlname . '" value="' . $element . '" type="hidden"/>' . "\n";
587 $out .= '<input id="table_element_' . $htmlname . '" value="' . $table_element . '" type="hidden"/>' . "\n";
588 $out .= '<input id="fk_element_' . $htmlname . '" value="' . $fk_element . '" type="hidden"/>' . "\n";
589 $out .= '<input id="loadmethod_' . $htmlname . '" value="' . $loadmethod . '" type="hidden"/>' . "\n";
590 if (!empty($savemethod)) {
591 $out .= '<input id="savemethod_' . $htmlname . '" value="' . $savemethod . '" type="hidden"/>' . "\n";
592 }
593 if (!empty($ext_element)) {
594 $out .= '<input id="ext_element_' . $htmlname . '" value="' . $ext_element . '" type="hidden"/>' . "\n";
595 }
596 if (!empty($custommsg)) {
597 if (is_array($custommsg)) {
598 if (!empty($custommsg['success'])) {
599 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg['success'] . '" type="hidden"/>' . "\n";
600 }
601 if (!empty($custommsg['error'])) {
602 $out .= '<input id="errormsg_' . $htmlname . '" value="' . $custommsg['error'] . '" type="hidden"/>' . "\n";
603 }
604 } else {
605 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg . '" type="hidden"/>' . "\n";
606 }
607 }
608 if ($inputType == 'textarea') {
609 $out .= '<input id="textarea_' . $htmlname . '_rows" value="' . $rows . '" type="hidden"/>' . "\n";
610 $out .= '<input id="textarea_' . $htmlname . '_cols" value="' . $cols . '" type="hidden"/>' . "\n";
611 }
612 $out .= '<span id="viewval_' . $htmlname . '" class="viewval_' . $inputType . ($button_only ? ' inactive' : ' active') . '">' . $value . '</span>' . "\n";
613 $out .= '<span id="editval_' . $htmlname . '" class="editval_' . $inputType . ($button_only ? ' inactive' : ' active') . ' hideobject">' . (!empty($editvalue) ? $editvalue : $value) . '</span>' . "\n";
614 } else {
615 $out = $value;
616 }
617
618 return $out;
619 }
620
639 public function textwithtooltip($text, $htmltext, $tooltipon = 1, $direction = 0, $img = '', $extracss = '', $notabs = 3, $incbefore = '', $noencodehtmltext = 0, $tooltiptrigger = '', $forcenowrap = 0)
640 {
641 if ($incbefore) {
642 $text = $incbefore . $text;
643 }
644 if (!$htmltext) {
645 return $text;
646 }
647 $direction = (int) $direction; // For backward compatibility when $direction was set to '' instead of 0
648
649 $tag = 'td';
650 if ($notabs == 2) {
651 $tag = 'div';
652 }
653 if ($notabs == 3) {
654 $tag = 'span';
655 }
656 // Sanitize tooltip
657 $htmltext = str_replace(array("\r", "\n"), '', $htmltext);
658
659 $extrastyle = '';
660 if ($direction < 0) {
661 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
662 $extrastyle = 'padding: 0px; padding-left: 2px;';
663 }
664 if ($direction > 0) {
665 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
666 $extrastyle = 'padding: 0px; padding-right: 2px;';
667 }
668
669 $classfortooltip = 'classfortooltip';
670
671 $s = '';
672 $textfordialog = '';
673
674 if ($tooltiptrigger == '') {
675 $htmltext = str_replace('"', '&quot;', $htmltext);
676 } else {
677 $classfortooltip = 'classfortooltiponclick';
678 $textfordialog .= '<div style="display: none;" id="idfortooltiponclick_' . $tooltiptrigger . '" class="classfortooltiponclicktext">' . $htmltext . '</div>';
679 }
680 if ($tooltipon == 2 || $tooltipon == 3) {
681 $paramfortooltipimg = ' class="' . $classfortooltip . ($notabs != 3 ? ' inline-block' : '') . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '"';
682 if ($tooltiptrigger == '') {
683 $paramfortooltipimg .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribute to put on img tag to store tooltip
684 } else {
685 $paramfortooltipimg .= ' dolid="' . $tooltiptrigger . '"';
686 }
687 } else {
688 $paramfortooltipimg = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribute to put on td text tag
689 }
690 if ($tooltipon == 1 || $tooltipon == 3) {
691 $paramfortooltiptd = ' class="' . ($tooltipon == 3 ? 'cursorpointer ' : '') . $classfortooltip . ' inline-block' . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '" ';
692 if ($tooltiptrigger == '') {
693 $paramfortooltiptd .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribute to put on td tag to store tooltip
694 } else {
695 $paramfortooltiptd .= ' dolid="' . $tooltiptrigger . '"';
696 }
697 } else {
698 $paramfortooltiptd = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribute to put on td text tag
699 }
700 if (empty($notabs)) {
701 $s .= '<table class="nobordernopadding"><tr style="height: auto;">';
702 } elseif ($notabs == 2) {
703 $s .= '<div class="inline-block' . ($forcenowrap ? ' nowrap' : '') . '">';
704 }
705 // Define value if value is before
706 if ($direction < 0) {
707 $s .= '<' . $tag . $paramfortooltipimg;
708 if ($tag == 'td') {
709 $s .= ' class="valigntop" width="14"';
710 }
711 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
712 }
713 // Use another method to help avoid having a space in value in order to use this value with jquery
714 // Define label
715 if ((string) $text != '') {
716 $s .= '<' . $tag . $paramfortooltiptd . '>' . $text . '</' . $tag . '>';
717 }
718 // Define value if value is after
719 if ($direction > 0) {
720 $s .= '<' . $tag . $paramfortooltipimg;
721 if ($tag == 'td') {
722 $s .= ' class="valignmiddle" width="14"';
723 }
724 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
725 }
726 if (empty($notabs)) {
727 $s .= '</tr></table>';
728 } elseif ($notabs == 2) {
729 $s .= '</div>';
730 }
731
732 return $s;
733 }
734
749 public function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 3, $tooltiptrigger = '', $forcenowrap = 0)
750 {
751 global $conf, $langs;
752
753 //For backwards compatibility
754 if ($type == '0') {
755 $type = 'info';
756 } elseif ($type == '1') {
757 $type = 'help';
758 }
759 // Clean parameters
760 $tooltiptrigger = preg_replace('/[^a-z0-9]/i', '', $tooltiptrigger);
761
762 if (preg_match('/onsmartphone$/', $tooltiptrigger) && empty($conf->dol_no_mouse_hover)) {
763 $tooltiptrigger = preg_replace('/^.*onsmartphone$/', '', $tooltiptrigger);
764 }
765 $alt = '';
766 if ($tooltiptrigger) {
767 $alt = $langs->transnoentitiesnoconv("ClickToShowHelp");
768 }
769
770 // If info or help with no javascript, show only text
771 if (empty($conf->use_javascript_ajax)) {
772 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
773 return $text;
774 } else {
775 $alt = $htmltext;
776 $htmltext = '';
777 }
778 }
779
780 // If info or help with smartphone, show only text (tooltip hover can't works)
781 if (!empty($conf->dol_no_mouse_hover) && empty($tooltiptrigger)) {
782 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
783 return $text;
784 }
785 }
786 // If info or help with smartphone, show only text (tooltip on click does not works with dialog on smaprtphone)
787 //if (!empty($conf->dol_no_mouse_hover) && !empty($tooltiptrigger))
788 //{
789 //if ($type == 'info' || $type == 'help') return '<a href="'..'">'.$text.'</a>';
790 //}
791
792 $img = '';
793 if ($type == 'info') {
794 $img = img_help(0, $alt);
795 } elseif ($type == 'help') {
796 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
797 } elseif ($type == 'helpclickable') {
798 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
799 } elseif ($type == 'superadmin') {
800 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
801 $img = img_picto($alt, 'redstar');
802 } elseif ($type == 'admin') {
803 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
804 $img = img_picto($alt, 'star');
805 } elseif ($type == 'warning') {
806 $img = img_warning($alt);
807 } elseif ($type != 'none') {
808 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
809 $img = img_picto($alt, $type); // $type can be an image path
810 }
811
812 return $this->textwithtooltip($text, $htmltext, ((($tooltiptrigger && !$img) || strpos($type, 'clickable')) ? 3 : 2), $direction, $img, $extracss, $notabs, '', $noencodehtmltext, $tooltiptrigger, $forcenowrap);
813 }
814
825 public function selectMassAction($selected, $arrayofaction, $alwaysvisible = 0, $name = 'massaction', $cssclass = 'checkforselect')
826 {
827 global $conf, $langs, $hookmanager;
828
829 $disabled = 0;
830 $ret = '<div class="centpercent center">';
831 $ret .= '<select class="flat' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'select valignmiddle alignstart" id="' . $name . '" name="' . $name . '"' . ($disabled ? ' disabled="disabled"' : '') . '>';
832
833 // Complete list with data from external modules. THe module can use $_SERVER['PHP_SELF'] to know on which page we are, or use the $parameters['currentcontext'] completed by executeHooks.
834 $parameters = array();
835 $reshook = $hookmanager->executeHooks('addMoreMassActions', $parameters); // Note that $action and $object may have been modified by hook
836 // check if there is a mass action
837
838 if (is_array($arrayofaction) && count($arrayofaction) == 0 && empty($hookmanager->resPrint)) {
839 return;
840 }
841 if (empty($reshook)) {
842 $ret .= '<option value="0"' . ($disabled ? ' disabled="disabled"' : '') . '>-- ' . $langs->trans("SelectAction") . ' --</option>';
843 if (is_array($arrayofaction)) {
844 foreach ($arrayofaction as $code => $label) {
845 $ret .= '<option value="' . $code . '"' . ($disabled ? ' disabled="disabled"' : '') . ' data-html="' . dol_escape_htmltag($label) . '">' . $label . '</option>';
846 }
847 }
848 }
849 $ret .= $hookmanager->resPrint;
850
851 $ret .= '</select>';
852
853 if (empty($conf->dol_optimize_smallscreen)) {
854 $ret .= ajax_combobox('.' . $name . 'select');
855 }
856
857 // Warning: if you set submit button to disabled, post using 'Enter' will no more work if there is no another input submit. So we add a hidden button
858 $ret .= '<input type="submit" name="confirmmassactioninvisible" style="display: none" tabindex="-1">'; // Hidden button BEFORE so it is the one used when we submit with ENTER.
859 $ret .= '<input type="submit" disabled name="confirmmassaction"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display: none"') . ' class="reposition button smallpaddingimp' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'confirmed" value="' . dol_escape_htmltag($langs->trans("Confirm")) . '">';
860 $ret .= '</div>';
861
862 if (!empty($conf->use_javascript_ajax)) {
863 $ret .= '<!-- JS CODE TO ENABLE mass action select -->
864 <script nonce="' . getNonce() . '">
865 function initCheckForSelect(mode, name, cssclass) /* mode is 0 during init of page or click all, 1 when we click on 1 checkboxi, "name" refers to the class of the massaction button, "cssclass" to the class of the checkfor select boxes */
866 {
867 atleastoneselected=0;
868 jQuery("."+cssclass).each(function( index ) {
869 /* console.log( index + ": " + $( this ).text() ); */
870 if ($(this).is(\':checked\')) atleastoneselected++;
871 });
872
873 console.log("initCheckForSelect mode="+mode+" name="+name+" cssclass="+cssclass+" atleastoneselected="+atleastoneselected);
874
875 if (atleastoneselected || ' . $alwaysvisible . ')
876 {
877 jQuery("."+name).show();
878 ' . ($selected ? 'if (atleastoneselected) { jQuery("."+name+"select").val("' . $selected . '").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', false); }' : '') . '
879 ' . ($selected ? 'if (! atleastoneselected) { jQuery("."+name+"select").val("0").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', true); } ' : '') . '
880 }
881 else
882 {
883 jQuery("."+name).hide();
884 jQuery("."+name+"other").hide();
885 }
886 }
887
888 jQuery(document).ready(function () {
889 initCheckForSelect(0, "' . $name . '", "' . $cssclass . '");
890 jQuery(".' . $cssclass . '").click(function() {
891 initCheckForSelect(1, "' . $name . '", "' . $cssclass . '");
892 });
893 jQuery(".' . $name . 'select").change(function() {
894 var massaction = $( this ).val();
895 var urlform = $( this ).closest("form").attr("action").replace("#show_files","");
896 if (massaction == "builddoc")
897 {
898 urlform = urlform + "#show_files";
899 }
900 $( this ).closest("form").attr("action", urlform);
901 console.log("we select a mass action name=' . $name . ' massaction="+massaction+" - "+urlform);
902 /* Warning: if you set submit button to disabled, post using Enter will no more work if there is no other button */
903 if ($(this).val() != \'0\')
904 {
905 jQuery(".' . $name . 'confirmed").prop(\'disabled\', false);
906 jQuery(".' . $name . 'other").hide(); /* To disable if another div was open */
907 jQuery(".' . $name . '"+massaction).show();
908 }
909 else
910 {
911 jQuery(".' . $name . 'confirmed").prop(\'disabled\', true);
912 jQuery(".' . $name . 'other").hide(); /* To disable any div open */
913 }
914 });
915 });
916 </script>
917 ';
918 }
919
920 return $ret;
921 }
922
923 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
924
941 public function select_country($selected = '', $htmlname = 'country_id', $htmloption = '', $maxlength = 0, $morecss = 'minwidth300', $usecodeaskey = '', $showempty = 1, $disablefavorites = 0, $addspecialentries = 0, $exclude_country_code = array(), $hideflags = 0)
942 {
943 // phpcs:enable
944 global $conf, $langs, $mysoc;
945
946 $langs->load("dict");
947
948 $out = '';
949 $countryArray = array();
950 $favorite = array();
951 $label = array();
952 $atleastonefavorite = 0;
953
954 $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite, eec";
955 $sql .= " FROM " . $this->db->prefix() . "c_country";
956 $sql .= " WHERE active > 0";
957 //$sql.= " ORDER BY code ASC";
958
959 dol_syslog(get_class($this) . "::select_country", LOG_DEBUG);
960 $resql = $this->db->query($sql);
961 if ($resql) {
962 $out .= '<select id="select' . $htmlname . '" class="flat maxwidth200onsmartphone selectcountry' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" ' . $htmloption . '>';
963 $num = $this->db->num_rows($resql);
964 $i = 0;
965 if ($num) {
966 while ($i < $num) {
967 $obj = $this->db->fetch_object($resql);
968
969 $countryArray[$i]['rowid'] = $obj->rowid;
970 $countryArray[$i]['code_iso'] = $obj->code_iso;
971 $countryArray[$i]['code_iso3'] = $obj->code_iso3;
972 $countryArray[$i]['label'] = ($obj->code_iso && $langs->transnoentitiesnoconv("Country" . $obj->code_iso) != "Country" . $obj->code_iso ? $langs->transnoentitiesnoconv("Country" . $obj->code_iso) : ($obj->label != '-' ? $obj->label : ''));
973 $countryArray[$i]['favorite'] = $obj->favorite;
974 $countryArray[$i]['eec'] = $obj->eec;
975 $favorite[$i] = $obj->favorite;
976 $label[$i] = dol_string_unaccent($countryArray[$i]['label']);
977 $i++;
978 }
979
980 if (empty($disablefavorites)) {
981 $array1_sort_order = SORT_DESC;
982 $array2_sort_order = SORT_ASC;
983 array_multisort($favorite, $array1_sort_order, $label, $array2_sort_order, $countryArray);
984 } else {
985 $countryArray = dol_sort_array($countryArray, 'label');
986 }
987
988 if ($showempty) {
989 if (is_numeric($showempty)) {
990 $out .= '<option value="">&nbsp;</option>' . "\n";
991 } else {
992 $out .= '<option value="-1">' . $langs->trans($showempty) . '</option>' . "\n";
993 }
994 }
995
996 if ($addspecialentries) { // Add dedicated entries for groups of countries
997 //if ($showempty) $out.= '<option value="" disabled class="selectoptiondisabledwhite">--------------</option>';
998 $out .= '<option value="special_allnotme"' . ($selected == 'special_allnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
999 $out .= '<option value="special_eec"' . ($selected == 'special_eec' ? ' selected' : '') . '>' . $langs->trans("CountriesInEEC") . '</option>';
1000 if ($mysoc->isInEEC()) {
1001 $out .= '<option value="special_eecnotme"' . ($selected == 'special_eecnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesInEECExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
1002 }
1003 $out .= '<option value="special_noteec"' . ($selected == 'special_noteec' ? ' selected' : '') . '>' . $langs->trans("CountriesNotInEEC") . '</option>';
1004 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1005 }
1006
1007 foreach ($countryArray as $row) {
1008 //if (empty($showempty) && empty($row['rowid'])) continue;
1009 if (empty($row['rowid'])) {
1010 continue;
1011 }
1012 if (is_array($exclude_country_code) && count($exclude_country_code) && in_array($row['code_iso'], $exclude_country_code)) {
1013 continue; // exclude some countries
1014 }
1015
1016 if (empty($disablefavorites) && $row['favorite'] && $row['code_iso']) {
1017 $atleastonefavorite++;
1018 }
1019 if (empty($row['favorite']) && $atleastonefavorite) {
1020 $atleastonefavorite = 0;
1021 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1022 }
1023
1024 $labeltoshow = '';
1025 if ($row['label']) {
1026 $labeltoshow .= dol_trunc($row['label'], $maxlength, 'middle');
1027 } else {
1028 $labeltoshow .= '&nbsp;';
1029 }
1030 if ($row['code_iso']) {
1031 $labeltoshow .= ' <span class="opacitymedium">(' . $row['code_iso'] . ')</span>';
1032 if (empty($hideflags)) {
1033 $tmpflag = picto_from_langcode($row['code_iso'], 'class="saturatemedium paddingrightonly"', 1);
1034 $labeltoshow = $tmpflag . ' ' . $labeltoshow;
1035 }
1036 }
1037
1038 if ($selected && $selected != '-1' && ($selected == $row['rowid'] || $selected == $row['code_iso'] || $selected == $row['code_iso3'] || $selected == $row['label'])) {
1039 $out .= '<option value="' . ($usecodeaskey ? ($usecodeaskey == 'code2' ? $row['code_iso'] : $row['code_iso3']) : $row['rowid']) . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '" data-eec="' . ((int) $row['eec']) . '">';
1040 } else {
1041 $out .= '<option value="' . ($usecodeaskey ? ($usecodeaskey == 'code2' ? $row['code_iso'] : $row['code_iso3']) : $row['rowid']) . '" data-html="' . dol_escape_htmltag($labeltoshow) . '" data-eec="' . ((int) $row['eec']) . '">';
1042 }
1043 $out .= $labeltoshow;
1044 $out .= '</option>' . "\n";
1045 }
1046 }
1047 $out .= '</select>';
1048 } else {
1049 dol_print_error($this->db);
1050 }
1051
1052 // Make select dynamic
1053 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1054 $out .= ajax_combobox('select' . $htmlname, array(), 0, 0, 'resolve');
1055
1056 return $out;
1057 }
1058
1059 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1060
1074 public function select_incoterms($selected = '', $location_incoterms = '', $page = '', $htmlname = 'incoterm_id', $htmloption = '', $forcecombo = 1, $events = array(), $disableautocomplete = 0)
1075 {
1076 // phpcs:enable
1077 global $conf, $langs;
1078
1079 $langs->load("dict");
1080
1081 $out = '';
1082 $moreattrib = '';
1083 $incotermArray = array();
1084
1085 $sql = "SELECT rowid, code";
1086 $sql .= " FROM " . $this->db->prefix() . "c_incoterms";
1087 $sql .= " WHERE active > 0";
1088 $sql .= " ORDER BY code ASC";
1089
1090 dol_syslog(get_class($this) . "::select_incoterm", LOG_DEBUG);
1091 $resql = $this->db->query($sql);
1092 if ($resql) {
1093 if ($conf->use_javascript_ajax && !$forcecombo) {
1094 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1095 $out .= ajax_combobox($htmlname, $events);
1096 }
1097
1098 if (!empty($page)) {
1099 $out .= '<form method="post" action="' . $page . '">';
1100 $out .= '<input type="hidden" name="action" value="set_incoterms">';
1101 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
1102 }
1103
1104 $out .= '<select id="' . $htmlname . '" class="flat selectincoterm width75" name="' . $htmlname . '" ' . $htmloption . '>';
1105 $out .= '<option value="0">&nbsp;</option>';
1106 $num = $this->db->num_rows($resql);
1107 $i = 0;
1108 if ($num) {
1109 while ($i < $num) {
1110 $obj = $this->db->fetch_object($resql);
1111 $incotermArray[$i]['rowid'] = $obj->rowid;
1112 $incotermArray[$i]['code'] = $obj->code;
1113 $i++;
1114 }
1115
1116 foreach ($incotermArray as $row) {
1117 if ($selected && ($selected == $row['rowid'] || $selected == $row['code'])) {
1118 $out .= '<option value="' . $row['rowid'] . '" selected>';
1119 } else {
1120 $out .= '<option value="' . $row['rowid'] . '">';
1121 }
1122
1123 if ($row['code']) {
1124 $out .= $row['code'];
1125 }
1126
1127 $out .= '</option>';
1128 }
1129 }
1130 $out .= '</select>';
1131
1132 if ($conf->use_javascript_ajax && empty($disableautocomplete)) {
1133 $out .= ajax_multiautocompleter('location_incoterms', array(), DOL_URL_ROOT . '/core/ajax/locationincoterms.php') . "\n";
1134 $moreattrib .= ' autocomplete="off"';
1135 }
1136 $out .= '<input id="location_incoterms" class="maxwidthonsmartphone type="text" name="location_incoterms" value="' . $location_incoterms . '">' . "\n";
1137
1138 if (!empty($page)) {
1139 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp nomargintop nomarginbottom" value="' . $langs->trans("Modify") . '"></form>';
1140 }
1141 } else {
1142 dol_print_error($this->db);
1143 }
1144
1145 return $out;
1146 }
1147
1148 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1149
1162 public function select_type_of_lines($selected = '', $htmlname = 'type', $showempty = 0, $hidetext = 0, $forceall = 0, $morecss = "")
1163 {
1164 // phpcs:enable
1165 global $langs;
1166
1167 // If product & services are enabled or both disabled.
1168 if ($forceall == 1 || (empty($forceall) && isModEnabled("product") && isModEnabled("service"))
1169 || (empty($forceall) && !isModEnabled('product') && !isModEnabled('service'))) {
1170 if (empty($hidetext)) {
1171 print $langs->trans("Type") . ': ';
1172 }
1173 print '<select class="flat'.($morecss ? ' '.$morecss : '').'" id="select_' . $htmlname . '" name="' . $htmlname . '">';
1174 if ($showempty) {
1175 print '<option value="-1"';
1176 if ($selected == -1) {
1177 print ' selected';
1178 }
1179 print '>';
1180 if (is_numeric($showempty)) {
1181 print '&nbsp;';
1182 } else {
1183 print $showempty;
1184 }
1185 print '</option>';
1186 }
1187
1188 print '<option value="0"';
1189 if (0 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'product')) {
1190 print ' selected';
1191 }
1192 print '>' . $langs->trans("Product");
1193
1194 print '<option value="1"';
1195 if (1 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'service')) {
1196 print ' selected';
1197 }
1198 print '>' . $langs->trans("Service");
1199
1200 print '</select>';
1201 print ajax_combobox('select_' . $htmlname);
1202 //if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1203 }
1204 if ((empty($forceall) && !isModEnabled('product') && isModEnabled("service")) || $forceall == 3) {
1205 print $langs->trans("Service");
1206 print '<input type="hidden" name="' . $htmlname . '" value="1">';
1207 }
1208 if ((empty($forceall) && isModEnabled("product") && !isModEnabled('service')) || $forceall == 2) {
1209 print $langs->trans("Product");
1210 print '<input type="hidden" name="' . $htmlname . '" value="0">';
1211 }
1212 if ($forceall < 0) { // This should happened only for contracts when both predefined product and service are disabled.
1213 print '<input type="hidden" name="' . $htmlname . '" value="1">'; // By default we set on service for contract. If CONTRACT_SUPPORT_PRODUCTS is set, forceall should be 1 not -1
1214 }
1215 }
1216
1217 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1218
1224 public function load_cache_types_fees()
1225 {
1226 // phpcs:enable
1227 global $langs;
1228
1229 $num = count($this->cache_types_fees);
1230 if ($num > 0) {
1231 return 0; // Cache already loaded
1232 }
1233
1234 dol_syslog(__METHOD__, LOG_DEBUG);
1235
1236 $langs->load("trips");
1237
1238 $sql = "SELECT c.code, c.label";
1239 $sql .= " FROM " . $this->db->prefix() . "c_type_fees as c";
1240 $sql .= " WHERE active > 0";
1241
1242 $resql = $this->db->query($sql);
1243 if ($resql) {
1244 $num = $this->db->num_rows($resql);
1245 $i = 0;
1246
1247 while ($i < $num) {
1248 $obj = $this->db->fetch_object($resql);
1249
1250 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
1251 $label = ($obj->code != $langs->trans($obj->code) ? $langs->trans($obj->code) : $langs->trans($obj->label));
1252 $this->cache_types_fees[$obj->code] = $label;
1253 $i++;
1254 }
1255
1256 asort($this->cache_types_fees);
1257
1258 return $num;
1259 } else {
1260 dol_print_error($this->db);
1261 return -1;
1262 }
1263 }
1264
1265 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1266
1275 public function select_type_fees($selected = '', $htmlname = 'type', $showempty = 0)
1276 {
1277 // phpcs:enable
1278 global $user, $langs;
1279
1280 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
1281
1282 $this->load_cache_types_fees();
1283
1284 print '<select id="select_' . $htmlname . '" class="flat" name="' . $htmlname . '">';
1285 if ($showempty) {
1286 print '<option value="-1"';
1287 if ($selected == -1) {
1288 print ' selected';
1289 }
1290 print '>&nbsp;</option>';
1291 }
1292
1293 foreach ($this->cache_types_fees as $key => $value) {
1294 print '<option value="' . $key . '"';
1295 if ($key == $selected) {
1296 print ' selected';
1297 }
1298 print '>';
1299 print $value;
1300 print '</option>';
1301 }
1302
1303 print '</select>';
1304 if ($user->admin) {
1305 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1306 }
1307 }
1308
1309
1310 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1311
1334 public function select_company($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $limit = 0, $morecss = 'minwidth100', $moreparam = '', $selected_input_value = '', $hidelabel = 1, $ajaxoptions = array(), $multiple = false, $excludeids = array(), $showcode = 0)
1335 {
1336 // phpcs:enable
1337 global $conf, $langs;
1338
1339 $out = '';
1340
1341 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT') && !$forcecombo) {
1342 if (is_null($ajaxoptions)) {
1343 $ajaxoptions = array();
1344 }
1345
1346 require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1347
1348 // No immediate load of all database
1349 $placeholder = '';
1350 if ($selected && empty($selected_input_value)) {
1351 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1352 $societetmp = new Societe($this->db);
1353 $societetmp->fetch($selected);
1354 $selected_input_value = $societetmp->name;
1355 unset($societetmp);
1356 }
1357
1358 // mode 1
1359 $urloption = 'htmlname=' . urlencode((string) (str_replace('.', '_', $htmlname))) . '&outjson=1&filter=' . urlencode((string) ($filter)) . (empty($excludeids) ? '' : '&excludeids=' . implode(',', $excludeids)) . ($showtype ? '&showtype=' . urlencode((string) ($showtype)) : '') . ($showcode ? '&showcode=' . urlencode((string) ($showcode)) : '');
1360
1361 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
1362 if (empty($hidelabel)) {
1363 $out .= $langs->trans("RefOrLabel") . ' : ';
1364 } elseif ($hidelabel > 1) {
1365 $placeholder = $langs->trans("RefOrLabel");
1366 if ($hidelabel == 2) {
1367 $out .= img_picto($langs->trans("Search"), 'search');
1368 }
1369 }
1370 $out .= '<input type="text" class="' . $morecss . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '') . ' ' . (getDolGlobalString('THIRDPARTY_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
1371 if ($hidelabel == 3) {
1372 $out .= img_picto($langs->trans("Search"), 'search');
1373 }
1374
1375 $out .= ajax_event($htmlname, $events);
1376
1377 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/societe/ajax/company.php', $urloption, getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT'), 0, $ajaxoptions);
1378 } else {
1379 // Immediate load of all database
1380 $out .= $this->select_thirdparty_list($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, '', 0, $limit, $morecss, $moreparam, $multiple, $excludeids, $showcode);
1381 }
1382
1383 return $out;
1384 }
1385
1386
1387 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1388
1414 public function select_contact($socid, $selected = '', $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $nokeyifsocid = true, $showsoc = 0, $forcecombo = 0, $events = array(), $moreparam = '', $htmlid = '', $selected_input_value = '', $filter = '')
1415 {
1416 // phpcs:enable
1417
1418 global $conf, $langs;
1419
1420 $out = '';
1421
1422 $sav = getDolGlobalString('CONTACT_USE_SEARCH_TO_SELECT');
1423 if ($nokeyifsocid && $socid > 0) {
1424 $conf->global->CONTACT_USE_SEARCH_TO_SELECT = 0;
1425 }
1426
1427 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('CONTACT_USE_SEARCH_TO_SELECT') && !$forcecombo) {
1428 if (is_null($events)) {
1429 $events = array();
1430 }
1431
1432 require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1433
1434 // No immediate load of all database
1435 $placeholder = '';
1436 if ($selected && empty($selected_input_value)) {
1437 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1438 $contacttmp = new Contact($this->db);
1439 $contacttmp->fetch($selected);
1440 $selected_input_value = $contacttmp->getFullName($langs);
1441 unset($contacttmp);
1442 }
1443 if (!is_numeric($showempty)) {
1444 $placeholder = $showempty;
1445 }
1446
1447 // mode 1
1448 $urloption = 'htmlname=' . urlencode((string) (str_replace('.', '_', $htmlname))) . '&outjson=1&filter=' . urlencode((string) ($filter)) . (empty($exclude) ? '' : '&exclude=' . urlencode($exclude)) . ($showsoc ? '&showsoc=' . urlencode((string) ($showsoc)) : '');
1449
1450 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
1451
1452 $out .= '<input type="text" class="' . $morecss . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '') . ' ' . (getDolGlobalString('CONTACT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
1453
1454 $out .= ajax_event($htmlname, $events);
1455
1456 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/contact/ajax/contact.php', $urloption, getDolGlobalString('CONTACT_USE_SEARCH_TO_SELECT'), 0, $events);
1457 } else {
1458 // Immediate load of all database
1459 $multiple = false;
1460 $disableifempty = 0;
1461 $options_only = false;
1462 $limitto = '';
1463
1464 $out .= $this->selectcontacts($socid, $selected, $htmlname, $showempty, $exclude, $limitto, $showfunction, $morecss, $options_only, $showsoc, $forcecombo, $events, $moreparam, $htmlid, $multiple, $disableifempty);
1465 }
1466
1467 $conf->global->CONTACT_USE_SEARCH_TO_SELECT = $sav;
1468
1469 return $out;
1470 }
1471
1472
1473 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1474
1499 public function select_thirdparty_list($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $filterkey = '', $outputmode = 0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $multiple = false, $excludeids = array(), $showcode = 0)
1500 {
1501 // phpcs:enable
1502 global $user, $langs;
1503 global $hookmanager;
1504
1505 $out = '';
1506 $num = 0;
1507 $outarray = array();
1508
1509 if ($selected === '') {
1510 $selected = array();
1511 } elseif (!is_array($selected)) {
1512 $selected = array($selected);
1513 }
1514
1515 // Clean $filter that may contains sql conditions so sql code
1516 if (function_exists('testSqlAndScriptInject')) {
1517 if (testSqlAndScriptInject($filter, 3) > 0) {
1518 $filter = '';
1519 return 'SQLInjectionTryDetected';
1520 }
1521 }
1522
1523 if ($filter != '') { // If a filter was provided
1524 if (preg_match('/[\‍(\‍)]/', $filter)) {
1525 // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax.
1526 $errormsg = '';
1527 $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1);
1528
1529 // Redo clean $filter that may contains sql conditions so sql code
1530 if (function_exists('testSqlAndScriptInject')) {
1531 if (testSqlAndScriptInject($filter, 3) > 0) {
1532 $filter = '';
1533 return 'SQLInjectionTryDetected';
1534 }
1535 }
1536 } else {
1537 // If not, we do nothing. We already know that there is no parenthesis
1538 // TODO Disallow this case in a future.
1539 dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Syntax.", LOG_WARNING);
1540 }
1541 }
1542
1543 // We search companies
1544 $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.tva_intra, s.client, s.fournisseur, s.code_client, s.code_fournisseur";
1545 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1546 $sql .= ", s.address, s.zip, s.town";
1547 $sql .= ", dictp.code as country_code";
1548 }
1549 $sql .= " FROM " . $this->db->prefix() . "societe as s";
1550 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1551 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_country as dictp ON dictp.rowid = s.fk_pays";
1552 }
1553 if (!$user->hasRight('societe', 'client', 'voir')) {
1554 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
1555 }
1556 $sql .= " WHERE s.entity IN (" . getEntity('societe') . ")";
1557 if (!empty($user->socid)) {
1558 $sql .= " AND s.rowid = " . ((int) $user->socid);
1559 }
1560 if ($filter) {
1561 // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria()
1562 // if not, by testSqlAndScriptInject() only.
1563 $sql .= " AND (" . $filter . ")";
1564 }
1565 if (!$user->hasRight('societe', 'client', 'voir')) {
1566 $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
1567 }
1568 if (getDolGlobalString('COMPANY_HIDE_INACTIVE_IN_COMBOBOX')) {
1569 $sql .= " AND s.status <> 0";
1570 }
1571 if (!empty($excludeids)) {
1572 $sql .= " AND s.rowid NOT IN (" . $this->db->sanitize(implode(',', $excludeids)) . ")";
1573 }
1574 // Add where from hooks
1575 $parameters = array();
1576 $reshook = $hookmanager->executeHooks('selectThirdpartyListWhere', $parameters); // Note that $action and $object may have been modified by hook
1577 $sql .= $hookmanager->resPrint;
1578 // Add criteria
1579 if ($filterkey && $filterkey != '') {
1580 $sql .= " AND (";
1581 $prefix = !getDolGlobalString('COMPANY_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if COMPANY_DONOTSEARCH_ANYWHERE is on
1582 // For natural search
1583 $search_crit = explode(' ', $filterkey);
1584 $i = 0;
1585 if (count($search_crit) > 1) {
1586 $sql .= "(";
1587 }
1588 foreach ($search_crit as $crit) {
1589 if ($i > 0) {
1590 $sql .= " AND ";
1591 }
1592 $sql .= "(s.nom LIKE '" . $this->db->escape($prefix . $crit) . "%')";
1593 $i++;
1594 }
1595 if (count($search_crit) > 1) {
1596 $sql .= ")";
1597 }
1598 if (isModEnabled('barcode')) {
1599 $sql .= " OR s.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1600 }
1601 $sql .= " OR s.code_client LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.code_fournisseur LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1602 $sql .= " OR s.name_alias LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.tva_intra LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1603 $sql .= ")";
1604 }
1605 $sql .= $this->db->order("nom", "ASC");
1606 $sql .= $this->db->plimit($limit, 0);
1607
1608 // Build output string
1609 dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
1610 $resql = $this->db->query($sql);
1611 if ($resql) {
1612 // Construct $out and $outarray
1613 $out .= '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($moreparam ? ' ' . $moreparam : '') . ' name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . '>' . "\n";
1614
1615 $textifempty = (($showempty && !is_numeric($showempty)) ? $langs->trans($showempty) : '');
1616 if (getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
1617 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
1618 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
1619 if ($showempty && !is_numeric($showempty)) {
1620 $textifempty = $langs->trans($showempty);
1621 } else {
1622 $textifempty .= $langs->trans("All");
1623 }
1624 }
1625 if ($showempty) {
1626 $out .= '<option value="-1" data-html="' . dol_escape_htmltag('<span class="opacitymedium">' . ($textifempty ? $textifempty : '&nbsp;') . '</span>') . '">' . $textifempty . '</option>' . "\n";
1627 }
1628
1629 $companytemp = new Societe($this->db);
1630
1631 $num = $this->db->num_rows($resql);
1632 $i = 0;
1633 if ($num) {
1634 while ($i < $num) {
1635 $obj = $this->db->fetch_object($resql);
1636 $label = '';
1637 if ($showcode || getDolGlobalString('SOCIETE_ADD_REF_IN_LIST')) {
1638 if (($obj->client) && (!empty($obj->code_client))) {
1639 $label = $obj->code_client . ' - ';
1640 }
1641 if (($obj->fournisseur) && (!empty($obj->code_fournisseur))) {
1642 $label .= $obj->code_fournisseur . ' - ';
1643 }
1644 $label .= ' ' . $obj->name;
1645 } else {
1646 $label = $obj->name;
1647 }
1648
1649 if (!empty($obj->name_alias)) {
1650 $label .= ' (' . $obj->name_alias . ')';
1651 }
1652
1653 if (getDolGlobalString('SOCIETE_SHOW_VAT_IN_LIST') && !empty($obj->tva_intra)) {
1654 $label .= ' - '.$obj->tva_intra;
1655 }
1656
1657 $labelhtml = $label;
1658
1659 if ($showtype) {
1660 $companytemp->id = $obj->rowid;
1661 $companytemp->client = $obj->client;
1662 $companytemp->fournisseur = $obj->fournisseur;
1663 $tmptype = $companytemp->getTypeUrl(1, '', 0, 'span');
1664 if ($tmptype) {
1665 $labelhtml .= ' ' . $tmptype;
1666 }
1667
1668 if ($obj->client || $obj->fournisseur) {
1669 $label .= ' (';
1670 }
1671 if ($obj->client == 1 || $obj->client == 3) {
1672 $label .= $langs->trans("Customer");
1673 }
1674 if ($obj->client == 2 || $obj->client == 3) {
1675 $label .= ($obj->client == 3 ? ', ' : '') . $langs->trans("Prospect");
1676 }
1677 if ($obj->fournisseur) {
1678 $label .= ($obj->client ? ', ' : '') . $langs->trans("Supplier");
1679 }
1680 if ($obj->client || $obj->fournisseur) {
1681 $label .= ')';
1682 }
1683 }
1684
1685 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1686 $s = ($obj->address ? ' - ' . $obj->address : '') . ($obj->zip ? ' - ' . $obj->zip : '') . ($obj->town ? ' ' . $obj->town : '');
1687 if (!empty($obj->country_code)) {
1688 $s .= ', ' . $langs->trans('Country' . $obj->country_code);
1689 }
1690 $label .= $s;
1691 $labelhtml .= $s;
1692 }
1693
1694 if (empty($outputmode)) {
1695 if (in_array($obj->rowid, $selected)) {
1696 $out .= '<option value="' . $obj->rowid . '" selected data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1697 } else {
1698 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1699 }
1700 } else {
1701 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label, 'labelhtml' => $labelhtml));
1702 }
1703
1704 $i++;
1705 if (($i % 10) == 0) {
1706 $out .= "\n";
1707 }
1708 }
1709 }
1710 $out .= '</select>' . "\n";
1711 if (!$forcecombo) {
1712 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1713 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("COMPANY_USE_SEARCH_TO_SELECT"));
1714 }
1715 } else {
1716 dol_print_error($this->db);
1717 }
1718
1719 $this->result = array('nbofthirdparties' => $num);
1720
1721 if ($outputmode) {
1722 return $outarray;
1723 }
1724 return $out;
1725 }
1726
1727
1753 public function selectcontacts($socid, $selected = array(), $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $options_only = 0, $showsoc = 0, $forcecombo = 0, $events = array(), $moreparam = '', $htmlid = '', $multiple = false, $disableifempty = 0, $filter = '')
1754 {
1755 global $conf, $user, $langs, $hookmanager, $action;
1756
1757 $langs->load('companies');
1758
1759 if (empty($htmlid)) {
1760 $htmlid = $htmlname;
1761 }
1762 $num = 0;
1763 $out = '';
1764 $outarray = array();
1765
1766 if ($selected === '') {
1767 $selected = array();
1768 } elseif (!is_array($selected)) {
1769 $selected = array((int) $selected);
1770 }
1771
1772 // Clean $filter that may contains sql conditions so sql code
1773 if (function_exists('testSqlAndScriptInject')) {
1774 if (testSqlAndScriptInject($filter, 3) > 0) {
1775 $filter = '';
1776 return 'SQLInjectionTryDetected';
1777 }
1778 }
1779
1780 if ($filter != '') { // If a filter was provided
1781 if (preg_match('/[\‍(\‍)]/', $filter)) {
1782 // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax.
1783 $errormsg = '';
1784 $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1);
1785
1786 // Redo clean $filter that may contains sql conditions so sql code
1787 if (function_exists('testSqlAndScriptInject')) {
1788 if (testSqlAndScriptInject($filter, 3) > 0) {
1789 $filter = '';
1790 return 'SQLInjectionTryDetected';
1791 }
1792 }
1793 } else {
1794 // If not, we do nothing. We already know that there is no parenthesis
1795 // TODO Disallow this case in a future by returning an error here.
1796 dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Filter Syntax.", LOG_WARNING);
1797 }
1798 }
1799
1800 if (!is_object($hookmanager)) {
1801 include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
1802 $hookmanager = new HookManager($this->db);
1803 }
1804
1805 // We search third parties
1806 $sql = "SELECT sp.rowid, sp.lastname, sp.statut, sp.firstname, sp.poste, sp.email, sp.phone, sp.phone_perso, sp.phone_mobile, sp.town AS contact_town";
1807 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1808 $sql .= ", s.nom as company, s.town AS company_town";
1809 }
1810 $sql .= " FROM " . $this->db->prefix() . "socpeople as sp";
1811 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1812 $sql .= " LEFT OUTER JOIN " . $this->db->prefix() . "societe as s ON s.rowid=sp.fk_soc";
1813 }
1814 $sql .= " WHERE sp.entity IN (" . getEntity('contact') . ")";
1815 $sql .= " AND ((sp.fk_user_creat = ".((int) $user->id)." AND sp.priv = 1) OR sp.priv = 0)"; // check if this is a private contact
1816 if ($socid > 0 || $socid == -1) {
1817 $sql .= " AND sp.fk_soc = " . ((int) $socid);
1818 }
1819 if (getDolGlobalString('CONTACT_HIDE_INACTIVE_IN_COMBOBOX')) {
1820 $sql .= " AND sp.statut <> 0";
1821 }
1822 if ($filter) {
1823 // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria()
1824 // if not, by testSqlAndScriptInject() only.
1825 $sql .= " AND (" . $filter . ")";
1826 }
1827 // Add where from hooks
1828 $parameters = array();
1829 $reshook = $hookmanager->executeHooks('selectContactListWhere', $parameters); // Note that $action and $object may have been modified by hook
1830 $sql .= $hookmanager->resPrint;
1831 $sql .= " ORDER BY sp.lastname ASC";
1832
1833 dol_syslog(get_class($this) . "::selectcontacts", LOG_DEBUG);
1834 $resql = $this->db->query($sql);
1835 if ($resql) {
1836 $num = $this->db->num_rows($resql);
1837
1838 if ($htmlname != 'none' && !$options_only) {
1839 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlid . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . (($num || empty($disableifempty)) ? '' : ' disabled') . ($multiple ? 'multiple' : '') . ' ' . (!empty($moreparam) ? $moreparam : '') . '>';
1840 }
1841
1842 if ($showempty && !is_numeric($showempty)) {
1843 $textforempty = $showempty;
1844 $out .= '<option class="optiongrey" value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>' . $textforempty . '</option>';
1845 } else {
1846 if (($showempty == 1 || ($showempty == 3 && $num > 1)) && !$multiple) {
1847 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>&nbsp;</option>';
1848 }
1849 if ($showempty == 2) {
1850 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>-- ' . $langs->trans("Internal") . ' --</option>';
1851 }
1852 }
1853
1854 $i = 0;
1855 if ($num) {
1856 include_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1857 $contactstatic = new Contact($this->db);
1858
1859 while ($i < $num) {
1860 $obj = $this->db->fetch_object($resql);
1861
1862 // Set email (or phones) and town extended infos
1863 $extendedInfos = '';
1864 if (getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1865 $extendedInfos = array();
1866 $email = trim($obj->email);
1867 if (!empty($email)) {
1868 $extendedInfos[] = $email;
1869 } else {
1870 $phone = trim($obj->phone);
1871 $phone_perso = trim($obj->phone_perso);
1872 $phone_mobile = trim($obj->phone_mobile);
1873 if (!empty($phone)) {
1874 $extendedInfos[] = $phone;
1875 }
1876 if (!empty($phone_perso)) {
1877 $extendedInfos[] = $phone_perso;
1878 }
1879 if (!empty($phone_mobile)) {
1880 $extendedInfos[] = $phone_mobile;
1881 }
1882 }
1883 $contact_town = trim($obj->contact_town);
1884 $company_town = trim($obj->company_town);
1885 if (!empty($contact_town)) {
1886 $extendedInfos[] = $contact_town;
1887 } elseif (!empty($company_town)) {
1888 $extendedInfos[] = $company_town;
1889 }
1890 $extendedInfos = implode(' - ', $extendedInfos);
1891 if (!empty($extendedInfos)) {
1892 $extendedInfos = ' - ' . $extendedInfos;
1893 }
1894 }
1895
1896 $contactstatic->id = $obj->rowid;
1897 $contactstatic->lastname = $obj->lastname;
1898 $contactstatic->firstname = $obj->firstname;
1899 if ($obj->statut == 1) {
1900 $tmplabel = '';
1901 if ($htmlname != 'none') {
1902 $disabled = 0;
1903 if (is_array($exclude) && count($exclude) && in_array($obj->rowid, $exclude)) {
1904 $disabled = 1;
1905 }
1906 if (is_array($limitto) && count($limitto) && !in_array($obj->rowid, $limitto)) {
1907 $disabled = 1;
1908 }
1909 if (!empty($selected) && in_array($obj->rowid, $selected)) {
1910 $out .= '<option value="' . $obj->rowid . '"';
1911 if ($disabled) {
1912 $out .= ' disabled';
1913 }
1914 $out .= ' selected>';
1915
1916 $tmplabel = $contactstatic->getFullName($langs) . $extendedInfos;
1917 if ($showfunction && $obj->poste) {
1918 $tmplabel .= ' (' . $obj->poste . ')';
1919 }
1920 if (($showsoc > 0) && $obj->company) {
1921 $tmplabel .= ' - (' . $obj->company . ')';
1922 }
1923
1924 $out .= $tmplabel;
1925 $out .= '</option>';
1926 } else {
1927 $out .= '<option value="' . $obj->rowid . '"';
1928 if ($disabled) {
1929 $out .= ' disabled';
1930 }
1931 $out .= '>';
1932
1933 $tmplabel = $contactstatic->getFullName($langs) . $extendedInfos;
1934 if ($showfunction && $obj->poste) {
1935 $tmplabel .= ' (' . $obj->poste . ')';
1936 }
1937 if (($showsoc > 0) && $obj->company) {
1938 $tmplabel .= ' - (' . $obj->company . ')';
1939 }
1940
1941 $out .= $tmplabel;
1942 $out .= '</option>';
1943 }
1944 } else {
1945 if (in_array($obj->rowid, $selected)) {
1946 $tmplabel = $contactstatic->getFullName($langs) . $extendedInfos;
1947 if ($showfunction && $obj->poste) {
1948 $tmplabel .= ' (' . $obj->poste . ')';
1949 }
1950 if (($showsoc > 0) && $obj->company) {
1951 $tmplabel .= ' - (' . $obj->company . ')';
1952 }
1953
1954 $out .= $tmplabel;
1955 }
1956 }
1957
1958 if ($tmplabel != '') {
1959 array_push($outarray, array('key' => $obj->rowid, 'value' => $tmplabel, 'label' => $tmplabel, 'labelhtml' => $tmplabel));
1960 }
1961 }
1962 $i++;
1963 }
1964 } else {
1965 $labeltoshow = ($socid != -1) ? ($langs->trans($socid ? "NoContactDefinedForThirdParty" : "NoContactDefined")) : $langs->trans('SelectAThirdPartyFirst');
1966 $out .= '<option class="disabled" value="-1"' . (($showempty == 2 || $multiple) ? '' : ' selected') . ' disabled="disabled">';
1967 $out .= $labeltoshow;
1968 $out .= '</option>';
1969 }
1970
1971 $parameters = array(
1972 'socid' => $socid,
1973 'htmlname' => $htmlname,
1974 'resql' => $resql,
1975 'out' => &$out,
1976 'showfunction' => $showfunction,
1977 'showsoc' => $showsoc,
1978 );
1979
1980 $reshook = $hookmanager->executeHooks('afterSelectContactOptions', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1981
1982 if ($htmlname != 'none' && !$options_only) {
1983 $out .= '</select>';
1984 }
1985
1986 if ($conf->use_javascript_ajax && !$forcecombo && !$options_only) {
1987 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1988 $out .= ajax_combobox($htmlid, $events, getDolGlobalInt("CONTACT_USE_SEARCH_TO_SELECT"));
1989 }
1990
1991 $this->num = $num;
1992
1993 if ($options_only === 2) {
1994 // Return array of options
1995 return $outarray;
1996 } else {
1997 return $out;
1998 }
1999 } else {
2000 dol_print_error($this->db);
2001 return -1;
2002 }
2003 }
2004
2005
2006 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2007
2018 public function select_remises($selected, $htmlname, $filter, $socid, $maxvalue = 0)
2019 {
2020 // phpcs:enable
2021 global $langs, $conf;
2022
2023 // On recherche les remises
2024 $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
2025 $sql .= " re.description, re.fk_facture_source";
2026 $sql .= " FROM " . $this->db->prefix() . "societe_remise_except as re";
2027 $sql .= " WHERE re.fk_soc = " . (int) $socid;
2028 $sql .= " AND re.entity = " . $conf->entity;
2029 if ($filter) {
2030 $sql .= " AND " . $filter;
2031 }
2032 $sql .= " ORDER BY re.description ASC";
2033
2034 dol_syslog(get_class($this) . "::select_remises", LOG_DEBUG);
2035 $resql = $this->db->query($sql);
2036 if ($resql) {
2037 print '<select id="select_' . $htmlname . '" class="flat maxwidthonsmartphone" name="' . $htmlname . '">';
2038 $num = $this->db->num_rows($resql);
2039
2040 $qualifiedlines = $num;
2041
2042 $i = 0;
2043 if ($num) {
2044 print '<option value="0">&nbsp;</option>';
2045 while ($i < $num) {
2046 $obj = $this->db->fetch_object($resql);
2047 $desc = dol_trunc($obj->description, 40);
2048 if (preg_match('/\‍(CREDIT_NOTE\‍)/', $desc)) {
2049 $desc = preg_replace('/\‍(CREDIT_NOTE\‍)/', $langs->trans("CreditNote"), $desc);
2050 }
2051 if (preg_match('/\‍(DEPOSIT\‍)/', $desc)) {
2052 $desc = preg_replace('/\‍(DEPOSIT\‍)/', $langs->trans("Deposit"), $desc);
2053 }
2054 if (preg_match('/\‍(EXCESS RECEIVED\‍)/', $desc)) {
2055 $desc = preg_replace('/\‍(EXCESS RECEIVED\‍)/', $langs->trans("ExcessReceived"), $desc);
2056 }
2057 if (preg_match('/\‍(EXCESS PAID\‍)/', $desc)) {
2058 $desc = preg_replace('/\‍(EXCESS PAID\‍)/', $langs->trans("ExcessPaid"), $desc);
2059 }
2060
2061 $selectstring = '';
2062 if ($selected > 0 && $selected == $obj->rowid) {
2063 $selectstring = ' selected';
2064 }
2065
2066 $disabled = '';
2067 if ($maxvalue > 0 && $obj->amount_ttc > $maxvalue) {
2068 $qualifiedlines--;
2069 $disabled = ' disabled';
2070 }
2071
2072 if (getDolGlobalString('MAIN_SHOW_FACNUMBER_IN_DISCOUNT_LIST') && !empty($obj->fk_facture_source)) {
2073 $tmpfac = new Facture($this->db);
2074 if ($tmpfac->fetch($obj->fk_facture_source) > 0) {
2075 $desc = $desc . ' - ' . $tmpfac->ref;
2076 }
2077 }
2078
2079 print '<option value="' . $obj->rowid . '"' . $selectstring . $disabled . '>' . $desc . ' (' . price($obj->amount_ht) . ' ' . $langs->trans("HT") . ' - ' . price($obj->amount_ttc) . ' ' . $langs->trans("TTC") . ')</option>';
2080 $i++;
2081 }
2082 }
2083 print '</select>';
2084 print ajax_combobox('select_' . $htmlname);
2085
2086 return $qualifiedlines;
2087 } else {
2088 dol_print_error($this->db);
2089 return -1;
2090 }
2091 }
2092
2093
2094 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2095
2111 public function select_users($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0')
2112 {
2113 // phpcs:enable
2114 print $this->select_dolusers($selected, $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity);
2115 }
2116
2117 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2118
2143 public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '', $maxlength = 0, $showstatus = 0, $morefilter = '', $show_every = 0, $enableonlytext = '', $morecss = '', $notdisabled = 0, $outputmode = 0, $multiple = false, $forcecombo = 0)
2144 {
2145 // phpcs:enable
2146 global $conf, $user, $langs, $hookmanager;
2147 global $action;
2148
2149 // If no preselected user defined, we take current user
2150 if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) {
2151 $selected = $user->id;
2152 }
2153
2154 if ($selected === '') {
2155 $selected = array();
2156 } elseif (!is_array($selected)) {
2157 $selected = array($selected);
2158 }
2159
2160 $excludeUsers = null;
2161 $includeUsers = null;
2162
2163 // Exclude some users
2164 if (is_array($exclude)) {
2165 $excludeUsers = implode(",", $exclude);
2166 }
2167 // Include some uses
2168 if (is_array($include)) {
2169 $includeUsers = implode(",", $include);
2170 } elseif ($include == 'hierarchy') {
2171 // Build list includeUsers to have only hierarchy
2172 $includeUsers = implode(",", $user->getAllChildIds(0));
2173 } elseif ($include == 'hierarchyme') {
2174 // Build list includeUsers to have only hierarchy and current user
2175 $includeUsers = implode(",", $user->getAllChildIds(1));
2176 }
2177
2178 $num = 0;
2179
2180 $out = '';
2181 $outarray = array();
2182 $outarray2 = array();
2183
2184 // Do we want to show the label of entity into the combo list ?
2185 $showlabelofentity = isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1 && !empty($user->admin) && empty($user->entity);
2186 $userissuperadminentityone = isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && empty($user->entity);
2187
2188 // Forge request to select users
2189 $sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut as status, u.login, u.admin, u.entity, u.gender, u.photo";
2190 if ($showlabelofentity) {
2191 $sql .= ", e.label";
2192 }
2193 $sql .= " FROM " . $this->db->prefix() . "user as u";
2194 if ($showlabelofentity) {
2195 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid = u.entity";
2196 }
2197 // Condition here should be the same than into societe->getSalesRepresentatives().
2198 if ($userissuperadminentityone && $force_entity !== 'default') {
2199 if (!empty($force_entity)) {
2200 $sql .= " WHERE u.entity IN (0, " . $this->db->sanitize($force_entity) . ")";
2201 } else {
2202 $sql .= " WHERE u.entity IS NOT NULL";
2203 }
2204 } else {
2205 if (isModEnabled('multicompany') && getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE')) {
2206 $sql .= " WHERE u.rowid IN (SELECT ug.fk_user FROM ".$this->db->prefix()."usergroup_user as ug WHERE ug.entity IN (".getEntity('usergroup')."))";
2207 } else {
2208 $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
2209 }
2210 }
2211
2212 if (!empty($user->socid)) {
2213 $sql .= " AND u.fk_soc = " . ((int) $user->socid);
2214 }
2215 if (is_array($exclude) && $excludeUsers) {
2216 $sql .= " AND u.rowid NOT IN (" . $this->db->sanitize($excludeUsers) . ")";
2217 }
2218 if ($includeUsers) {
2219 $sql .= " AND u.rowid IN (" . $this->db->sanitize($includeUsers) . ")";
2220 }
2221 if (getDolGlobalString('USER_HIDE_INACTIVE_IN_COMBOBOX') || $notdisabled) {
2222 $sql .= " AND u.statut <> 0";
2223 }
2224 if (getDolGlobalString('USER_HIDE_NONEMPLOYEE_IN_COMBOBOX') || $notdisabled) {
2225 $sql .= " AND u.employee <> 0";
2226 }
2227 if (getDolGlobalString('USER_HIDE_EXTERNAL_IN_COMBOBOX') || $notdisabled) {
2228 $sql .= " AND u.fk_soc IS NULL";
2229 }
2230 if (!empty($morefilter)) {
2231 $sql .= " " . $morefilter;
2232 }
2233
2234 //Add hook to filter on user (for example on usergroup define in custom modules)
2235 $reshook = $hookmanager->executeHooks('addSQLWhereFilterOnSelectUsers', array(), $this, $action);
2236 if (!empty($reshook)) {
2237 $sql .= $hookmanager->resPrint;
2238 }
2239
2240 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) { // MAIN_FIRSTNAME_NAME_POSITION is 0 means firstname+lastname
2241 $sql .= " ORDER BY u.statut DESC, u.firstname ASC, u.lastname ASC";
2242 } else {
2243 $sql .= " ORDER BY u.statut DESC, u.lastname ASC, u.firstname ASC";
2244 }
2245
2246 dol_syslog(get_class($this) . "::select_dolusers", LOG_DEBUG);
2247
2248 $resql = $this->db->query($sql);
2249 if ($resql) {
2250 $num = $this->db->num_rows($resql);
2251 $i = 0;
2252 if ($num) {
2253 // do not use maxwidthonsmartphone by default. Set it by caller so auto size to 100% will work when not defined
2254 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : ' minwidth200') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
2255 if ($show_empty && !$multiple) {
2256 $textforempty = ' ';
2257 if (!empty($conf->use_javascript_ajax)) {
2258 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
2259 }
2260 if (!is_numeric($show_empty)) {
2261 $textforempty = $show_empty;
2262 }
2263 $out .= '<option class="optiongrey" value="' . ($show_empty < 0 ? $show_empty : -1) . '"' . ((empty($selected) || in_array(-1, $selected)) ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
2264
2265 $outarray[($show_empty < 0 ? $show_empty : -1)] = $textforempty;
2266 $outarray2[($show_empty < 0 ? $show_empty : -1)] = array(
2267 'id' => ($show_empty < 0 ? $show_empty : -1),
2268 'label' => $textforempty,
2269 'labelhtml' => $textforempty,
2270 'color' => '',
2271 'picto' => ''
2272 );
2273 }
2274 if ($show_every) {
2275 $out .= '<option value="-2"' . ((in_array(-2, $selected)) ? ' selected' : '') . '>-- ' . $langs->trans("Everybody") . ' --</option>' . "\n";
2276
2277 $outarray[-2] = '-- ' . $langs->trans("Everybody") . ' --';
2278 $outarray2[-2] = array(
2279 'id' => -2,
2280 'label' => '-- ' . $langs->trans("Everybody") . ' --',
2281 'labelhtml' => '-- ' . $langs->trans("Everybody") . ' --',
2282 'color' => '',
2283 'picto' => ''
2284 );
2285 }
2286
2287 $userstatic = new User($this->db);
2288
2289 while ($i < $num) {
2290 $obj = $this->db->fetch_object($resql);
2291
2292 $userstatic->id = $obj->rowid;
2293 $userstatic->lastname = $obj->lastname;
2294 $userstatic->firstname = $obj->firstname;
2295 $userstatic->photo = $obj->photo;
2296 $userstatic->status = $obj->status;
2297 $userstatic->entity = $obj->entity;
2298 $userstatic->admin = $obj->admin;
2299 $userstatic->gender = $obj->gender;
2300
2301 $disableline = '';
2302 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
2303 $disableline = ($enableonlytext ? $enableonlytext : '1');
2304 }
2305
2306 $labeltoshow = '';
2307 $labeltoshowhtml = '';
2308
2309 // $fullNameMode is 0=Lastname+Firstname (MAIN_FIRSTNAME_NAME_POSITION=1), 1=Firstname+Lastname (MAIN_FIRSTNAME_NAME_POSITION=0)
2310 $fullNameMode = 0;
2311 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) {
2312 $fullNameMode = 1; //Firstname+lastname
2313 }
2314 $labeltoshow .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2315 $labeltoshowhtml .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2316 if (empty($obj->firstname) && empty($obj->lastname)) {
2317 $labeltoshow .= $obj->login;
2318 $labeltoshowhtml .= $obj->login;
2319 }
2320
2321 // Complete name with a more info string like: ' (info1 - info2 - ...)'
2322 $moreinfo = '';
2323 $moreinfohtml = '';
2324 if (getDolGlobalString('MAIN_SHOW_LOGIN')) {
2325 $moreinfo .= ($moreinfo ? ' - ' : ' (');
2326 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(');
2327 $moreinfo .= $obj->login;
2328 $moreinfohtml .= $obj->login;
2329 }
2330 if ($showstatus >= 0) {
2331 if ($obj->status == 1 && $showstatus == 1) {
2332 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Enabled');
2333 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Enabled');
2334 }
2335 if ($obj->status == 0 && $showstatus == 1) {
2336 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Disabled');
2337 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Disabled');
2338 }
2339 }
2340 if ($showlabelofentity) {
2341 if (empty($obj->entity)) {
2342 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans("AllEntities");
2343 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans("AllEntities");
2344 } else {
2345 if ($obj->entity != $conf->entity) {
2346 $moreinfo .= ($moreinfo ? ' - ' : ' (') . ($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2347 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(').($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2348 }
2349 }
2350 }
2351 $moreinfo .= (!empty($moreinfo) ? ')' : '');
2352 $moreinfohtml .= (!empty($moreinfohtml) ? ')</span>' : '');
2353 if (!empty($disableline) && $disableline != '1') {
2354 // Add text from $enableonlytext parameter
2355 $moreinfo .= ' - ' . $disableline;
2356 $moreinfohtml .= ' - ' . $disableline;
2357 }
2358 $labeltoshow .= $moreinfo;
2359 $labeltoshowhtml .= $moreinfohtml;
2360
2361 $out .= '<option value="' . $obj->rowid . '"';
2362 if (!empty($disableline)) {
2363 $out .= ' disabled';
2364 }
2365 if ((!empty($selected[0]) && is_object($selected[0])) ? $selected[0]->id == $obj->rowid : in_array($obj->rowid, $selected)) {
2366 $out .= ' selected';
2367 }
2368 $out .= ' data-html="';
2369
2370 $outhtml = $userstatic->getNomUrl(-3, '', 0, 1, 24, 1, 'login', '', 1) . ' ';
2371 if ($showstatus >= 0 && $obj->status == 0) {
2372 $outhtml .= '<strike class="opacitymediumxxx">';
2373 }
2374 $outhtml .= $labeltoshowhtml;
2375 if ($showstatus >= 0 && $obj->status == 0) {
2376 $outhtml .= '</strike>';
2377 }
2378 $labeltoshowhtml = $outhtml;
2379
2380 $out .= dol_escape_htmltag($outhtml);
2381 $out .= '">';
2382 $out .= $labeltoshow;
2383 $out .= '</option>';
2384
2385 $outarray[$userstatic->id] = $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength) . $moreinfo;
2386 $outarray2[$userstatic->id] = array(
2387 'id' => $userstatic->id,
2388 'label' => $labeltoshow,
2389 'labelhtml' => $labeltoshowhtml,
2390 'color' => '',
2391 'picto' => ''
2392 );
2393
2394 $i++;
2395 }
2396 } else {
2397 $out .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '" disabled>';
2398 $out .= '<option value="">' . $langs->trans("None") . '</option>';
2399 }
2400 $out .= '</select>';
2401
2402 if ($num && !$forcecombo) {
2403 // Enhance with select2
2404 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2405 $out .= ajax_combobox($htmlname);
2406 }
2407 } else {
2408 dol_print_error($this->db);
2409 }
2410
2411 $this->num = $num;
2412
2413 if ($outputmode == 2) {
2414 return $outarray2;
2415 } elseif ($outputmode) {
2416 return $outarray;
2417 }
2418
2419 return $out;
2420 }
2421
2422
2423 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2446 public function select_dolusers_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = array(), $enableonly = array(), $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofuserid = array(), $listofcontactid = array(), $listofotherid = array())
2447 {
2448 // phpcs:enable
2449 global $langs;
2450
2451 $userstatic = new User($this->db);
2452 $out = '';
2453
2454 if (!empty($_SESSION['assignedtouser'])) {
2455 $assignedtouser = json_decode($_SESSION['assignedtouser'], true);
2456 if (!is_array($assignedtouser)) {
2457 $assignedtouser = array();
2458 }
2459 } else {
2460 $assignedtouser = array();
2461 }
2462 $nbassignetouser = count($assignedtouser);
2463
2464 //if ($nbassignetouser && $action != 'view') $out .= '<br>';
2465 if ($nbassignetouser) {
2466 $out .= '<ul class="attendees">';
2467 }
2468 $i = 0;
2469 $ownerid = 0;
2470 foreach ($assignedtouser as $key => $value) {
2471 if ($value['id'] == $ownerid) {
2472 continue;
2473 }
2474
2475 $out .= '<li>';
2476 $userstatic->fetch($value['id']);
2477 $out .= $userstatic->getNomUrl(-1);
2478 if ($i == 0) {
2479 $ownerid = $value['id'];
2480 $out .= ' (' . $langs->trans("Owner") . ')';
2481 }
2482 if ($nbassignetouser > 1 && $action != 'view') {
2483 $out .= ' <input type="image" style="border: 0px;" src="' . img_picto($langs->trans("Remove"), 'delete', '', 0, 1) . '" value="' . $userstatic->id . '" class="removedassigned reposition" id="removedassigned_' . $userstatic->id . '" name="removedassigned_' . $userstatic->id . '">';
2484 }
2485 // Show my availability
2486 if ($showproperties) {
2487 if ($ownerid == $value['id'] && is_array($listofuserid) && count($listofuserid) && in_array($ownerid, array_keys($listofuserid))) {
2488 $out .= '<div class="myavailability inline-block">';
2489 $out .= '<span class="hideonsmartphone">&nbsp;-&nbsp;<span class="opacitymedium">' . $langs->trans("Availability") . ':</span> </span><input id="transparency" class="paddingrightonly" ' . ($action == 'view' ? 'disabled' : '') . ' type="checkbox" name="transparency"' . ($listofuserid[$ownerid]['transparency'] ? ' checked' : '') . '><label for="transparency">' . $langs->trans("Busy") . '</label>';
2490 $out .= '</div>';
2491 }
2492 }
2493 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2494 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2495
2496 $out .= '</li>';
2497 $i++;
2498 }
2499 if ($nbassignetouser) {
2500 $out .= '</ul>';
2501 }
2502
2503 // Method with no ajax
2504 if ($action != 'view') {
2505 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassigned" value="">';
2506 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2507 $out .= 'jQuery(".removedassigned").click(function() { jQuery(".removedassignedhidden").val(jQuery(this).val()); });';
2508 $out .= 'jQuery(".assignedtouser").change(function() { console.log(jQuery(".assignedtouser option:selected").val());';
2509 $out .= ' if (jQuery(".assignedtouser option:selected").val() > 0) { jQuery("#' . $action . 'assignedtouser").attr("disabled", false); }';
2510 $out .= ' else { jQuery("#' . $action . 'assignedtouser").attr("disabled", true); }';
2511 $out .= '});';
2512 $out .= '})</script>';
2513 $out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2514 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtouser" name="' . $action . 'assignedtouser" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2515 $out .= '<br>';
2516 }
2517
2518 return $out;
2519 }
2520
2521 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2541 public function select_dolresources_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = array(), $enableonly = array(), $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofresourceid = array())
2542 {
2543 // phpcs:enable
2544 global $langs;
2545
2546 require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php';
2547 require_once DOL_DOCUMENT_ROOT.'/resource/class/dolresource.class.php';
2548 $formresources = new FormResource($this->db);
2549 $resourcestatic = new Dolresource($this->db);
2550
2551 $out = '';
2552 if (!empty($_SESSION['assignedtoresource'])) {
2553 $assignedtoresource = json_decode($_SESSION['assignedtoresource'], true);
2554 if (!is_array($assignedtoresource)) {
2555 $assignedtoresource = array();
2556 }
2557 } else {
2558 $assignedtoresource = array();
2559 }
2560 $nbassignetoresource = count($assignedtoresource);
2561
2562 //if ($nbassignetoresource && $action != 'view') $out .= '<br>';
2563 if ($nbassignetoresource) {
2564 $out .= '<ul class="attendees">';
2565 }
2566 $i = 0;
2567
2568 foreach ($assignedtoresource as $key => $value) {
2569 $out .= '<li>';
2570 $resourcestatic->fetch($value['id']);
2571 $out .= $resourcestatic->getNomUrl(-1);
2572 if ($nbassignetoresource > 1 && $action != 'view') {
2573 $out .= ' <input type="image" style="border: 0px;" src="' . img_picto($langs->trans("Remove"), 'delete', '', 0, 1) . '" value="' . $resourcestatic->id . '" class="removedassigned reposition" id="removedassignedresource_' . $resourcestatic->id . '" name="removedassignedresource_' . $resourcestatic->id . '">';
2574 }
2575 // Show my availability
2576 if ($showproperties) {
2577 if (is_array($listofresourceid) && count($listofresourceid)) {
2578 $out .= '<div class="myavailability inline-block">';
2579 $out .= '<span class="hideonsmartphone">&nbsp;-&nbsp;<span class="opacitymedium">' . $langs->trans("Availability") . ':</span> </span><input id="transparencyresource" class="paddingrightonly" ' . ($action == 'view' ? 'disabled' : '') . ' type="checkbox" name="transparency"' . ($listofresourceid[$value['id']]['transparency'] ? ' checked' : '') . '><label for="transparency">' . $langs->trans("Busy") . '</label>';
2580 $out .= '</div>';
2581 }
2582 }
2583 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2584 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2585
2586 $out .= '</li>';
2587 $i++;
2588 }
2589 if ($nbassignetoresource) {
2590 $out .= '</ul>';
2591 }
2592
2593 // Method with no ajax
2594 if ($action != 'view') {
2595 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassignedresource" value="">';
2596 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2597 $out .= 'jQuery(".removedassignedresource").click(function() { jQuery(".removedassignedresourcehidden").val(jQuery(this).val()); });';
2598 $out .= 'jQuery(".assignedtoresource").change(function() { console.log(jQuery(".assignedtoresource option:selected").val());';
2599 $out .= ' if (jQuery(".assignedtoresource option:selected").val() > 0) { jQuery("#' . $action . 'assignedtoresource").attr("disabled", false); }';
2600 $out .= ' else { jQuery("#' . $action . 'assignedtoresource").attr("disabled", true); }';
2601 $out .= '});';
2602 $out .= '})</script>';
2603
2604 $events = array();
2605 $out .= img_picto('', 'resource', 'class="pictofixedwidth"');
2606 $out .= $formresources->select_resource_list(0, $htmlname, [], 1, 1, 0, $events, array(), 2, 0);
2607 //$out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2608 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtoresource" name="' . $action . 'assignedtoresource" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2609 $out .= '<br>';
2610 }
2611
2612 return $out;
2613 }
2614
2615 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2616
2645 public function select_produits($selected = 0, $htmlname = 'productid', $filtertype = '', $limit = 0, $price_level = 0, $status = 1, $finished = 2, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $selected_combinations = null, $nooutput = 0, $status_purchase = -1)
2646 {
2647 // phpcs:enable
2648 global $langs, $conf;
2649
2650 $out = '';
2651
2652 // check parameters
2653 $price_level = (!empty($price_level) ? $price_level : 0);
2654 if (is_null($ajaxoptions)) {
2655 $ajaxoptions = array();
2656 }
2657
2658 if (strval($filtertype) === '' && (isModEnabled("product") || isModEnabled("service"))) {
2659 if (isModEnabled("product") && !isModEnabled('service')) {
2660 $filtertype = '0';
2661 } elseif (!isModEnabled('product') && isModEnabled("service")) {
2662 $filtertype = '1';
2663 }
2664 }
2665
2666 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
2667 $placeholder = '';
2668
2669 if ($selected && empty($selected_input_value)) {
2670 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2671 $producttmpselect = new Product($this->db);
2672 $producttmpselect->fetch($selected);
2673 $selected_input_value = $producttmpselect->ref;
2674 unset($producttmpselect);
2675 }
2676 // handle case where product or service module is disabled + no filter specified
2677 if ($filtertype == '') {
2678 if (!isModEnabled('product')) { // when product module is disabled, show services only
2679 $filtertype = 1;
2680 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
2681 $filtertype = 0;
2682 }
2683 }
2684 // mode=1 means customers products
2685 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=1&status=' . $status . '&status_purchase=' . $status_purchase . '&finished=' . $finished . '&hidepriceinlabel=' . $hidepriceinlabel . '&warehousestatus=' . $warehouseStatus;
2686 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
2687
2688 if (isModEnabled('variants') && is_array($selected_combinations)) {
2689 // Code to automatically insert with javascript the select of attributes under the select of product
2690 // when a parent of variant has been selected.
2691 $out .= '
2692 <!-- script to auto show attributes select tags if a variant was selected -->
2693 <script nonce="' . getNonce() . '">
2694 // auto show attributes fields
2695 selected = ' . json_encode($selected_combinations) . ';
2696 combvalues = {};
2697
2698 jQuery(document).ready(function () {
2699
2700 jQuery("input[name=\'prod_entry_mode\']").change(function () {
2701 if (jQuery(this).val() == \'free\') {
2702 jQuery(\'div#attributes_box\').empty();
2703 }
2704 });
2705
2706 jQuery("input#' . $htmlname . '").change(function () {
2707
2708 if (!jQuery(this).val()) {
2709 jQuery(\'div#attributes_box\').empty();
2710 return;
2711 }
2712
2713 console.log("A change has started. We get variants fields to inject html select");
2714
2715 jQuery.getJSON("' . DOL_URL_ROOT . '/variants/ajax/getCombinations.php", {
2716 id: jQuery(this).val()
2717 }, function (data) {
2718 jQuery(\'div#attributes_box\').empty();
2719
2720 jQuery.each(data, function (key, val) {
2721
2722 combvalues[val.id] = val.values;
2723
2724 var span = jQuery(document.createElement(\'div\')).css({
2725 \'display\': \'table-row\'
2726 });
2727
2728 span.append(
2729 jQuery(document.createElement(\'div\')).text(val.label).css({
2730 \'font-weight\': \'bold\',
2731 \'display\': \'table-cell\'
2732 })
2733 );
2734
2735 var html = jQuery(document.createElement(\'select\')).attr(\'name\', \'combinations[\' + val.id + \']\').css({
2736 \'margin-left\': \'15px\',
2737 \'white-space\': \'pre\'
2738 }).append(
2739 jQuery(document.createElement(\'option\')).val(\'\')
2740 );
2741
2742 jQuery.each(combvalues[val.id], function (key, val) {
2743 var tag = jQuery(document.createElement(\'option\')).val(val.id).html(val.value);
2744
2745 if (selected[val.fk_product_attribute] == val.id) {
2746 tag.attr(\'selected\', \'selected\');
2747 }
2748
2749 html.append(tag);
2750 });
2751
2752 span.append(html);
2753 jQuery(\'div#attributes_box\').append(span);
2754 });
2755 })
2756 });
2757
2758 ' . ($selected ? 'jQuery("input#' . $htmlname . '").change();' : '') . '
2759 });
2760 </script>
2761 ';
2762 }
2763
2764 if (empty($hidelabel)) {
2765 $out .= $langs->trans("RefOrLabel") . ' : ';
2766 } elseif ($hidelabel > 1) {
2767 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
2768 if ($hidelabel == 2) {
2769 $out .= img_picto($langs->trans("Search"), 'search');
2770 }
2771 }
2772 $out .= '<input type="text" class="minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
2773 if ($hidelabel == 3) {
2774 $out .= img_picto($langs->trans("Search"), 'search');
2775 }
2776 } else {
2777 $out .= $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus, $status_purchase);
2778 }
2779
2780 if (empty($nooutput)) {
2781 print $out;
2782 } else {
2783 return $out;
2784 }
2785 }
2786
2787 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2788
2804 public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 0, $showempty = '1', $morecss = '', $nooutput = '', $forcecombo = 0, $TProducts = [])
2805 {
2806 // phpcs:enable
2807 global $db;
2808
2809 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2810
2811 $error = 0;
2812 $out = '';
2813
2814 if (!$forcecombo) {
2815 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2816 $events = array();
2817 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
2818 }
2819
2820 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
2821
2822 $sql = 'SELECT b.rowid, b.ref, b.label, b.fk_product';
2823 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'bom_bom as b';
2824 $sql .= ' WHERE b.entity IN (' . getEntity('bom') . ')';
2825 if (!empty($status)) {
2826 $sql .= ' AND status = ' . (int) $status;
2827 }
2828 if (!empty($type)) {
2829 $sql .= ' AND bomtype = ' . (int) $type;
2830 }
2831 if (!empty($TProducts)) {
2832 $sql .= ' AND fk_product IN (' . $this->db->sanitize(implode(',', $TProducts)) . ')';
2833 }
2834 if (!empty($limit)) {
2835 $sql .= ' LIMIT ' . (int) $limit;
2836 }
2837 $resql = $db->query($sql);
2838 if ($resql) {
2839 if ($showempty) {
2840 $out .= '<option value="-1"';
2841 if (empty($selected)) {
2842 $out .= ' selected';
2843 }
2844 $out .= '>&nbsp;</option>';
2845 }
2846 while ($obj = $db->fetch_object($resql)) {
2847 $product = new Product($db);
2848 $res = $product->fetch($obj->fk_product);
2849 $out .= '<option value="' . $obj->rowid . '"';
2850 if ($obj->rowid == $selected) {
2851 $out .= 'selected';
2852 }
2853 $out .= '>' . $obj->ref . ' - ' . $product->label . ' - ' . $obj->label . '</option>';
2854 }
2855 } else {
2856 $error++;
2857 dol_print_error($db);
2858 }
2859 $out .= '</select>';
2860 if (empty($nooutput)) {
2861 print $out;
2862 } else {
2863 return $out;
2864 }
2865 }
2866
2867 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2868
2894 public function select_produits_list($selected = 0, $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = 'maxwidth500', $hidepriceinlabel = 0, $warehouseStatus = '', $status_purchase = -1)
2895 {
2896 // phpcs:enable
2897 global $langs;
2898 global $hookmanager;
2899
2900 $out = '';
2901 $outarray = array();
2902
2903 // Units
2904 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2905 $langs->load('other');
2906 }
2907
2908 $warehouseStatusArray = array();
2909 if (!empty($warehouseStatus)) {
2910 require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
2911 if (preg_match('/warehouseclosed/', $warehouseStatus)) {
2912 $warehouseStatusArray[] = Entrepot::STATUS_CLOSED;
2913 }
2914 if (preg_match('/warehouseopen/', $warehouseStatus)) {
2915 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL;
2916 }
2917 if (preg_match('/warehouseinternal/', $warehouseStatus)) {
2918 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL;
2919 }
2920 }
2921
2922 $selectFields = " p.rowid, p.ref, p.label, p.description, p.barcode, p.fk_country, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.default_vat_code, p.duration, p.fk_price_expression";
2923 if (count($warehouseStatusArray)) {
2924 $selectFieldsGrouped = ", sum(" . $this->db->ifsql("e.statut IS NULL", "0", "ps.reel") . ") as stock"; // e.statut is null if there is no record in stock
2925 } else {
2926 $selectFieldsGrouped = ", " . $this->db->ifsql("p.stock IS NULL", 0, "p.stock") . " AS stock";
2927 }
2928
2929 $sql = "SELECT ";
2930
2931 // Add select from hooks
2932 $parameters = array();
2933 $reshook = $hookmanager->executeHooks('selectProductsListSelect', $parameters); // Note that $action and $object may have been modified by hook
2934 if (empty($reshook)) {
2935 $sql .= $selectFields.$selectFieldsGrouped.$hookmanager->resPrint;
2936 } else {
2937 $sql .= $hookmanager->resPrint;
2938 }
2939
2940 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
2941 //Product category
2942 $sql .= ", (SELECT " . $this->db->prefix() . "categorie_product.fk_categorie
2943 FROM " . $this->db->prefix() . "categorie_product
2944 WHERE " . $this->db->prefix() . "categorie_product.fk_product=p.rowid
2945 LIMIT 1
2946 ) AS categorie_product_id ";
2947 }
2948
2949 //Price by customer
2950 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2951 $sql .= ', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
2952 $sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx, pcp.default_vat_code as custdefault_vat_code, pcp.ref_customer as custref';
2953 $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custdefault_vat_code, custref";
2954 }
2955 // Units
2956 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2957 $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units";
2958 $selectFields .= ', unit_long, unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units';
2959 }
2960
2961 // Multilang : we add translation
2962 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2963 $sql .= ", pl.label as label_translated";
2964 $sql .= ", pl.description as description_translated";
2965 $selectFields .= ", label_translated";
2966 $selectFields .= ", description_translated";
2967 }
2968 // Price by quantity
2969 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2970 $sql .= ", (SELECT pp.rowid FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid";
2971 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2972 $sql .= " AND price_level = " . ((int) $price_level);
2973 }
2974 $sql .= " ORDER BY date_price";
2975 $sql .= " DESC LIMIT 1) as price_rowid";
2976 $sql .= ", (SELECT pp.price_by_qty FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid"; // price_by_qty is 1 if some prices by qty exists in subtable
2977 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2978 $sql .= " AND price_level = " . ((int) $price_level);
2979 }
2980 $sql .= " ORDER BY date_price";
2981 $sql .= " DESC LIMIT 1) as price_by_qty";
2982 $selectFields .= ", price_rowid, price_by_qty";
2983 }
2984
2985 $sql .= " FROM ".$this->db->prefix()."product as p";
2986
2987 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_FORCE_INDEX')) {
2988 $sql .= " USE INDEX (" . $this->db->sanitize(getDolGlobalString('MAIN_PRODUCT_FORCE_INDEX')) . ")";
2989 }
2990
2991 // Add from (left join) from hooks
2992 $parameters = array();
2993 $reshook = $hookmanager->executeHooks('selectProductsListFrom', $parameters); // Note that $action and $object may have been modified by hook
2994 $sql .= $hookmanager->resPrint;
2995
2996 if (count($warehouseStatusArray)) {
2997 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_stock as ps on ps.fk_product = p.rowid";
2998 $sql .= " LEFT JOIN " . $this->db->prefix() . "entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (" . getEntity('stock') . ")";
2999 $sql .= ' AND e.statut IN (' . $this->db->sanitize($this->db->escape(implode(',', $warehouseStatusArray))) . ')'; // Return line if product is inside the selected stock. If not, an empty line will be returned so we will count 0.
3000 }
3001
3002 //Price by customer
3003 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
3004 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_customer_price as pcp ON pcp.fk_soc=" . ((int) $socid) . " AND pcp.fk_product=p.rowid";
3005 }
3006 // Units
3007 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3008 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3009 }
3010 // Multilang : we add translation
3011 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3012 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_lang as pl ON pl.fk_product = p.rowid ";
3013 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE') && !empty($socid)) {
3014 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
3015 $soc = new Societe($this->db);
3016 $result = $soc->fetch($socid);
3017 if ($result > 0 && !empty($soc->default_lang)) {
3018 $sql .= " AND pl.lang = '" . $this->db->escape($soc->default_lang) . "'";
3019 } else {
3020 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
3021 }
3022 } else {
3023 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
3024 }
3025 }
3026
3027 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
3028 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_attribute_combination pac ON pac.fk_product_child = p.rowid";
3029 }
3030
3031 $sql .= ' WHERE p.entity IN (' . getEntity('product') . ')';
3032
3033 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
3034 $sql .= " AND pac.rowid IS NULL";
3035 }
3036
3037 if ($finished == 0) {
3038 $sql .= " AND p.finished = " . ((int) $finished);
3039 } elseif ($finished == 1) {
3040 $sql .= " AND p.finished = ".((int) $finished);
3041 }
3042 if ($status >= 0) {
3043 $sql .= " AND p.tosell = ".((int) $status);
3044 }
3045 if ($status_purchase >= 0) {
3046 $sql .= " AND p.tobuy = " . ((int) $status_purchase);
3047 }
3048 // Filter by product type
3049 if (strval($filtertype) != '') {
3050 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3051 } elseif (!isModEnabled('product')) { // when product module is disabled, show services only
3052 $sql .= " AND p.fk_product_type = 1";
3053 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
3054 $sql .= " AND p.fk_product_type = 0";
3055 }
3056 // Add where from hooks
3057 $parameters = array();
3058 $reshook = $hookmanager->executeHooks('selectProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3059 $sql .= $hookmanager->resPrint;
3060 // Add criteria on ref/label
3061 if ($filterkey != '') {
3062 $sqlSupplierSearch= '';
3063
3064 $sql .= ' AND (';
3065 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3066 // For natural search
3067 $search_crit = explode(' ', $filterkey);
3068 $i = 0;
3069 if (count($search_crit) > 1) {
3070 $sql .= "(";
3071 }
3072 foreach ($search_crit as $crit) {
3073 if ($i > 0) {
3074 $sql .= " AND ";
3075 }
3076 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3077 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3078 $sql .= " OR pl.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3079 }
3080 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
3081 $sql .= " OR pcp.ref_customer LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3082 }
3083 if (getDolGlobalString('PRODUCT_AJAX_SEARCH_ON_DESCRIPTION')) {
3084 $sql .= " OR p.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3085 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3086 $sql .= " OR pl.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3087 }
3088 }
3089
3090 // include search in supplier ref
3091 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
3092 $sqlSupplierSearch .= !empty($sqlSupplierSearch) ? ' AND ':'';
3093 $sqlSupplierSearch .= " pfp.ref_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3094 }
3095 $sql .= ")";
3096 $i++;
3097 }
3098 if (count($search_crit) > 1) {
3099 $sql .= ")";
3100 }
3101 if (isModEnabled('barcode')) {
3102 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3103 }
3104
3105 // include search in supplier ref
3106 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
3107 $sql .= " OR EXISTS (SELECT pfp.fk_product FROM " . $this->db->prefix() . "product_fournisseur_price as pfp WHERE p.rowid = pfp.fk_product";
3108 $sql .= " AND (";
3109 $sql .= $sqlSupplierSearch;
3110 $sql .= "))";
3111 }
3112
3113 $sql .= ')';
3114 }
3115 if (count($warehouseStatusArray)) {
3116 $sql .= " GROUP BY " . $selectFields;
3117 }
3118
3119 //Sort by category
3120 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
3121 $sql .= " ORDER BY categorie_product_id ";
3122 //ASC OR DESC order
3123 (getDolGlobalInt('PRODUCT_SORT_BY_CATEGORY') == 1) ? $sql .= "ASC" : $sql .= "DESC";
3124 } else {
3125 $sql .= $this->db->order("p.ref");
3126 }
3127
3128 $sql .= $this->db->plimit($limit, 0);
3129
3130 // Build output string
3131 dol_syslog(get_class($this) . "::select_produits_list search products", LOG_DEBUG);
3132 $result = $this->db->query($sql);
3133 if ($result) {
3134 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3135 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3136 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3137
3138 $num = $this->db->num_rows($result);
3139
3140 $events = array();
3141
3142 if (!$forcecombo) {
3143 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
3144 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
3145 }
3146
3147 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
3148
3149 $textifempty = '';
3150 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
3151 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
3152 if (getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3153 if ($showempty && !is_numeric($showempty)) {
3154 $textifempty = $langs->trans($showempty);
3155 } else {
3156 $textifempty .= $langs->trans("All");
3157 }
3158 } else {
3159 if ($showempty && !is_numeric($showempty)) {
3160 $textifempty = $langs->trans($showempty);
3161 }
3162 }
3163 if ($showempty) {
3164 $out .= '<option value="-1" selected>' . ($textifempty ? $textifempty : '&nbsp;') . '</option>';
3165 }
3166
3167 $i = 0;
3168 while ($num && $i < $num) {
3169 $opt = '';
3170 $optJson = array();
3171 $objp = $this->db->fetch_object($result);
3172
3173 if ((getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) && !empty($objp->price_by_qty) && $objp->price_by_qty == 1) { // Price by quantity will return many prices for the same product
3174 $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type";
3175 $sql .= " FROM " . $this->db->prefix() . "product_price_by_qty";
3176 $sql .= " WHERE fk_product_price = " . ((int) $objp->price_rowid);
3177 $sql .= " ORDER BY quantity ASC";
3178
3179 dol_syslog(get_class($this) . "::select_produits_list search prices by qty", LOG_DEBUG);
3180 $result2 = $this->db->query($sql);
3181 if ($result2) {
3182 $nb_prices = $this->db->num_rows($result2);
3183 $j = 0;
3184 while ($nb_prices && $j < $nb_prices) {
3185 $objp2 = $this->db->fetch_object($result2);
3186
3187 $objp->price_by_qty_rowid = $objp2->rowid;
3188 $objp->price_by_qty_price_base_type = $objp2->price_base_type;
3189 $objp->price_by_qty_quantity = $objp2->quantity;
3190 $objp->price_by_qty_unitprice = $objp2->unitprice;
3191 $objp->price_by_qty_remise_percent = $objp2->remise_percent;
3192 // For backward compatibility
3193 $objp->quantity = $objp2->quantity;
3194 $objp->price = $objp2->price;
3195 $objp->unitprice = $objp2->unitprice;
3196 $objp->remise_percent = $objp2->remise_percent;
3197
3198 //$objp->tva_tx is not overwritten by $objp2 value
3199 //$objp->default_vat_code is not overwritten by $objp2 value
3200
3201 $this->constructProductListOption($objp, $opt, $optJson, 0, $selected, $hidepriceinlabel, $filterkey);
3202
3203 $j++;
3204
3205 // Add new entry
3206 // "key" value of json key array is used by jQuery automatically as selected value
3207 // "label" value of json key array is used by jQuery automatically as text for combo box
3208 $out .= $opt;
3209 array_push($outarray, $optJson);
3210 }
3211 }
3212 } else {
3213 if (isModEnabled('dynamicprices') && !empty($objp->fk_price_expression)) {
3214 $price_product = new Product($this->db);
3215 $price_product->fetch($objp->rowid, '', '', 1);
3216
3217 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3218 $priceparser = new PriceParser($this->db);
3219 $price_result = $priceparser->parseProduct($price_product);
3220 if ($price_result >= 0) {
3221 $objp->price = $price_result;
3222 $objp->unitprice = $price_result;
3223 //Calculate the VAT
3224 $objp->price_ttc = (float) price2num($objp->price) * (1 + ($objp->tva_tx / 100));
3225 $objp->price_ttc = price2num($objp->price_ttc, 'MU');
3226 }
3227 }
3228
3229 $this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected, $hidepriceinlabel, $filterkey);
3230 // Add new entry
3231 // "key" value of json key array is used by jQuery automatically as selected value
3232 // "label" value of json key array is used by jQuery automatically as text for combo box
3233 $out .= $opt;
3234 array_push($outarray, $optJson);
3235 }
3236
3237 $i++;
3238 }
3239
3240 $out .= '</select>';
3241
3242 $this->db->free($result);
3243
3244 if (empty($outputmode)) {
3245 return $out;
3246 }
3247
3248 return $outarray;
3249 } else {
3250 dol_print_error($this->db);
3251 }
3252
3253 return '';
3254 }
3255
3271 protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0)
3272 {
3273 global $langs, $conf, $user;
3274 global $hookmanager;
3275
3276 $outkey = '';
3277 $outval = '';
3278 $outref = '';
3279 $outlabel = '';
3280 $outlabel_translated = '';
3281 $outdesc = '';
3282 $outdesc_translated = '';
3283 $outbarcode = '';
3284 $outorigin = '';
3285 $outtype = '';
3286 $outprice_ht = '';
3287 $outprice_ttc = '';
3288 $outpricebasetype = '';
3289 $outtva_tx = '';
3290 $outdefault_vat_code = '';
3291 $outqty = 1;
3292 $outdiscount = 0;
3293
3294 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3295
3296 $label = $objp->label;
3297 if (!empty($objp->label_translated)) {
3298 $label = $objp->label_translated;
3299 }
3300 if (!empty($filterkey) && $filterkey != '') {
3301 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3302 }
3303
3304 $outkey = $objp->rowid;
3305 $outref = $objp->ref;
3306 $outrefcust = empty($objp->custref) ? '' : $objp->custref;
3307 $outlabel = $objp->label;
3308 $outdesc = $objp->description;
3309 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3310 $outlabel_translated = $objp->label_translated;
3311 $outdesc_translated = $objp->description_translated;
3312 }
3313 $outbarcode = $objp->barcode;
3314 $outorigin = $objp->fk_country;
3315 $outpbq = empty($objp->price_by_qty_rowid) ? '' : $objp->price_by_qty_rowid;
3316
3317 $outtype = $objp->fk_product_type;
3318 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3319 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3320
3321 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3322 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
3323 }
3324
3325 // Units
3326 $outvalUnits = '';
3327 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3328 if (!empty($objp->unit_short)) {
3329 $outvalUnits .= ' - ' . $objp->unit_short;
3330 }
3331 }
3332 if (getDolGlobalString('PRODUCT_SHOW_DIMENSIONS_IN_COMBO')) {
3333 if (!empty($objp->weight) && $objp->weight_units !== null) {
3334 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3335 $outvalUnits .= ' - ' . $unitToShow;
3336 }
3337 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3338 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3339 $outvalUnits .= ' - ' . $unitToShow;
3340 }
3341 if (!empty($objp->surface) && $objp->surface_units !== null) {
3342 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3343 $outvalUnits .= ' - ' . $unitToShow;
3344 }
3345 if (!empty($objp->volume) && $objp->volume_units !== null) {
3346 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3347 $outvalUnits .= ' - ' . $unitToShow;
3348 }
3349 }
3350 if ($outdurationvalue && $outdurationunit) {
3351 $da = array(
3352 'h' => $langs->trans('Hour'),
3353 'd' => $langs->trans('Day'),
3354 'w' => $langs->trans('Week'),
3355 'm' => $langs->trans('Month'),
3356 'y' => $langs->trans('Year')
3357 );
3358 if (isset($da[$outdurationunit])) {
3359 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3360 }
3361 }
3362
3363 $opt = '<option value="' . $objp->rowid . '"';
3364 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
3365 if (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0) {
3366 $opt .= ' pbq="' . $objp->price_by_qty_rowid . '" data-pbq="' . $objp->price_by_qty_rowid . '" data-pbqup="' . $objp->price_by_qty_unitprice . '" data-pbqbase="' . $objp->price_by_qty_price_base_type . '" data-pbqqty="' . $objp->price_by_qty_quantity . '" data-pbqpercent="' . $objp->price_by_qty_remise_percent . '"';
3367 }
3368 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3369 if ($user->hasRight('stock', 'lire')) {
3370 if ($objp->stock > 0) {
3371 $opt .= ' class="product_line_stock_ok"';
3372 } elseif ($objp->stock <= 0) {
3373 $opt .= ' class="product_line_stock_too_low"';
3374 }
3375 }
3376 }
3377 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
3378 $opt .= ' data-labeltrans="' . $outlabel_translated . '"';
3379 $opt .= ' data-desctrans="' . dol_escape_htmltag($outdesc_translated) . '"';
3380 }
3381 $opt .= '>';
3382 $opt .= $objp->ref;
3383 if (!empty($objp->custref)) {
3384 $opt .= ' (' . $objp->custref . ')';
3385 }
3386 if ($outbarcode) {
3387 $opt .= ' (' . $outbarcode . ')';
3388 }
3389 $opt .= ' - ' . dol_trunc($label, $maxlengtharticle);
3390 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3391 $opt .= ' (' . getCountry($outorigin, 1) . ')';
3392 }
3393
3394 $objRef = $objp->ref;
3395 if (!empty($objp->custref)) {
3396 $objRef .= ' (' . $objp->custref . ')';
3397 }
3398 if (!empty($filterkey) && $filterkey != '') {
3399 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3400 }
3401 $outval .= $objRef;
3402 if ($outbarcode) {
3403 $outval .= ' (' . $outbarcode . ')';
3404 }
3405 $outval .= ' - ' . dol_trunc($label, $maxlengtharticle);
3406 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3407 $outval .= ' (' . getCountry($outorigin, 1) . ')';
3408 }
3409
3410 // Units
3411 $opt .= $outvalUnits;
3412 $outval .= $outvalUnits;
3413
3414 $found = 0;
3415
3416 // Multiprice
3417 // If we need a particular price level (from 1 to n)
3418 if (empty($hidepriceinlabel) && $price_level >= 1 && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3419 $sql = "SELECT price, price_ttc, price_base_type, tva_tx, default_vat_code";
3420 $sql .= " FROM " . $this->db->prefix() . "product_price";
3421 $sql .= " WHERE fk_product = " . ((int) $objp->rowid);
3422 $sql .= " AND entity IN (" . getEntity('productprice') . ")";
3423 $sql .= " AND price_level = " . ((int) $price_level);
3424 $sql .= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid.
3425 $sql .= " LIMIT 1";
3426
3427 dol_syslog(get_class($this) . '::constructProductListOption search price for product ' . $objp->rowid . ' AND level ' . $price_level, LOG_DEBUG);
3428 $result2 = $this->db->query($sql);
3429 if ($result2) {
3430 $objp2 = $this->db->fetch_object($result2);
3431 if ($objp2) {
3432 $found = 1;
3433 if ($objp2->price_base_type == 'HT') {
3434 $opt .= ' - ' . price($objp2->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3435 $outval .= ' - ' . price($objp2->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3436 } else {
3437 $opt .= ' - ' . price($objp2->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3438 $outval .= ' - ' . price($objp2->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3439 }
3440 $outprice_ht = price($objp2->price);
3441 $outprice_ttc = price($objp2->price_ttc);
3442 $outpricebasetype = $objp2->price_base_type;
3443 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
3444 $outtva_tx = $objp2->tva_tx; // We use the vat rate on line of multiprice
3445 $outdefault_vat_code = $objp2->default_vat_code; // We use the vat code on line of multiprice
3446 } else {
3447 $outtva_tx = $objp->tva_tx; // We use the vat rate of product, not the one on line of multiprice
3448 $outdefault_vat_code = $objp->default_vat_code; // We use the vat code or product, not the one on line of multiprice
3449 }
3450 }
3451 } else {
3452 dol_print_error($this->db);
3453 }
3454 }
3455
3456 // Price by quantity
3457 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1 && (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3458 $found = 1;
3459 $outqty = $objp->quantity;
3460 $outdiscount = $objp->remise_percent;
3461 if ($objp->quantity == 1) {
3462 $opt .= ' - ' . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/";
3463 $outval .= ' - ' . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/";
3464 $opt .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3465 $outval .= $langs->transnoentities("Unit");
3466 } else {
3467 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3468 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3469 $opt .= $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3470 $outval .= $langs->transnoentities("Units");
3471 }
3472
3473 $outprice_ht = price($objp->unitprice);
3474 $outprice_ttc = price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
3475 $outpricebasetype = $objp->price_base_type;
3476 $outtva_tx = $objp->tva_tx; // This value is the value on product when constructProductListOption is called by select_produits_list even if other field $objp-> are from table price_by_qty
3477 $outdefault_vat_code = $objp->default_vat_code; // This value is the value on product when constructProductListOption is called by select_produits_list even if other field $objp-> are from table price_by_qty
3478 }
3479 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1) {
3480 $opt .= " (" . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3481 $outval .= " (" . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3482 }
3483 if (empty($hidepriceinlabel) && !empty($objp->remise_percent) && $objp->remise_percent >= 1) {
3484 $opt .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3485 $outval .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3486 }
3487
3488 // Price by customer
3489 if (empty($hidepriceinlabel) && getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
3490 if (!empty($objp->idprodcustprice)) {
3491 $found = 1;
3492
3493 if ($objp->custprice_base_type == 'HT') {
3494 $opt .= ' - ' . price($objp->custprice, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3495 $outval .= ' - ' . price($objp->custprice, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3496 } else {
3497 $opt .= ' - ' . price($objp->custprice_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3498 $outval .= ' - ' . price($objp->custprice_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3499 }
3500
3501 $outprice_ht = price($objp->custprice);
3502 $outprice_ttc = price($objp->custprice_ttc);
3503 $outpricebasetype = $objp->custprice_base_type;
3504 $outtva_tx = $objp->custtva_tx;
3505 $outdefault_vat_code = $objp->custdefault_vat_code;
3506 }
3507 }
3508
3509 // If level no defined or multiprice not found, we used the default price
3510 if (empty($hidepriceinlabel) && !$found) {
3511 if ($objp->price_base_type == 'HT') {
3512 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3513 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3514 } else {
3515 $opt .= ' - ' . price($objp->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3516 $outval .= ' - ' . price($objp->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3517 }
3518 $outprice_ht = price($objp->price);
3519 $outprice_ttc = price($objp->price_ttc);
3520 $outpricebasetype = $objp->price_base_type;
3521 $outtva_tx = $objp->tva_tx;
3522 $outdefault_vat_code = $objp->default_vat_code;
3523 }
3524
3525 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3526 if ($user->hasRight('stock', 'lire')) {
3527 $opt .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'), 0, $langs, 0, 0);
3528
3529 if ($objp->stock > 0) {
3530 $outval .= ' - <span class="product_line_stock_ok">';
3531 } elseif ($objp->stock <= 0) {
3532 $outval .= ' - <span class="product_line_stock_too_low">';
3533 }
3534 $outval .= $langs->transnoentities("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3535 $outval .= '</span>';
3536 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3537 $langs->load("stocks");
3538
3539 $tmpproduct = new Product($this->db);
3540 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3541 $tmpproduct->load_virtual_stock();
3542 $virtualstock = $tmpproduct->stock_theorique;
3543
3544 $opt .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3545
3546 $outval .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3547 if ($virtualstock > 0) {
3548 $outval .= '<span class="product_line_stock_ok">';
3549 } elseif ($virtualstock <= 0) {
3550 $outval .= '<span class="product_line_stock_too_low">';
3551 }
3552 $outval .= $virtualstock;
3553 $outval .= '</span>';
3554
3555 unset($tmpproduct);
3556 }
3557 }
3558 }
3559
3560 $parameters = array('objp' => $objp);
3561 $reshook = $hookmanager->executeHooks('constructProductListOption', $parameters); // Note that $action and $object may have been modified by hook
3562 if (empty($reshook)) {
3563 $opt .= $hookmanager->resPrint;
3564 } else {
3565 $opt = $hookmanager->resPrint;
3566 }
3567
3568 $opt .= "</option>\n";
3569 $optJson = array(
3570 'key' => $outkey,
3571 'value' => $outref,
3572 'label' => $outval,
3573 'label2' => $outlabel,
3574 'desc' => $outdesc,
3575 'type' => $outtype,
3576 'price_ht' => price2num($outprice_ht),
3577 'price_ttc' => price2num($outprice_ttc),
3578 'price_ht_locale' => price(price2num($outprice_ht)),
3579 'price_ttc_locale' => price(price2num($outprice_ttc)),
3580 'pricebasetype' => $outpricebasetype,
3581 'tva_tx' => $outtva_tx,
3582 'default_vat_code' => $outdefault_vat_code,
3583 'qty' => $outqty,
3584 'discount' => $outdiscount,
3585 'duration_value' => $outdurationvalue,
3586 'duration_unit' => $outdurationunit,
3587 'pbq' => $outpbq,
3588 'labeltrans' => $outlabel_translated,
3589 'desctrans' => $outdesc_translated,
3590 'ref_customer' => $outrefcust
3591 );
3592 }
3593
3594 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3595
3611 public function select_produits_fournisseurs($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $ajaxoptions = array(), $hidelabel = 0, $alsoproductwithnosupplierprice = 0, $morecss = '', $placeholder = '')
3612 {
3613 // phpcs:enable
3614 global $langs, $conf;
3615 global $price_level, $status, $finished;
3616
3617 if (!isset($status)) {
3618 $status = 1;
3619 }
3620
3621 $selected_input_value = '';
3622 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3623 if ($selected > 0) {
3624 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3625 $producttmpselect = new Product($this->db);
3626 $producttmpselect->fetch($selected);
3627 $selected_input_value = $producttmpselect->ref;
3628 unset($producttmpselect);
3629 }
3630
3631 // mode=2 means suppliers products
3632 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=2&status=' . $status . '&finished=' . $finished . '&alsoproductwithnosupplierprice=' . $alsoproductwithnosupplierprice;
3633 print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT'), 0, $ajaxoptions);
3634
3635 print($hidelabel ? '' : $langs->trans("RefOrLabel") . ' : ') . '<input type="text" class="'.$morecss.'" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . $placeholder . '"' : '') . '>';
3636 } else {
3637 print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', $status, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder);
3638 }
3639 }
3640
3641 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3642
3661 public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '', $showstockinlist = 0, $placeholder = '')
3662 {
3663 // phpcs:enable
3664 global $langs, $conf, $user;
3665 global $hookmanager;
3666
3667 $out = '';
3668 $outarray = array();
3669
3670 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3671
3672 $langs->load('stocks');
3673 // Units
3674 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3675 $langs->load('other');
3676 }
3677
3678 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, p.fk_product_type, p.stock, p.tva_tx as tva_tx_sale, p.default_vat_code as default_vat_code_sale,";
3679 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice, pfp.barcode";
3680 $sql .= ", pfp.multicurrency_code, pfp.multicurrency_unitprice";
3681 $sql .= ", pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.default_vat_code, pfp.fk_soc, s.nom as name";
3682 $sql .= ", pfp.supplier_reputation";
3683 // if we use supplier description of the products
3684 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3685 $sql .= ", pfp.desc_fourn as description";
3686 } else {
3687 $sql .= ", p.description";
3688 }
3689 // Units
3690 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3691 $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units";
3692 }
3693 $sql .= " FROM " . $this->db->prefix() . "product as p";
3694 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (" . getEntity('product') . ") )";
3695 if ($socid > 0) {
3696 $sql .= " AND pfp.fk_soc = " . ((int) $socid);
3697 }
3698 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3699 // Units
3700 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3701 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3702 }
3703 $sql .= " WHERE p.entity IN (" . getEntity('product') . ")";
3704 if ($statut != -1) {
3705 $sql .= " AND p.tobuy = " . ((int) $statut);
3706 }
3707 if (strval($filtertype) != '') {
3708 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3709 }
3710 if (!empty($filtre)) {
3711 $sql .= " " . $filtre;
3712 }
3713 // Add where from hooks
3714 $parameters = array();
3715 $reshook = $hookmanager->executeHooks('selectSuppliersProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3716 $sql .= $hookmanager->resPrint;
3717 // Add criteria on ref/label
3718 if ($filterkey != '') {
3719 $sql .= ' AND (';
3720 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3721 // For natural search
3722 $search_crit = explode(' ', $filterkey);
3723 $i = 0;
3724 if (count($search_crit) > 1) {
3725 $sql .= "(";
3726 }
3727 foreach ($search_crit as $crit) {
3728 if ($i > 0) {
3729 $sql .= " AND ";
3730 }
3731 $sql .= "(pfp.ref_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3732 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3733 $sql .= " OR pfp.desc_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3734 }
3735 $sql .= ")";
3736 $i++;
3737 }
3738 if (count($search_crit) > 1) {
3739 $sql .= ")";
3740 }
3741 if (isModEnabled('barcode')) {
3742 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3743 $sql .= " OR pfp.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3744 }
3745 $sql .= ')';
3746 }
3747 $sql .= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC";
3748 $sql .= $this->db->plimit($limit, 0);
3749
3750 // Build output string
3751
3752 dol_syslog(get_class($this) . "::select_produits_fournisseurs_list", LOG_DEBUG);
3753 $result = $this->db->query($sql);
3754 if ($result) {
3755 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3756 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3757
3758 $num = $this->db->num_rows($result);
3759
3760 //$out.='<select class="flat" id="select'.$htmlname.'" name="'.$htmlname.'">'; // remove select to have id same with combo and ajax
3761 $out .= '<select class="flat ' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '">';
3762 if (!$selected) {
3763 $out .= '<option value="-1" selected>' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3764 } else {
3765 $out .= '<option value="-1">' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3766 }
3767
3768 $i = 0;
3769 while ($i < $num) {
3770 $objp = $this->db->fetch_object($result);
3771
3772 if (is_null($objp->idprodfournprice)) {
3773 // There is no supplier price found, we will use the vat rate for sale
3774 $objp->tva_tx = $objp->tva_tx_sale;
3775 $objp->default_vat_code = $objp->default_vat_code_sale;
3776 }
3777
3778 $outkey = $objp->idprodfournprice; // id in table of price
3779 if (!$outkey && $alsoproductwithnosupplierprice) {
3780 $outkey = 'idprod_' . $objp->rowid; // id of product
3781 }
3782
3783 $outref = $objp->ref;
3784 $outbarcode = $objp->barcode;
3785 $outqty = 1;
3786 $outdiscount = 0;
3787 $outtype = $objp->fk_product_type;
3788 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3789 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3790
3791 // Units
3792 $outvalUnits = '';
3793 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3794 if (!empty($objp->unit_short)) {
3795 $outvalUnits .= ' - ' . $objp->unit_short;
3796 }
3797 if (!empty($objp->weight) && $objp->weight_units !== null) {
3798 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3799 $outvalUnits .= ' - ' . $unitToShow;
3800 }
3801 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3802 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3803 $outvalUnits .= ' - ' . $unitToShow;
3804 }
3805 if (!empty($objp->surface) && $objp->surface_units !== null) {
3806 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3807 $outvalUnits .= ' - ' . $unitToShow;
3808 }
3809 if (!empty($objp->volume) && $objp->volume_units !== null) {
3810 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3811 $outvalUnits .= ' - ' . $unitToShow;
3812 }
3813 if ($outdurationvalue && $outdurationunit) {
3814 $da = array(
3815 'h' => $langs->trans('Hour'),
3816 'd' => $langs->trans('Day'),
3817 'w' => $langs->trans('Week'),
3818 'm' => $langs->trans('Month'),
3819 'y' => $langs->trans('Year')
3820 );
3821 if (isset($da[$outdurationunit])) {
3822 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3823 }
3824 }
3825 }
3826
3827 $objRef = $objp->ref;
3828 if ($filterkey && $filterkey != '') {
3829 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3830 }
3831 $objRefFourn = $objp->ref_fourn;
3832 if ($filterkey && $filterkey != '') {
3833 $objRefFourn = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRefFourn, 1);
3834 }
3835 $label = $objp->label;
3836 if ($filterkey && $filterkey != '') {
3837 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3838 }
3839
3840 switch ($objp->fk_product_type) {
3842 $picto = 'product';
3843 break;
3845 $picto = 'service';
3846 break;
3847 default:
3848 $picto = '';
3849 break;
3850 }
3851
3852 if (empty($picto)) {
3853 $optlabel = '';
3854 } else {
3855 $optlabel = img_object('', $picto, 'class="paddingright classfortooltip"', 0, 0, 1);
3856 }
3857
3858 $optlabel .= $objp->ref;
3859 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3860 $optlabel .= ' <span class="opacitymedium">(' . $objp->ref_fourn . ')</span>';
3861 }
3862 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3863 $optlabel .= ' (' . $outbarcode . ')';
3864 }
3865 $optlabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3866
3867 $outvallabel = $objRef;
3868 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3869 $outvallabel .= ' (' . $objRefFourn . ')';
3870 }
3871 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3872 $outvallabel .= ' (' . $outbarcode . ')';
3873 }
3874 $outvallabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3875
3876 // Units
3877 $optlabel .= $outvalUnits;
3878 $outvallabel .= $outvalUnits;
3879
3880 if (!empty($objp->idprodfournprice)) {
3881 $outqty = $objp->quantity;
3882 $outdiscount = $objp->remise_percent;
3883 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3884 $prod_supplier = new ProductFournisseur($this->db);
3885 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3886 $prod_supplier->id = $objp->fk_product;
3887 $prod_supplier->fourn_qty = $objp->quantity;
3888 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3889 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3890
3891 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3892 $priceparser = new PriceParser($this->db);
3893 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3894 if ($price_result >= 0) {
3895 $objp->fprice = $price_result;
3896 if ($objp->quantity >= 1) {
3897 $objp->unitprice = $objp->fprice / $objp->quantity; // Replace dynamically unitprice
3898 }
3899 }
3900 }
3901 if ($objp->quantity == 1) {
3902 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3903 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/";
3904 $optlabel .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3905 $outvallabel .= $langs->transnoentities("Unit");
3906 } else {
3907 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3908 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3909 $optlabel .= ' ' . $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3910 $outvallabel .= ' ' . $langs->transnoentities("Units");
3911 }
3912
3913 if ($objp->quantity > 1) {
3914 $optlabel .= " (" . price($objp->unitprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3915 $outvallabel .= " (" . price($objp->unitprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3916 }
3917 if ($objp->remise_percent >= 1) {
3918 $optlabel .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3919 $outvallabel .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3920 }
3921 if ($objp->duration) {
3922 $optlabel .= " - " . $objp->duration;
3923 $outvallabel .= " - " . $objp->duration;
3924 }
3925 if (!$socid) {
3926 $optlabel .= " - " . dol_trunc($objp->name, 8);
3927 $outvallabel .= " - " . dol_trunc($objp->name, 8);
3928 }
3929 if ($objp->supplier_reputation) {
3930 //TODO dictionary
3931 $reputations = array('' => $langs->trans('Standard'), 'FAVORITE' => $langs->trans('Favorite'), 'NOTTHGOOD' => $langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER' => $langs->trans('DoNotOrderThisProductToThisSupplier'));
3932
3933 $optlabel .= " - " . $reputations[$objp->supplier_reputation];
3934 $outvallabel .= " - " . $reputations[$objp->supplier_reputation];
3935 }
3936 } else {
3937 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3938 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3939 }
3940
3941 if (isModEnabled('stock') && $showstockinlist && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3942 $novirtualstock = ($showstockinlist == 2);
3943
3944 if ($user->hasRight('stock', 'lire')) {
3945 $outvallabel .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3946
3947 if ($objp->stock > 0) {
3948 $optlabel .= ' - <span class="product_line_stock_ok">';
3949 } elseif ($objp->stock <= 0) {
3950 $optlabel .= ' - <span class="product_line_stock_too_low">';
3951 }
3952 $optlabel .= $langs->transnoentities("Stock") . ':' . price(price2num($objp->stock, 'MS'));
3953 $optlabel .= '</span>';
3954 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3955 $langs->load("stocks");
3956
3957 $tmpproduct = new Product($this->db);
3958 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3959 $tmpproduct->load_virtual_stock();
3960 $virtualstock = $tmpproduct->stock_theorique;
3961
3962 $outvallabel .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3963
3964 $optlabel .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3965 if ($virtualstock > 0) {
3966 $optlabel .= '<span class="product_line_stock_ok">';
3967 } elseif ($virtualstock <= 0) {
3968 $optlabel .= '<span class="product_line_stock_too_low">';
3969 }
3970 $optlabel .= $virtualstock;
3971 $optlabel .= '</span>';
3972
3973 unset($tmpproduct);
3974 }
3975 }
3976 }
3977
3978 $optstart = '<option value="' . $outkey . '"';
3979 if ($selected && $selected == $objp->idprodfournprice) {
3980 $optstart .= ' selected';
3981 }
3982 if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) {
3983 $optstart .= ' disabled';
3984 }
3985
3986 if (!empty($objp->idprodfournprice) && $objp->idprodfournprice > 0) {
3987 $optstart .= ' data-product-id="' . dol_escape_htmltag($objp->rowid) . '"';
3988 $optstart .= ' data-price-id="' . dol_escape_htmltag($objp->idprodfournprice) . '"';
3989 $optstart .= ' data-qty="' . dol_escape_htmltag($objp->quantity) . '"';
3990 $optstart .= ' data-up="' . dol_escape_htmltag(price2num($objp->unitprice)) . '"'; // the price with numeric international format
3991 $optstart .= ' data-up-locale="' . dol_escape_htmltag(price($objp->unitprice)) . '"'; // the price formatted in user language
3992 $optstart .= ' data-discount="' . dol_escape_htmltag($outdiscount) . '"';
3993 $optstart .= ' data-tvatx="' . dol_escape_htmltag(price2num($objp->tva_tx)) . '"'; // the rate with numeric international format
3994 $optstart .= ' data-tvatx-formated="' . dol_escape_htmltag(price($objp->tva_tx, 0, $langs, 1, -1, 2)) . '"'; // the rate formatted in user language
3995 $optstart .= ' data-default-vat-code="' . dol_escape_htmltag($objp->default_vat_code) . '"';
3996 $optstart .= ' data-supplier-ref="' . dol_escape_htmltag($objp->ref_fourn) . '"';
3997 if (isModEnabled('multicurrency')) {
3998 $optstart .= ' data-multicurrency-code="' . dol_escape_htmltag($objp->multicurrency_code) . '"';
3999 $optstart .= ' data-multicurrency-unitprice="' . dol_escape_htmltag(price2num($objp->multicurrency_unitprice)) . '"'; // the price with numeric international format
4000 }
4001 }
4002 $optstart .= ' data-description="' . dol_escape_htmltag($objp->description, 0, 1) . '"';
4003
4004 $outarrayentry = array(
4005 'key' => $outkey,
4006 'value' => $outref,
4007 'label' => $outvallabel,
4008 'qty' => $outqty,
4009 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
4010 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
4011 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
4012 'tva_tx_formated' => price($objp->tva_tx, 0, $langs, 1, -1, 2),
4013 'tva_tx' => price2num($objp->tva_tx),
4014 'default_vat_code' => $objp->default_vat_code,
4015 'supplier_ref' => $objp->ref_fourn,
4016 'discount' => $outdiscount,
4017 'type' => $outtype,
4018 'duration_value' => $outdurationvalue,
4019 'duration_unit' => $outdurationunit,
4020 'disabled' => empty($objp->idprodfournprice),
4021 'description' => $objp->description
4022 );
4023 if (isModEnabled('multicurrency')) {
4024 $outarrayentry['multicurrency_code'] = $objp->multicurrency_code;
4025 $outarrayentry['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
4026 }
4027
4028 $parameters = array(
4029 'objp' => &$objp,
4030 'optstart' => &$optstart,
4031 'optlabel' => &$optlabel,
4032 'outvallabel' => &$outvallabel,
4033 'outarrayentry' => &$outarrayentry
4034 );
4035 $reshook = $hookmanager->executeHooks('selectProduitsFournisseurListOption', $parameters, $this);
4036
4037
4038 // Add new entry
4039 // "key" value of json key array is used by jQuery automatically as selected value. Example: 'type' = product or service, 'price_ht' = unit price without tax
4040 // "label" value of json key array is used by jQuery automatically as text for combo box
4041 $out .= $optstart . ' data-html="' . dol_escape_htmltag($optlabel) . '">' . $optlabel . "</option>\n";
4042 $outarraypush = array(
4043 'key' => $outkey,
4044 'value' => $outref,
4045 'label' => $outvallabel,
4046 'qty' => $outqty,
4047 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
4048 'price_qty_ht_locale' => price($objp->fprice),
4049 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
4050 'price_unit_ht_locale' => price($objp->unitprice),
4051 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
4052 'tva_tx_formated' => price($objp->tva_tx),
4053 'tva_tx' => price2num($objp->tva_tx),
4054 'default_vat_code' => $objp->default_vat_code,
4055 'supplier_ref' => $objp->ref_fourn,
4056 'discount' => $outdiscount,
4057 'type' => $outtype,
4058 'duration_value' => $outdurationvalue,
4059 'duration_unit' => $outdurationunit,
4060 'disabled' => (empty($objp->idprodfournprice) ? true : false),
4061 'description' => $objp->description
4062 );
4063 if (isModEnabled('multicurrency')) {
4064 $outarraypush['multicurrency_code'] = $objp->multicurrency_code;
4065 $outarraypush['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
4066 }
4067 array_push($outarray, $outarraypush);
4068
4069 // Example of var_dump $outarray
4070 // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
4071 // ["label"]=>string(76) "ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
4072 // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false)
4073 //}
4074 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
4075 //$outval=array('label'=>'ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)');
4076 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
4077
4078 $i++;
4079 }
4080 $out .= '</select>';
4081
4082 $this->db->free($result);
4083
4084 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
4085 $out .= ajax_combobox($htmlname);
4086 } else {
4087 dol_print_error($this->db);
4088 }
4089
4090 if (empty($outputmode)) {
4091 return $out;
4092 }
4093 return $outarray;
4094 }
4095
4096 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4097
4106 public function select_product_fourn_price($productid, $htmlname = 'productfournpriceid', $selected_supplier = 0)
4107 {
4108 // phpcs:enable
4109 global $langs, $conf;
4110
4111 $langs->load('stocks');
4112
4113 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, pfp.fk_soc,";
4114 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,";
4115 $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name";
4116 $sql .= " FROM " . $this->db->prefix() . "product as p";
4117 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
4118 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
4119 $sql .= " WHERE pfp.entity IN (" . getEntity('productsupplierprice') . ")";
4120 $sql .= " AND p.tobuy = 1";
4121 $sql .= " AND s.fournisseur = 1";
4122 $sql .= " AND p.rowid = " . ((int) $productid);
4123 if (!getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED')) {
4124 $sql .= " ORDER BY s.nom, pfp.ref_fourn DESC";
4125 } else {
4126 $sql .= " ORDER BY pfp.unitprice ASC";
4127 }
4128
4129 dol_syslog(get_class($this) . "::select_product_fourn_price", LOG_DEBUG);
4130 $result = $this->db->query($sql);
4131
4132 if ($result) {
4133 $num = $this->db->num_rows($result);
4134
4135 $form = '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4136
4137 if (!$num) {
4138 $form .= '<option value="0">-- ' . $langs->trans("NoSupplierPriceDefinedForThisProduct") . ' --</option>';
4139 } else {
4140 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
4141 $form .= '<option value="0">&nbsp;</option>';
4142
4143 $i = 0;
4144 while ($i < $num) {
4145 $objp = $this->db->fetch_object($result);
4146
4147 $opt = '<option value="' . $objp->idprodfournprice . '"';
4148 //if there is only one supplier, preselect it
4149 if ($num == 1 || ($selected_supplier > 0 && $objp->fk_soc == $selected_supplier) || ($i == 0 && getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED'))) {
4150 $opt .= ' selected';
4151 }
4152 $opt .= '>' . $objp->name . ' - ' . $objp->ref_fourn . ' - ';
4153
4154 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
4155 $prod_supplier = new ProductFournisseur($this->db);
4156 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
4157 $prod_supplier->id = $productid;
4158 $prod_supplier->fourn_qty = $objp->quantity;
4159 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
4160 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
4161
4162 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
4163 $priceparser = new PriceParser($this->db);
4164 $price_result = $priceparser->parseProductSupplier($prod_supplier);
4165 if ($price_result >= 0) {
4166 $objp->fprice = $price_result;
4167 if ($objp->quantity >= 1) {
4168 $objp->unitprice = $objp->fprice / $objp->quantity;
4169 }
4170 }
4171 }
4172 if ($objp->quantity == 1) {
4173 $opt .= price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
4174 }
4175
4176 $opt .= $objp->quantity . ' ';
4177
4178 if ($objp->quantity == 1) {
4179 $opt .= $langs->trans("Unit");
4180 } else {
4181 $opt .= $langs->trans("Units");
4182 }
4183 if ($objp->quantity > 1) {
4184 $opt .= " - ";
4185 $opt .= price($objp->unitprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit");
4186 }
4187 if ($objp->duration) {
4188 $opt .= " - " . $objp->duration;
4189 }
4190 $opt .= "</option>\n";
4191
4192 $form .= $opt;
4193 $i++;
4194 }
4195 }
4196
4197 $form .= '</select>';
4198 $this->db->free($result);
4199 return $form;
4200 } else {
4201 dol_print_error($this->db);
4202 return '';
4203 }
4204 }
4205
4206
4207 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4214 {
4215 // phpcs:enable
4216 global $langs;
4217
4218 $num = count($this->cache_conditions_paiements);
4219 if ($num > 0) {
4220 return 0; // Cache already loaded
4221 }
4222
4223 dol_syslog(__METHOD__, LOG_DEBUG);
4224
4225 $sql = "SELECT rowid, code, libelle as label, deposit_percent";
4226 $sql .= " FROM " . $this->db->prefix() . 'c_payment_term';
4227 $sql .= " WHERE entity IN (" . getEntity('c_payment_term') . ")";
4228 $sql .= " AND active > 0";
4229 $sql .= " ORDER BY sortorder";
4230
4231 $resql = $this->db->query($sql);
4232 if ($resql) {
4233 $num = $this->db->num_rows($resql);
4234 $i = 0;
4235 while ($i < $num) {
4236 $obj = $this->db->fetch_object($resql);
4237
4238 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4239 $label = ($langs->trans("PaymentConditionShort" . $obj->code) != "PaymentConditionShort" . $obj->code ? $langs->trans("PaymentConditionShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4240 $this->cache_conditions_paiements[$obj->rowid]['code'] = $obj->code;
4241 $this->cache_conditions_paiements[$obj->rowid]['label'] = $label;
4242 $this->cache_conditions_paiements[$obj->rowid]['deposit_percent'] = $obj->deposit_percent;
4243 $i++;
4244 }
4245
4246 //$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1); // We use the field sortorder of table
4247
4248 return $num;
4249 } else {
4250 dol_print_error($this->db);
4251 return -1;
4252 }
4253 }
4254
4255 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4256
4262 public function load_cache_availability()
4263 {
4264 // phpcs:enable
4265 global $langs;
4266
4267 $num = count($this->cache_availability); // TODO Use $conf->cache['availability'] instead of $this->cache_availability
4268 if ($num > 0) {
4269 return 0; // Cache already loaded
4270 }
4271
4272 dol_syslog(__METHOD__, LOG_DEBUG);
4273
4274 $langs->load('propal');
4275
4276 $sql = "SELECT rowid, code, label, position";
4277 $sql .= " FROM " . $this->db->prefix() . 'c_availability';
4278 $sql .= " WHERE active > 0";
4279
4280 $resql = $this->db->query($sql);
4281 if ($resql) {
4282 $num = $this->db->num_rows($resql);
4283 $i = 0;
4284 while ($i < $num) {
4285 $obj = $this->db->fetch_object($resql);
4286
4287 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4288 $label = ($langs->trans("AvailabilityType" . $obj->code) != "AvailabilityType" . $obj->code ? $langs->trans("AvailabilityType" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4289 $this->cache_availability[$obj->rowid]['code'] = $obj->code;
4290 $this->cache_availability[$obj->rowid]['label'] = $label;
4291 $this->cache_availability[$obj->rowid]['position'] = $obj->position;
4292 $i++;
4293 }
4294
4295 $this->cache_availability = dol_sort_array($this->cache_availability, 'position', 'asc', 0, 0, 1);
4296
4297 return $num;
4298 } else {
4299 dol_print_error($this->db);
4300 return -1;
4301 }
4302 }
4303
4314 public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0, $morecss = '')
4315 {
4316 global $langs, $user;
4317
4318 $this->load_cache_availability();
4319
4320 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4321
4322 print '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4323 if ($addempty) {
4324 print '<option value="0">&nbsp;</option>';
4325 }
4326 foreach ($this->cache_availability as $id => $arrayavailability) {
4327 if ($selected == $id) {
4328 print '<option value="' . $id . '" selected>';
4329 } else {
4330 print '<option value="' . $id . '">';
4331 }
4332 print dol_escape_htmltag($arrayavailability['label']);
4333 print '</option>';
4334 }
4335 print '</select>';
4336 if ($user->admin) {
4337 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4338 }
4339 print ajax_combobox($htmlname);
4340 }
4341
4347 public function loadCacheInputReason()
4348 {
4349 global $langs;
4350
4351 $num = count($this->cache_demand_reason); // TODO Use $conf->cache['input_reason'] instead of $this->cache_demand_reason
4352 if ($num > 0) {
4353 return 0; // Cache already loaded
4354 }
4355
4356 $sql = "SELECT rowid, code, label";
4357 $sql .= " FROM " . $this->db->prefix() . 'c_input_reason';
4358 $sql .= " WHERE active > 0";
4359
4360 $resql = $this->db->query($sql);
4361 if ($resql) {
4362 $num = $this->db->num_rows($resql);
4363 $i = 0;
4364 $tmparray = array();
4365 while ($i < $num) {
4366 $obj = $this->db->fetch_object($resql);
4367
4368 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4369 $label = ($obj->label != '-' ? $obj->label : '');
4370 if ($langs->trans("DemandReasonType" . $obj->code) != "DemandReasonType" . $obj->code) {
4371 $label = $langs->trans("DemandReasonType" . $obj->code); // So translation key DemandReasonTypeSRC_XXX will work
4372 }
4373 if ($langs->trans($obj->code) != $obj->code) {
4374 $label = $langs->trans($obj->code); // So translation key SRC_XXX will work
4375 }
4376
4377 $tmparray[$obj->rowid]['id'] = $obj->rowid;
4378 $tmparray[$obj->rowid]['code'] = $obj->code;
4379 $tmparray[$obj->rowid]['label'] = $label;
4380 $i++;
4381 }
4382
4383 $this->cache_demand_reason = dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1);
4384
4385 unset($tmparray);
4386 return $num;
4387 } else {
4388 dol_print_error($this->db);
4389 return -1;
4390 }
4391 }
4392
4405 public function selectInputReason($selected = '', $htmlname = 'demandreasonid', $exclude = '', $addempty = 0, $morecss = '', $notooltip = 0)
4406 {
4407 global $langs, $user;
4408
4409 $this->loadCacheInputReason();
4410
4411 print '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4412 if ($addempty) {
4413 print '<option value="0"' . (empty($selected) ? ' selected' : '') . '>&nbsp;</option>';
4414 }
4415 foreach ($this->cache_demand_reason as $id => $arraydemandreason) {
4416 if ($arraydemandreason['code'] == $exclude) {
4417 continue;
4418 }
4419
4420 if ($selected && ($selected == $arraydemandreason['id'] || $selected == $arraydemandreason['code'])) {
4421 print '<option value="' . $arraydemandreason['id'] . '" selected>';
4422 } else {
4423 print '<option value="' . $arraydemandreason['id'] . '">';
4424 }
4425 $label = $arraydemandreason['label']; // Translation of label was already done into the ->loadCacheInputReason
4426 print $langs->trans($label);
4427 print '</option>';
4428 }
4429 print '</select>';
4430 if ($user->admin && empty($notooltip)) {
4431 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4432 }
4433 print ajax_combobox('select_' . $htmlname);
4434 }
4435
4436 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4437
4444 {
4445 // phpcs:enable
4446 global $langs;
4447
4448 $num = count($this->cache_types_paiements); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_types_paiements
4449 if ($num > 0) {
4450 return $num; // Cache already loaded
4451 }
4452
4453 dol_syslog(__METHOD__, LOG_DEBUG);
4454
4455 $this->cache_types_paiements = array();
4456
4457 $sql = "SELECT id, code, libelle as label, type, active";
4458 $sql .= " FROM " . $this->db->prefix() . "c_paiement";
4459 $sql .= " WHERE entity IN (" . getEntity('c_paiement') . ")";
4460
4461 $resql = $this->db->query($sql);
4462 if ($resql) {
4463 $num = $this->db->num_rows($resql);
4464 $i = 0;
4465 while ($i < $num) {
4466 $obj = $this->db->fetch_object($resql);
4467
4468 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4469 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4470 $this->cache_types_paiements[$obj->id]['id'] = $obj->id;
4471 $this->cache_types_paiements[$obj->id]['code'] = $obj->code;
4472 $this->cache_types_paiements[$obj->id]['label'] = $label;
4473 $this->cache_types_paiements[$obj->id]['type'] = $obj->type;
4474 $this->cache_types_paiements[$obj->id]['active'] = $obj->active;
4475 $i++;
4476 }
4477
4478 $this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1);
4479
4480 return $num;
4481 } else {
4482 dol_print_error($this->db);
4483 return -1;
4484 }
4485 }
4486
4487
4488 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4489
4508 public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1, $noprint = 0)
4509 {
4510 // phpcs:enable
4511 $out = $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, $noinfoadmin, $morecss, $deposit_percent);
4512 if (empty($noprint)) {
4513 print $out;
4514 } else {
4515 return $out;
4516 }
4517 }
4518
4519
4536 public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4537 {
4538 global $langs, $user, $conf;
4539
4540 $out = '';
4541 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4542
4544
4545 // Set default value if not already set by caller
4546 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID')) {
4547 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TERM_ID", LOG_NOTICE);
4548 $selected = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID');
4549 }
4550
4551 $out .= '<select id="' . $htmlname . '" class="flat selectpaymentterms' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4552 if ($addempty) {
4553 $out .= '<option value="0">&nbsp;</option>';
4554 }
4555
4556 $selectedDepositPercent = null;
4557
4558 foreach ($this->cache_conditions_paiements as $id => $arrayconditions) {
4559 if ($filtertype <= 0 && !empty($arrayconditions['deposit_percent'])) {
4560 continue;
4561 }
4562
4563 if ($selected == $id) {
4564 $selectedDepositPercent = $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'];
4565 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '" selected>';
4566 } else {
4567 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '">';
4568 }
4569 $label = $arrayconditions['label'];
4570
4571 if (!empty($arrayconditions['deposit_percent'])) {
4572 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'], $label);
4573 }
4574
4575 $out .= $label;
4576 $out .= '</option>';
4577 }
4578 $out .= '</select>';
4579 if ($user->admin && empty($noinfoadmin)) {
4580 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4581 }
4582 $out .= ajax_combobox($htmlname);
4583
4584 if ($deposit_percent >= 0) {
4585 $out .= ' <span id="' . $htmlname . '_deposit_percent_container"' . (empty($selectedDepositPercent) ? ' style="display: none"' : '') . '>';
4586 $out .= $langs->trans('DepositPercent') . ' : ';
4587 $out .= '<input id="' . $htmlname . '_deposit_percent" name="' . $htmlname . '_deposit_percent" class="maxwidth50" value="' . $deposit_percent . '" />';
4588 $out .= '</span>';
4589 $out .= '
4590 <script nonce="' . getNonce() . '">
4591 $(document).ready(function () {
4592 $("#' . $htmlname . '").change(function () {
4593 let $selected = $(this).find("option:selected");
4594 let depositPercent = $selected.attr("data-deposit_percent");
4595
4596 if (depositPercent.length > 0) {
4597 $("#' . $htmlname . '_deposit_percent_container").show().find("#' . $htmlname . '_deposit_percent").val(depositPercent);
4598 } else {
4599 $("#' . $htmlname . '_deposit_percent_container").hide().find("#' . $htmlname . '_deposit_percent").val(0);
4600 }
4601
4602 return true;
4603 });
4604 });
4605 </script>';
4606 }
4607
4608 return $out;
4609 }
4610
4611
4612 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4613
4630 public function select_types_paiements($selected = '', $htmlname = 'paiementtype', $filtertype = '', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '', $nooutput = 0)
4631 {
4632 // phpcs:enable
4633 global $langs, $user, $conf;
4634
4635 $out = '';
4636
4637 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
4638
4639 $filterarray = array();
4640 if ($filtertype == 'CRDT') {
4641 $filterarray = array(0, 2, 3);
4642 } elseif ($filtertype == 'DBIT') {
4643 $filterarray = array(1, 2, 3);
4644 } elseif ($filtertype != '' && $filtertype != '-1') {
4645 $filterarray = explode(',', $filtertype);
4646 }
4647
4649
4650 // Set default value if not already set by caller
4651 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID')) {
4652 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TYPE_ID", LOG_NOTICE);
4653 $selected = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID');
4654 }
4655
4656 $out .= '<select id="select' . $htmlname . '" class="flat selectpaymenttypes' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4657 if ($empty) {
4658 $out .= '<option value="">&nbsp;</option>';
4659 }
4660 foreach ($this->cache_types_paiements as $id => $arraytypes) {
4661 // If not good status
4662 if ($active >= 0 && $arraytypes['active'] != $active) {
4663 continue;
4664 }
4665
4666 // We skip of the user requested to filter on specific payment methods
4667 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
4668 continue;
4669 }
4670
4671 // We discard empty lines if showempty is on because an empty line has already been output.
4672 if ($empty && empty($arraytypes['code'])) {
4673 continue;
4674 }
4675
4676 if ($format == 0) {
4677 $out .= '<option value="' . $id . '"';
4678 } elseif ($format == 1) {
4679 $out .= '<option value="' . $arraytypes['code'] . '"';
4680 } elseif ($format == 2) {
4681 $out .= '<option value="' . $arraytypes['code'] . '"';
4682 } elseif ($format == 3) {
4683 $out .= '<option value="' . $id . '"';
4684 }
4685 // Print attribute selected or not
4686 if ($format == 1 || $format == 2) {
4687 if ($selected == $arraytypes['code']) {
4688 $out .= ' selected';
4689 }
4690 } else {
4691 if ($selected == $id) {
4692 $out .= ' selected';
4693 }
4694 }
4695 $out .= '>';
4696 $value = '';
4697 if ($format == 0) {
4698 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4699 } elseif ($format == 1) {
4700 $value = $arraytypes['code'];
4701 } elseif ($format == 2) {
4702 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4703 } elseif ($format == 3) {
4704 $value = $arraytypes['code'];
4705 }
4706 $out .= $value ? $value : '&nbsp;';
4707 $out .= '</option>';
4708 }
4709 $out .= '</select>';
4710 if ($user->admin && !$noadmininfo) {
4711 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4712 }
4713 $out .= ajax_combobox('select' . $htmlname);
4714
4715 if (empty($nooutput)) {
4716 print $out;
4717 } else {
4718 return $out;
4719 }
4720 }
4721
4722
4731 public function selectPriceBaseType($selected = '', $htmlname = 'price_base_type', $addjscombo = 0)
4732 {
4733 global $langs;
4734
4735 $return = '<select class="flat maxwidth100" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4736 $options = array(
4737 'HT' => $langs->trans("HT"),
4738 'TTC' => $langs->trans("TTC")
4739 );
4740 foreach ($options as $id => $value) {
4741 if ($selected == $id) {
4742 $return .= '<option value="' . $id . '" selected>' . $value;
4743 } else {
4744 $return .= '<option value="' . $id . '">' . $value;
4745 }
4746 $return .= '</option>';
4747 }
4748 $return .= '</select>';
4749 if ($addjscombo) {
4750 $return .= ajax_combobox('select_' . $htmlname);
4751 }
4752
4753 return $return;
4754 }
4755
4756 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4757
4764 {
4765 // phpcs:enable
4766 global $langs;
4767
4768 $num = count($this->cache_transport_mode); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_transport_mode
4769 if ($num > 0) {
4770 return $num; // Cache already loaded
4771 }
4772
4773 dol_syslog(__METHOD__, LOG_DEBUG);
4774
4775 $this->cache_transport_mode = array();
4776
4777 $sql = "SELECT rowid, code, label, active";
4778 $sql .= " FROM " . $this->db->prefix() . "c_transport_mode";
4779 $sql .= " WHERE entity IN (" . getEntity('c_transport_mode') . ")";
4780
4781 $resql = $this->db->query($sql);
4782 if ($resql) {
4783 $num = $this->db->num_rows($resql);
4784 $i = 0;
4785 while ($i < $num) {
4786 $obj = $this->db->fetch_object($resql);
4787
4788 // If traduction exist, we use it else we take the default label
4789 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4790 $this->cache_transport_mode[$obj->rowid]['rowid'] = $obj->rowid;
4791 $this->cache_transport_mode[$obj->rowid]['code'] = $obj->code;
4792 $this->cache_transport_mode[$obj->rowid]['label'] = $label;
4793 $this->cache_transport_mode[$obj->rowid]['active'] = $obj->active;
4794 $i++;
4795 }
4796
4797 $this->cache_transport_mode = dol_sort_array($this->cache_transport_mode, 'label', 'asc', 0, 0, 1);
4798
4799 return $num;
4800 } else {
4801 dol_print_error($this->db);
4802 return -1;
4803 }
4804 }
4805
4819 public function selectTransportMode($selected = '', $htmlname = 'transportmode', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '')
4820 {
4821 global $langs, $user;
4822
4823 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $format, LOG_DEBUG);
4824
4826
4827 print '<select id="select' . $htmlname . '" class="flat selectmodetransport' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4828 if ($empty) {
4829 print '<option value="">&nbsp;</option>';
4830 }
4831 foreach ($this->cache_transport_mode as $id => $arraytypes) {
4832 // If not good status
4833 if ($active >= 0 && $arraytypes['active'] != $active) {
4834 continue;
4835 }
4836
4837 // We discard empty line if showempty is on because an empty line has already been output.
4838 if ($empty && empty($arraytypes['code'])) {
4839 continue;
4840 }
4841
4842 if ($format == 0) {
4843 print '<option value="' . $id . '"';
4844 } elseif ($format == 1) {
4845 print '<option value="' . $arraytypes['code'] . '"';
4846 } elseif ($format == 2) {
4847 print '<option value="' . $arraytypes['code'] . '"';
4848 } elseif ($format == 3) {
4849 print '<option value="' . $id . '"';
4850 }
4851 // If text is selected, we compare with code, else with id
4852 if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) {
4853 print ' selected';
4854 } elseif ($selected == $id) {
4855 print ' selected';
4856 }
4857 print '>';
4858 $value = '';
4859 if ($format == 0) {
4860 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4861 } elseif ($format == 1) {
4862 $value = $arraytypes['code'];
4863 } elseif ($format == 2) {
4864 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4865 } elseif ($format == 3) {
4866 $value = $arraytypes['code'];
4867 }
4868 print $value ? $value : '&nbsp;';
4869 print '</option>';
4870 }
4871 print '</select>';
4872 if ($user->admin && !$noadmininfo) {
4873 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4874 }
4875 }
4876
4889 public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '', $noinfoadmin = 0, $morecss = '')
4890 {
4891 global $langs, $user;
4892
4893 $langs->load("admin");
4894 $langs->load("deliveries");
4895
4896 $sql = "SELECT rowid, code, libelle as label";
4897 $sql .= " FROM " . $this->db->prefix() . "c_shipment_mode";
4898 $sql .= " WHERE active > 0";
4899 if ($filtre) {
4900 $sql .= " AND " . $filtre;
4901 }
4902 $sql .= " ORDER BY libelle ASC";
4903
4904 dol_syslog(get_class($this) . "::selectShippingMode", LOG_DEBUG);
4905 $result = $this->db->query($sql);
4906 if ($result) {
4907 $num = $this->db->num_rows($result);
4908 $i = 0;
4909 if ($num) {
4910 print '<select id="select' . $htmlname . '" class="flat selectshippingmethod' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4911 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4912 print '<option value="-1">&nbsp;</option>';
4913 }
4914 while ($i < $num) {
4915 $obj = $this->db->fetch_object($result);
4916 if ($selected == $obj->rowid) {
4917 print '<option value="' . $obj->rowid . '" selected>';
4918 } else {
4919 print '<option value="' . $obj->rowid . '">';
4920 }
4921 print ($langs->trans("SendingMethod" . strtoupper($obj->code)) != "SendingMethod" . strtoupper($obj->code)) ? $langs->trans("SendingMethod" . strtoupper($obj->code)) : $obj->label;
4922 print '</option>';
4923 $i++;
4924 }
4925 print "</select>";
4926 if ($user->admin && empty($noinfoadmin)) {
4927 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4928 }
4929
4930 print ajax_combobox('select' . $htmlname);
4931 } else {
4932 print $langs->trans("NoShippingMethodDefined");
4933 }
4934 } else {
4935 dol_print_error($this->db);
4936 }
4937 }
4938
4948 public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0)
4949 {
4950 global $langs;
4951
4952 $langs->load("deliveries");
4953
4954 if ($htmlname != "none") {
4955 print '<form method="POST" action="' . $page . '">';
4956 print '<input type="hidden" name="action" value="setshippingmethod">';
4957 print '<input type="hidden" name="token" value="' . newToken() . '">';
4958 $this->selectShippingMethod($selected, $htmlname, '', $addempty);
4959 print '<input type="submit" class="button valignmiddle" value="' . $langs->trans("Modify") . '">';
4960 print '</form>';
4961 } else {
4962 if ($selected) {
4963 $code = $langs->getLabelFromKey($this->db, $selected, 'c_shipment_mode', 'rowid', 'code');
4964 print $langs->trans("SendingMethod" . strtoupper($code));
4965 } else {
4966 print "&nbsp;";
4967 }
4968 }
4969 }
4970
4979 public function selectSituationInvoices($selected = '', $socid = 0)
4980 {
4981 global $langs;
4982
4983 $langs->load('bills');
4984
4985 $opt = '<option value="" selected></option>';
4986 $sql = "SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc";
4987 $sql .= ' FROM ' . $this->db->prefix() . 'facture';
4988 $sql .= ' WHERE entity IN (' . getEntity('invoice') . ')';
4989 $sql .= ' AND situation_counter >= 1';
4990 $sql .= ' AND fk_soc = ' . (int) $socid;
4991 $sql .= ' AND type <> 2';
4992 $sql .= ' ORDER by situation_cycle_ref, situation_counter desc';
4993 $resql = $this->db->query($sql);
4994
4995 if ($resql && $this->db->num_rows($resql) > 0) {
4996 // Last seen cycle
4997 $ref = 0;
4998 while ($obj = $this->db->fetch_object($resql)) {
4999 //Same cycle ?
5000 if ($obj->situation_cycle_ref != $ref) {
5001 // Just seen this cycle
5002 $ref = $obj->situation_cycle_ref;
5003 //not final ?
5004 if ($obj->situation_final != 1) {
5005 //Not prov?
5006 if (substr($obj->ref, 1, 4) != 'PROV') {
5007 if ($selected == $obj->rowid) {
5008 $opt .= '<option value="' . $obj->rowid . '" selected>' . $obj->ref . '</option>';
5009 } else {
5010 $opt .= '<option value="' . $obj->rowid . '">' . $obj->ref . '</option>';
5011 }
5012 }
5013 }
5014 }
5015 }
5016 } else {
5017 dol_syslog("Error sql=" . $sql . ", error=" . $this->error, LOG_ERR);
5018 }
5019 if ($opt == '<option value ="" selected></option>') {
5020 $opt = '<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>';
5021 }
5022 return $opt;
5023 }
5024
5034 public function selectUnits($selected = '', $htmlname = 'units', $showempty = 0, $unit_type = '')
5035 {
5036 global $langs;
5037
5038 $langs->load('products');
5039
5040 $return = '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
5041
5042 $sql = "SELECT rowid, label, code FROM " . $this->db->prefix() . "c_units";
5043 $sql .= ' WHERE active > 0';
5044 if (!empty($unit_type)) {
5045 $sql .= " AND unit_type = '" . $this->db->escape($unit_type) . "'";
5046 }
5047 $sql .= " ORDER BY sortorder";
5048
5049 $resql = $this->db->query($sql);
5050 if ($resql && $this->db->num_rows($resql) > 0) {
5051 if ($showempty) {
5052 $return .= '<option value="none"></option>';
5053 }
5054
5055 while ($res = $this->db->fetch_object($resql)) {
5056 $unitLabel = $res->label;
5057 if (!empty($langs->tab_translate['unit' . $res->code])) { // check if Translation is available before
5058 $unitLabel = $langs->trans('unit' . $res->code) != $res->label ? $langs->trans('unit' . $res->code) : $res->label;
5059 }
5060
5061 if ($selected == $res->rowid) {
5062 $return .= '<option value="' . $res->rowid . '" selected>' . $unitLabel . '</option>';
5063 } else {
5064 $return .= '<option value="' . $res->rowid . '">' . $unitLabel . '</option>';
5065 }
5066 }
5067 $return .= '</select>';
5068 }
5069 return $return;
5070 }
5071
5072 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5073
5088 public function select_comptes($selected = '', $htmlname = 'accountid', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '', $showcurrency = 0, $morecss = '', $nooutput = 0)
5089 {
5090 // phpcs:enable
5091 global $langs;
5092
5093 $out = '';
5094
5095 $langs->load("admin");
5096 $num = 0;
5097
5098 $sql = "SELECT rowid, label, bank, clos as status, currency_code";
5099 $sql .= " FROM " . $this->db->prefix() . "bank_account";
5100 $sql .= " WHERE entity IN (" . getEntity('bank_account') . ")";
5101 if ($status != 2) {
5102 $sql .= " AND clos = " . (int) $status;
5103 }
5104 if ($filtre) { // TODO Support USF
5105 $sql .= " AND " . $filtre;
5106 }
5107 $sql .= " ORDER BY label";
5108
5109 dol_syslog(get_class($this) . "::select_comptes", LOG_DEBUG);
5110 $result = $this->db->query($sql);
5111 if ($result) {
5112 $num = $this->db->num_rows($result);
5113 $i = 0;
5114 if ($num) {
5115 $out .= '<select id="select' . $htmlname . '" class="flat selectbankaccount' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5116
5117 if (!empty($useempty) && !is_numeric($useempty)) {
5118 $out .= '<option value="-1">'.$langs->trans($useempty).'</option>';
5119 } elseif ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5120 $out .= '<option value="-1">&nbsp;</option>';
5121 }
5122
5123 while ($i < $num) {
5124 $obj = $this->db->fetch_object($result);
5125 if ($selected == $obj->rowid || ($useempty == 2 && $num == 1 && empty($selected))) {
5126 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '" selected>';
5127 } else {
5128 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '">';
5129 }
5130 $out .= trim($obj->label);
5131 if ($showcurrency) {
5132 $out .= ' (' . $obj->currency_code . ')';
5133 }
5134 if ($status == 2 && $obj->status == 1) {
5135 $out .= ' (' . $langs->trans("Closed") . ')';
5136 }
5137 $out .= '</option>';
5138 $i++;
5139 }
5140 $out .= "</select>";
5141 $out .= ajax_combobox('select' . $htmlname);
5142 } else {
5143 if ($status == 0) {
5144 $out .= '<span class="opacitymedium">' . $langs->trans("NoActiveBankAccountDefined") . '</span>';
5145 } else {
5146 $out .= '<span class="opacitymedium">' . $langs->trans("NoBankAccountFound") . '</span>';
5147 }
5148 }
5149 } else {
5150 dol_print_error($this->db);
5151 }
5152
5153 // Output or return
5154 if (empty($nooutput)) {
5155 print $out;
5156 } else {
5157 return $out;
5158 }
5159
5160 return $num;
5161 }
5162
5174 public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '')
5175 {
5176 global $langs;
5177
5178 $langs->load("admin");
5179 $num = 0;
5180
5181 $sql = "SELECT rowid, name, fk_country, status, entity";
5182 $sql .= " FROM " . $this->db->prefix() . "establishment";
5183 $sql .= " WHERE 1=1";
5184 if ($status != 2) {
5185 $sql .= " AND status = " . (int) $status;
5186 }
5187 if ($filtre) { // TODO Support USF
5188 $sql .= " AND " . $filtre;
5189 }
5190 $sql .= " ORDER BY name";
5191
5192 dol_syslog(get_class($this) . "::select_establishment", LOG_DEBUG);
5193 $result = $this->db->query($sql);
5194 if ($result) {
5195 $num = $this->db->num_rows($result);
5196 $i = 0;
5197 if ($num) {
5198 print '<select id="select' . $htmlname . '" class="flat selectestablishment" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5199 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5200 print '<option value="-1">&nbsp;</option>';
5201 }
5202
5203 while ($i < $num) {
5204 $obj = $this->db->fetch_object($result);
5205 if ($selected == $obj->rowid) {
5206 print '<option value="' . $obj->rowid . '" selected>';
5207 } else {
5208 print '<option value="' . $obj->rowid . '">';
5209 }
5210 print trim($obj->name);
5211 if ($status == 2 && $obj->status == 1) {
5212 print ' (' . $langs->trans("Closed") . ')';
5213 }
5214 print '</option>';
5215 $i++;
5216 }
5217 print "</select>";
5218 } else {
5219 if ($status == 0) {
5220 print '<span class="opacitymedium">' . $langs->trans("NoActiveEstablishmentDefined") . '</span>';
5221 } else {
5222 print '<span class="opacitymedium">' . $langs->trans("NoEstablishmentFound") . '</span>';
5223 }
5224 }
5225
5226 return $num;
5227 } else {
5228 dol_print_error($this->db);
5229 return -1;
5230 }
5231 }
5232
5242 public function formSelectAccount($page, $selected = '', $htmlname = 'fk_account', $addempty = 0)
5243 {
5244 global $langs;
5245 if ($htmlname != "none") {
5246 print '<form method="POST" action="' . $page . '">';
5247 print '<input type="hidden" name="action" value="setbankaccount">';
5248 print '<input type="hidden" name="token" value="' . newToken() . '">';
5249 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
5250 $nbaccountfound = $this->select_comptes($selected, $htmlname, 0, '', $addempty);
5251 if ($nbaccountfound > 0) {
5252 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5253 }
5254 print '</form>';
5255 } else {
5256 $langs->load('banks');
5257
5258 if ($selected) {
5259 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
5260 $bankstatic = new Account($this->db);
5261 $result = $bankstatic->fetch($selected);
5262 if ($result) {
5263 print $bankstatic->getNomUrl(1);
5264 }
5265 } else {
5266 print "&nbsp;";
5267 }
5268 }
5269 }
5270
5271 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5272
5292 public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $fromid = 0, $outputmode = 0, $include = 0, $morecss = '', $useempty = 1)
5293 {
5294 // phpcs:enable
5295 global $conf, $langs;
5296 $langs->load("categories");
5297
5298 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
5299
5300 // For backward compatibility
5301 if (is_numeric($type)) {
5302 dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING);
5303 }
5304
5305 if ($type === Categorie::TYPE_BANK_LINE) {
5306 // TODO Move this into common category feature
5307 $cate_arbo = array();
5308 $sql = "SELECT c.label, c.rowid";
5309 $sql .= " FROM " . $this->db->prefix() . "bank_categ as c";
5310 $sql .= " WHERE entity = " . $conf->entity;
5311 $sql .= " ORDER BY c.label";
5312 $result = $this->db->query($sql);
5313 if ($result) {
5314 $num = $this->db->num_rows($result);
5315 $i = 0;
5316 while ($i < $num) {
5317 $objp = $this->db->fetch_object($result);
5318 if ($objp) {
5319 $cate_arbo[$objp->rowid] = array('id' => $objp->rowid, 'fulllabel' => $objp->label, 'color' => '', 'picto' => 'category');
5320 }
5321 $i++;
5322 }
5323 $this->db->free($result);
5324 } else {
5325 dol_print_error($this->db);
5326 }
5327 } else {
5328 $cat = new Categorie($this->db);
5329 $cate_arbo = $cat->get_full_arbo($type, $fromid, $include);
5330 }
5331
5332 $outarray = array();
5333 $outarrayrichhtml = array();
5334
5335
5336 $output = '<select class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
5337 if (is_array($cate_arbo)) {
5338 $num = count($cate_arbo);
5339
5340 if (!$num) {
5341 $output .= '<option value="-1" disabled>' . $langs->trans("NoCategoriesDefined") . '</option>';
5342 } else {
5343 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5344 $output .= '<option value="-1">&nbsp;</option>';
5345 }
5346 foreach ($cate_arbo as $key => $value) {
5347 if ($cate_arbo[$key]['id'] == $selected || ($selected === 'auto' && count($cate_arbo) == 1)) {
5348 $add = 'selected ';
5349 } else {
5350 $add = '';
5351 }
5352
5353 $labeltoshow = img_picto('', 'category', 'class="pictofixedwidth" style="color: #' . $cate_arbo[$key]['color'] . '"');
5354 $labeltoshow .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5355
5356 $outarray[$cate_arbo[$key]['id']] = $cate_arbo[$key]['fulllabel'];
5357
5358 $outarrayrichhtml[$cate_arbo[$key]['id']] = $labeltoshow;
5359
5360 $output .= '<option ' . $add . 'value="' . $cate_arbo[$key]['id'] . '"';
5361 $output .= ' data-html="' . dol_escape_htmltag($labeltoshow) . '"';
5362 $output .= '>';
5363 $output .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5364 $output .= '</option>';
5365
5366 $cate_arbo[$key]['data-html'] = $labeltoshow;
5367 }
5368 }
5369 }
5370 $output .= '</select>';
5371 $output .= "\n";
5372
5373 if ($outputmode == 2) {
5374 // TODO: handle error when $cate_arbo is not an array
5375 return $cate_arbo;
5376 } elseif ($outputmode == 1) {
5377 return $outarray;
5378 } elseif ($outputmode == 3) {
5379 return $outarrayrichhtml;
5380 }
5381 return $output;
5382 }
5383
5384 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5385
5402 public function form_confirm($page, $title, $question, $action, $formquestion = array(), $selectedchoice = "", $useajax = 0, $height = 170, $width = 500)
5403 {
5404 // phpcs:enable
5405 dol_syslog(__METHOD__ . ': using form_confirm is deprecated. Use formconfim instead.', LOG_WARNING);
5406 print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width);
5407 }
5408
5436 public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No')
5437 {
5438 global $langs, $conf;
5439
5440 $more = '<!-- formconfirm - before call, page=' . dol_escape_htmltag($page) . ' -->';
5441 $formconfirm = '';
5442 $inputok = array();
5443 $inputko = array();
5444
5445 // Clean parameters
5446 $newselectedchoice = empty($selectedchoice) ? "no" : $selectedchoice;
5447 if ($conf->browser->layout == 'phone') {
5448 $width = '95%';
5449 }
5450
5451 // Set height automatically if not defined
5452 if (empty($height)) {
5453 $height = 220;
5454 if (is_array($formquestion) && count($formquestion) > 2) {
5455 $height += ((count($formquestion) - 2) * 24);
5456 }
5457 }
5458
5459 if (is_array($formquestion) && !empty($formquestion)) {
5460 // First add hidden fields and value
5461 foreach ($formquestion as $key => $input) {
5462 if (is_array($input) && !empty($input)) {
5463 if ($input['type'] == 'hidden') {
5464 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5465 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5466
5467 $more .= '<input type="hidden" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '" value="' . dol_escape_htmltag($input['value']) . '" class="' . $morecss . '"' . $moreattr . '>' . "\n";
5468 }
5469 }
5470 }
5471
5472 // Now add questions
5473 $moreonecolumn = '';
5474 $more .= '<div class="tagtable paddingtopbottomonly centpercent noborderspacing">' . "\n";
5475 foreach ($formquestion as $key => $input) {
5476 if (is_array($input) && !empty($input)) {
5477 $size = (!empty($input['size']) ? ' size="' . $input['size'] . '"' : ''); // deprecated. Use morecss instead.
5478 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5479 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5480
5481 if ($input['type'] == 'text') {
5482 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div><div class="tagtd"><input type="text" class="flat' . $morecss . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $size . ' value="' . (empty($input['value']) ? '' : $input['value']) . '"' . $moreattr . ' /></div></div>' . "\n";
5483 } elseif ($input['type'] == 'password') {
5484 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div><div class="tagtd"><input type="password" class="flat' . $morecss . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $size . ' value="' . (empty($input['value']) ? '' : $input['value']) . '"' . $moreattr . ' /></div></div>' . "\n";
5485 } elseif ($input['type'] == 'textarea') {
5486 /*$more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">'.$input['label'].'</div><div class="tagtd">';
5487 $more .= '<textarea name="'.$input['name'].'" class="'.$morecss.'"'.$moreattr.'>';
5488 $more .= $input['value'];
5489 $more .= '</textarea>';
5490 $more .= '</div></div>'."\n";*/
5491 $moreonecolumn .= '<div class="margintoponly">';
5492 $moreonecolumn .= $input['label'] . '<br>';
5493 $moreonecolumn .= '<textarea name="' . dol_escape_htmltag($input['name']) . '" id="' . dol_escape_htmltag($input['name']) . '" class="' . $morecss . '"' . $moreattr . '>';
5494 $moreonecolumn .= $input['value'];
5495 $moreonecolumn .= '</textarea>';
5496 $moreonecolumn .= '</div>';
5497 } elseif (in_array($input['type'], ['select', 'multiselect'])) {
5498 if (empty($morecss)) {
5499 $morecss = 'minwidth100';
5500 }
5501
5502 $show_empty = isset($input['select_show_empty']) ? $input['select_show_empty'] : 1;
5503 $key_in_label = isset($input['select_key_in_label']) ? $input['select_key_in_label'] : 0;
5504 $value_as_key = isset($input['select_value_as_key']) ? $input['select_value_as_key'] : 0;
5505 $translate = isset($input['select_translate']) ? $input['select_translate'] : 0;
5506 $maxlen = isset($input['select_maxlen']) ? $input['select_maxlen'] : 0;
5507 $disabled = isset($input['select_disabled']) ? $input['select_disabled'] : 0;
5508 $sort = isset($input['select_sort']) ? $input['select_sort'] : '';
5509
5510 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">';
5511 if (!empty($input['label'])) {
5512 $more .= $input['label'] . '</div><div class="tagtd left">';
5513 }
5514 if ($input['type'] == 'select') {
5515 $more .= $this->selectarray($input['name'], $input['values'], isset($input['default']) ? $input['default'] : '-1', $show_empty, $key_in_label, $value_as_key, $moreattr, $translate, $maxlen, $disabled, $sort, $morecss);
5516 } else {
5517 $more .= $this->multiselectarray($input['name'], $input['values'], is_array($input['default']) ? $input['default'] : [$input['default']], $key_in_label, $value_as_key, $morecss, $translate, $maxlen, $moreattr);
5518 }
5519 $more .= '</div></div>' . "\n";
5520 } elseif ($input['type'] == 'checkbox') {
5521 $more .= '<div class="tagtr">';
5522 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '"><label for="' . dol_escape_htmltag($input['name']) . '">' . $input['label'] . '</label></div><div class="tagtd">';
5523 $more .= '<input type="checkbox" class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $moreattr;
5524 if (!is_bool($input['value']) && $input['value'] != 'false' && $input['value'] != '0' && $input['value'] != '') {
5525 $more .= ' checked';
5526 }
5527 if (is_bool($input['value']) && $input['value']) {
5528 $more .= ' checked';
5529 }
5530 if (isset($input['disabled'])) {
5531 $more .= ' disabled';
5532 }
5533 $more .= ' /></div>';
5534 $more .= '</div>' . "\n";
5535 } elseif ($input['type'] == 'radio') {
5536 $i = 0;
5537 foreach ($input['values'] as $selkey => $selval) {
5538 $more .= '<div class="tagtr">';
5539 if (isset($input['label'])) {
5540 if ($i == 0) {
5541 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? ' tdtop' : (' tdtop ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5542 } else {
5543 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' "' . $input['tdclass'])) . '">&nbsp;</div>';
5544 }
5545 }
5546 $more .= '<div class="tagtd' . ($i == 0 ? ' tdtop' : '') . '"><input type="radio" class="flat' . $morecss . '" id="' . dol_escape_htmltag($input['name'] . $selkey) . '" name="' . dol_escape_htmltag($input['name']) . '" value="' . $selkey . '"' . $moreattr;
5547 if (!empty($input['disabled'])) {
5548 $more .= ' disabled';
5549 }
5550 if (isset($input['default']) && $input['default'] === $selkey) {
5551 $more .= ' checked="checked"';
5552 }
5553 $more .= ' /> ';
5554 $more .= '<label for="' . dol_escape_htmltag($input['name'] . $selkey) . '" class="valignmiddle">' . $selval . '</label>';
5555 $more .= '</div></div>' . "\n";
5556 $i++;
5557 }
5558 } elseif ($input['type'] == 'date' || $input['type'] == 'datetime') {
5559 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5560 $more .= '<div class="tagtd">';
5561 $addnowlink = (empty($input['datenow']) ? 0 : 1);
5562 $h = $m = 0;
5563 if ($input['type'] == 'datetime') {
5564 $h = isset($input['hours']) ? $input['hours'] : 1;
5565 $m = isset($input['minutes']) ? $input['minutes'] : 1;
5566 }
5567 $more .= $this->selectDate(isset($input['value']) ? $input['value'] : -1, $input['name'], $h, $m, 0, '', 1, $addnowlink);
5568 $more .= '</div></div>'."\n";
5569 $formquestion[] = array('name' => $input['name'].'day');
5570 $formquestion[] = array('name' => $input['name'].'month');
5571 $formquestion[] = array('name' => $input['name'].'year');
5572 $formquestion[] = array('name' => $input['name'].'hour');
5573 $formquestion[] = array('name' => $input['name'].'min');
5574 } elseif ($input['type'] == 'other') { // can be 1 column or 2 depending if label is set or not
5575 $more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">';
5576 if (!empty($input['label'])) {
5577 $more .= $input['label'] . '</div><div class="tagtd">';
5578 }
5579 $more .= $input['value'];
5580 $more .= '</div></div>' . "\n";
5581 } elseif ($input['type'] == 'onecolumn') {
5582 $moreonecolumn .= '<div class="margintoponly">';
5583 $moreonecolumn .= $input['value'];
5584 $moreonecolumn .= '</div>' . "\n";
5585 } elseif ($input['type'] == 'hidden') {
5586 // Do nothing more, already added by a previous loop
5587 } elseif ($input['type'] == 'separator') {
5588 $more .= '<br>';
5589 } else {
5590 $more .= 'Error type ' . $input['type'] . ' for the confirm box is not a supported type';
5591 }
5592 }
5593 }
5594 $more .= '</div>' . "\n";
5595 $more .= $moreonecolumn;
5596 }
5597
5598 // JQUERY method dialog is broken with smartphone, we use standard HTML.
5599 // Note: When using dol_use_jmobile or no js, you must also check code for button use a GET url with action=xxx and check that you also output the confirm code when action=xxx
5600 // See page product/card.php for example
5601 if (!empty($conf->dol_use_jmobile)) {
5602 $useajax = 0;
5603 }
5604 if (empty($conf->use_javascript_ajax)) {
5605 $useajax = 0;
5606 }
5607
5608 if ($useajax) {
5609 $autoOpen = true;
5610 $dialogconfirm = 'dialog-confirm';
5611 $button = '';
5612 if (!is_numeric($useajax)) {
5613 $button = $useajax;
5614 $useajax = 1;
5615 $autoOpen = false;
5616 $dialogconfirm .= '-' . $button;
5617 }
5618 $pageyes = $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=yes';
5619 $pageno = ($useajax == 2 ? $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=no' : '');
5620
5621 // Add input fields into list of fields to read during submit (inputok and inputko)
5622 if (is_array($formquestion)) {
5623 foreach ($formquestion as $key => $input) {
5624 //print "xx ".$key." rr ".is_array($input)."<br>\n";
5625 // Add name of fields to propagate with the GET when submitting the form with button OK.
5626 if (is_array($input) && isset($input['name'])) {
5627 if (strpos($input['name'], ',') > 0) {
5628 $inputok = array_merge($inputok, explode(',', $input['name']));
5629 } else {
5630 array_push($inputok, $input['name']);
5631 }
5632 }
5633 // Add name of fields to propagate with the GET when submitting the form with button KO.
5634 // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset
5635 if (is_array($input) && isset($input['inputko']) && $input['inputko'] == 1 && isset($input['name'])) {
5636 array_push($inputko, $input['name']);
5637 }
5638 }
5639 }
5640
5641 // Show JQuery confirm box.
5642 $formconfirm .= '<div id="' . $dialogconfirm . '" title="' . dol_escape_htmltag($title) . '" style="display: none;">';
5643 if (is_array($formquestion) && array_key_exists('text', $formquestion) && !empty($formquestion['text'])) {
5644 $formconfirm .= '<div class="confirmtext">' . $formquestion['text'] . '</div>' . "\n";
5645 }
5646 if (!empty($more)) {
5647 $formconfirm .= '<div class="confirmquestions">' . $more . '</div>' . "\n";
5648 }
5649 $formconfirm .= ($question ? '<div class="confirmmessage">' . img_help(0, '') . ' ' . $question . '</div>' : '');
5650 $formconfirm .= '</div>' . "\n";
5651
5652 $formconfirm .= "\n<!-- begin code of popup for formconfirm page=" . $page . " -->\n";
5653 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5654 $formconfirm .= "/* Code for the jQuery('#dialogforpopup').dialog() */\n";
5655 $formconfirm .= 'jQuery(document).ready(function() {
5656 $(function() {
5657 $( "#' . $dialogconfirm . '" ).dialog(
5658 {
5659 autoOpen: ' . ($autoOpen ? "true" : "false") . ',';
5660 if ($newselectedchoice == 'no') {
5661 $formconfirm .= '
5662 open: function() {
5663 $(this).parent().find("button.ui-button:eq(2)").focus();
5664 },';
5665 }
5666
5667 $jsforcursor = '';
5668 if ($useajax == 1) {
5669 $jsforcursor = '// The call to urljump can be slow, so we set the wait cursor' . "\n";
5670 $jsforcursor .= 'jQuery("html,body,#id-container").addClass("cursorwait");' . "\n";
5671 }
5672
5673 $postconfirmas = 'GET';
5674
5675 $formconfirm .= '
5676 resizable: false,
5677 height: "' . $height . '",
5678 width: "' . $width . '",
5679 modal: true,
5680 closeOnEscape: false,
5681 buttons: {
5682 "' . dol_escape_js($langs->transnoentities($labelbuttonyes)) . '": function() {
5683 var options = "token=' . urlencode(newToken()) . '";
5684 var inputok = ' . json_encode($inputok) . '; /* List of fields into form */
5685 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5686 var pageyes = "' . dol_escape_js(!empty($pageyes) ? $pageyes : '') . '";
5687
5688 if (inputok.length > 0) {
5689 $.each(inputok, function(i, inputname) {
5690 var more = "";
5691 var inputvalue;
5692 if ($("input[name=\'" + inputname + "\']").attr("type") == "radio") {
5693 inputvalue = $("input[name=\'" + inputname + "\']:checked").val();
5694 } else {
5695 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5696 inputvalue = $("#" + inputname + more).val();
5697 }
5698 if (typeof inputvalue == "undefined") { inputvalue=""; }
5699 console.log("formconfirm check inputname="+inputname+" inputvalue="+inputvalue);
5700 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5701 });
5702 }
5703 var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "&") + options;
5704 if (pageyes.length > 0) {';
5705 if ($postconfirmas == 'GET') {
5706 $formconfirm .= 'location.href = urljump;';
5707 } else {
5708 $formconfirm .= $jsforcursor;
5709 $formconfirm .= 'var post = $.post(
5710 pageyes,
5711 options,
5712 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5713 );';
5714 }
5715 $formconfirm .= '
5716 console.log("after post ok");
5717 }
5718 $(this).dialog("close");
5719 },
5720 "' . dol_escape_js($langs->transnoentities($labelbuttonno)) . '": function() {
5721 var options = "token=' . urlencode(newToken()) . '";
5722 var inputko = ' . json_encode($inputko) . '; /* List of fields into form */
5723 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5724 var pageno="' . dol_escape_js(!empty($pageno) ? $pageno : '') . '";
5725 if (inputko.length > 0) {
5726 $.each(inputko, function(i, inputname) {
5727 var more = "";
5728 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5729 var inputvalue = $("#" + inputname + more).val();
5730 if (typeof inputvalue == "undefined") { inputvalue=""; }
5731 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5732 });
5733 }
5734 var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "&") + options;
5735 //alert(urljump);
5736 if (pageno.length > 0) {';
5737 if ($postconfirmas == 'GET') {
5738 $formconfirm .= 'location.href = urljump;';
5739 } else {
5740 $formconfirm .= $jsforcursor;
5741 $formconfirm .= 'var post = $.post(
5742 pageno,
5743 options,
5744 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5745 );';
5746 }
5747 $formconfirm .= '
5748 console.log("after post ko");
5749 }
5750 $(this).dialog("close");
5751 }
5752 }
5753 }
5754 );
5755
5756 var button = "' . $button . '";
5757 if (button.length > 0) {
5758 $( "#" + button ).click(function() {
5759 $("#' . $dialogconfirm . '").dialog("open");
5760 });
5761 }
5762 });
5763 });
5764 </script>';
5765 $formconfirm .= "<!-- end ajax formconfirm -->\n";
5766 } else {
5767 $formconfirm .= "\n<!-- begin formconfirm page=" . dol_escape_htmltag($page) . " -->\n";
5768
5769 if (empty($disableformtag)) {
5770 $formconfirm .= '<form method="POST" action="' . $page . '" class="notoptoleftroright">' . "\n";
5771 }
5772
5773 $formconfirm .= '<input type="hidden" name="action" value="' . $action . '">' . "\n";
5774 $formconfirm .= '<input type="hidden" name="token" value="' . newToken() . '">' . "\n";
5775
5776 $formconfirm .= '<table class="valid centpercent">' . "\n";
5777
5778 // Line title
5779 $formconfirm .= '<tr class="validtitre"><td class="validtitre" colspan="2">';
5780 $formconfirm .= img_picto('', 'pictoconfirm') . ' ' . $title;
5781 $formconfirm .= '</td></tr>' . "\n";
5782
5783 // Line text
5784 if (is_array($formquestion) && array_key_exists('text', $formquestion) && !empty($formquestion['text'])) {
5785 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . $formquestion['text'] . '</td></tr>' . "\n";
5786 }
5787
5788 // Line form fields
5789 if ($more) {
5790 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . "\n";
5791 $formconfirm .= $more;
5792 $formconfirm .= '</td></tr>' . "\n";
5793 }
5794
5795 // Line with question
5796 $formconfirm .= '<tr class="valid">';
5797 $formconfirm .= '<td class="valid">' . $question . '</td>';
5798 $formconfirm .= '<td class="valid center">';
5799 $formconfirm .= $this->selectyesno("confirm", $newselectedchoice, 0, false, 0, 0, 'marginleftonly marginrightonly', $labelbuttonyes, $labelbuttonno);
5800 $formconfirm .= '<input class="button valignmiddle confirmvalidatebutton small" type="submit" value="' . $langs->trans("Validate") . '">';
5801 $formconfirm .= '</td>';
5802 $formconfirm .= '</tr>' . "\n";
5803
5804 $formconfirm .= '</table>' . "\n";
5805
5806 if (empty($disableformtag)) {
5807 $formconfirm .= "</form>\n";
5808 }
5809 $formconfirm .= '<br>';
5810
5811 if (!empty($conf->use_javascript_ajax)) {
5812 $formconfirm .= '<!-- code to disable button to avoid double clic -->';
5813 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5814 $formconfirm .= '
5815 $(document).ready(function () {
5816 $(".confirmvalidatebutton").on("click", function() {
5817 console.log("We click on button confirmvalidatebutton");
5818 $(this).attr("disabled", "disabled");
5819 setTimeout(\'$(".confirmvalidatebutton").removeAttr("disabled")\', 3000);
5820 //console.log($(this).closest("form"));
5821 $(this).closest("form").submit();
5822 });
5823 });
5824 ';
5825 $formconfirm .= '</script>' . "\n";
5826 }
5827
5828 $formconfirm .= "<!-- end formconfirm -->\n";
5829 }
5830
5831 return $formconfirm;
5832 }
5833
5834
5835 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5836
5852 public function form_project($page, $socid, $selected = '', $htmlname = 'projectid', $discard_closed = 0, $maxlength = 20, $forcefocus = 0, $nooutput = 0, $textifnoproject = '', $morecss = '')
5853 {
5854 // phpcs:enable
5855 global $langs;
5856
5857 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
5858 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
5859
5860 $out = '';
5861
5862 $formproject = new FormProjets($this->db);
5863
5864 $langs->load("project");
5865 if ($htmlname != "none") {
5866 $out .= '<form method="post" action="' . $page . '">';
5867 $out .= '<input type="hidden" name="action" value="classin">';
5868 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5869 $out .= $formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1, 0, $morecss);
5870 $out .= '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5871 $out .= '</form>';
5872 } else {
5873 $out .= '<span class="project_head_block">';
5874 if ($selected) {
5875 $projet = new Project($this->db);
5876 $projet->fetch($selected);
5877 $out .= $projet->getNomUrl(0, '', 1);
5878 } else {
5879 $out .= '<span class="opacitymedium">' . $textifnoproject . '</span>';
5880 }
5881 $out .= '</span>';
5882 }
5883
5884 if (empty($nooutput)) {
5885 print $out;
5886 return '';
5887 }
5888 return $out;
5889 }
5890
5891 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5892
5908 public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0, $type = '', $filtertype = -1, $deposit_percent = -1, $nooutput = 0)
5909 {
5910 // phpcs:enable
5911 global $langs;
5912
5913 $out = '';
5914
5915 if ($htmlname != "none") {
5916 $out .= '<form method="POST" action="' . $page . '">';
5917 $out .= '<input type="hidden" name="action" value="setconditions">';
5918 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5919 if ($type) {
5920 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5921 }
5922 $out .= $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, 0, '', $deposit_percent);
5923 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5924 $out .= '</form>';
5925 } else {
5926 if ($selected) {
5928 if (isset($this->cache_conditions_paiements[$selected])) {
5929 $label = $this->cache_conditions_paiements[$selected]['label'];
5930
5931 if (!empty($this->cache_conditions_paiements[$selected]['deposit_percent'])) {
5932 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $this->cache_conditions_paiements[$selected]['deposit_percent'], $label);
5933 }
5934
5935 $out .= $label;
5936 } else {
5937 $langs->load('errors');
5938 $out .= $langs->trans('ErrorNotInDictionaryPaymentConditions');
5939 }
5940 } else {
5941 $out .= '&nbsp;';
5942 }
5943 }
5944
5945 if (empty($nooutput)) {
5946 print $out;
5947 return '';
5948 }
5949 return $out;
5950 }
5951
5952 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5953
5963 public function form_availability($page, $selected = '', $htmlname = 'availability', $addempty = 0)
5964 {
5965 // phpcs:enable
5966 global $langs;
5967 if ($htmlname != "none") {
5968 print '<form method="post" action="' . $page . '">';
5969 print '<input type="hidden" name="action" value="setavailability">';
5970 print '<input type="hidden" name="token" value="' . newToken() . '">';
5971 $this->selectAvailabilityDelay($selected, $htmlname, -1, $addempty);
5972 print '<input type="submit" name="modify" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5973 print '<input type="submit" name="cancel" class="button smallpaddingimp" value="' . $langs->trans("Cancel") . '">';
5974 print '</form>';
5975 } else {
5976 if ($selected) {
5977 $this->load_cache_availability();
5978 print $this->cache_availability[$selected]['label'];
5979 } else {
5980 print "&nbsp;";
5981 }
5982 }
5983 }
5984
5995 public function formInputReason($page, $selected = '', $htmlname = 'demandreason', $addempty = 0)
5996 {
5997 global $langs;
5998 if ($htmlname != "none") {
5999 print '<form method="post" action="' . $page . '">';
6000 print '<input type="hidden" name="action" value="setdemandreason">';
6001 print '<input type="hidden" name="token" value="' . newToken() . '">';
6002 $this->selectInputReason($selected, $htmlname, -1, $addempty);
6003 print '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
6004 print '</form>';
6005 } else {
6006 if ($selected) {
6007 $this->loadCacheInputReason();
6008 foreach ($this->cache_demand_reason as $key => $val) {
6009 if ($val['id'] == $selected) {
6010 print $val['label'];
6011 break;
6012 }
6013 }
6014 } else {
6015 print "&nbsp;";
6016 }
6017 }
6018 }
6019
6020 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6021
6035 public function form_date($page, $selected, $htmlname, $displayhour = 0, $displaymin = 0, $nooutput = 0, $type = '')
6036 {
6037 // phpcs:enable
6038 global $langs;
6039
6040 $ret = '';
6041
6042 if ($htmlname != "none") {
6043 $ret .= '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
6044 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
6045 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
6046 if ($type) {
6047 $ret .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
6048 }
6049 $ret .= '<table class="nobordernopadding">';
6050 $ret .= '<tr><td>';
6051 $ret .= $this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form' . $htmlname, 1, 0);
6052 $ret .= '</td>';
6053 $ret .= '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6054 $ret .= '</tr></table></form>';
6055 } else {
6056 if ($displayhour) {
6057 $ret .= dol_print_date($selected, 'dayhour');
6058 } else {
6059 $ret .= dol_print_date($selected, 'day');
6060 }
6061 }
6062
6063 if (empty($nooutput)) {
6064 print $ret;
6065 }
6066 return $ret;
6067 }
6068
6069
6070 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6071
6082 public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = array(), $include = array())
6083 {
6084 // phpcs:enable
6085 global $langs;
6086
6087 if ($htmlname != "none") {
6088 print '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
6089 print '<input type="hidden" name="action" value="set' . $htmlname . '">';
6090 print '<input type="hidden" name="token" value="' . newToken() . '">';
6091 print $this->select_dolusers($selected, $htmlname, 1, $exclude, 0, $include);
6092 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6093 print '</form>';
6094 } else {
6095 if ($selected) {
6096 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
6097 $theuser = new User($this->db);
6098 $theuser->fetch($selected);
6099 print $theuser->getNomUrl(1);
6100 } else {
6101 print "&nbsp;";
6102 }
6103 }
6104 }
6105
6106
6107 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6108
6122 public function form_modes_reglement($page, $selected = '', $htmlname = 'mode_reglement_id', $filtertype = '', $active = 1, $addempty = 0, $type = '', $nooutput = 0)
6123 {
6124 // phpcs:enable
6125 global $langs;
6126
6127 $out = '';
6128 if ($htmlname != "none") {
6129 $out .= '<form method="POST" action="' . $page . '">';
6130 $out .= '<input type="hidden" name="action" value="setmode">';
6131 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6132 if ($type) {
6133 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
6134 }
6135 $out .= $this->select_types_paiements($selected, $htmlname, $filtertype, 0, $addempty, 0, 0, $active, '', 1);
6136 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6137 $out .= '</form>';
6138 } else {
6139 if ($selected) {
6141 $out .= $this->cache_types_paiements[$selected]['label'];
6142 } else {
6143 $out .= "&nbsp;";
6144 }
6145 }
6146
6147 if ($nooutput) {
6148 return $out;
6149 } else {
6150 print $out;
6151 }
6152 return '';
6153 }
6154
6165 public function formSelectTransportMode($page, $selected = '', $htmlname = 'transport_mode_id', $active = 1, $addempty = 0)
6166 {
6167 global $langs;
6168 if ($htmlname != "none") {
6169 print '<form method="POST" action="' . $page . '">';
6170 print '<input type="hidden" name="action" value="settransportmode">';
6171 print '<input type="hidden" name="token" value="' . newToken() . '">';
6172 $this->selectTransportMode($selected, $htmlname, 0, $addempty, 0, 0, $active);
6173 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6174 print '</form>';
6175 } else {
6176 if ($selected) {
6178 print $this->cache_transport_mode[$selected]['label'];
6179 } else {
6180 print "&nbsp;";
6181 }
6182 }
6183 }
6184
6185 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6186
6195 public function form_multicurrency_code($page, $selected = '', $htmlname = 'multicurrency_code')
6196 {
6197 // phpcs:enable
6198 global $langs;
6199 if ($htmlname != "none") {
6200 print '<form method="POST" action="' . $page . '">';
6201 print '<input type="hidden" name="action" value="setmulticurrencycode">';
6202 print '<input type="hidden" name="token" value="' . newToken() . '">';
6203 print $this->selectMultiCurrency($selected, $htmlname, 0);
6204 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6205 print '</form>';
6206 } else {
6207 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6208 print !empty($selected) ? currency_name($selected, 1) : '&nbsp;';
6209 }
6210 }
6211
6212 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6213
6223 public function form_multicurrency_rate($page, $rate = 0.0, $htmlname = 'multicurrency_tx', $currency = '')
6224 {
6225 // phpcs:enable
6226 global $langs, $mysoc, $conf;
6227
6228 if ($htmlname != "none") {
6229 print '<form method="POST" action="' . $page . '">';
6230 print '<input type="hidden" name="action" value="setmulticurrencyrate">';
6231 print '<input type="hidden" name="token" value="' . newToken() . '">';
6232 print '<input type="text" class="maxwidth100" name="' . $htmlname . '" value="' . (!empty($rate) ? price(price2num($rate, 'CU')) : 1) . '" /> ';
6233 print '<select name="calculation_mode">';
6234 print '<option value="1">Change ' . $langs->trans("PriceUHT") . ' of lines</option>';
6235 print '<option value="2">Change ' . $langs->trans("PriceUHTCurrency") . ' of lines</option>';
6236 print '</select> ';
6237 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6238 print '</form>';
6239 } else {
6240 if (!empty($rate)) {
6241 print price($rate, 1, $langs, 0, 0);
6242 if ($currency && $rate != 1) {
6243 print ' &nbsp; (' . price($rate, 1, $langs, 0, 0) . ' ' . $currency . ' = 1 ' . $conf->currency . ')';
6244 }
6245 } else {
6246 print 1;
6247 }
6248 }
6249 }
6250
6251
6252 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6253
6269 public function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter = '', $maxvalue = 0, $more = '', $hidelist = 0, $discount_type = 0)
6270 {
6271 // phpcs:enable
6272 global $conf, $langs;
6273 if ($htmlname != "none") {
6274 print '<form method="post" action="' . $page . '">';
6275 print '<input type="hidden" name="action" value="setabsolutediscount">';
6276 print '<input type="hidden" name="token" value="' . newToken() . '">';
6277 print '<div class="inline-block">';
6278 if (!empty($discount_type)) {
6279 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
6280 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL") {
6281 $translationKey = 'HasAbsoluteDiscountFromSupplier'; // If we want deposit to be subtracted to payments only and not to total of final invoice
6282 } else {
6283 $translationKey = 'HasCreditNoteFromSupplier';
6284 }
6285 } else {
6286 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6287 $translationKey = 'HasAbsoluteDiscountFromSupplier';
6288 } else {
6289 $translationKey = 'HasCreditNoteFromSupplier';
6290 }
6291 }
6292 } else {
6293 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
6294 if (!$filter || $filter == "fk_facture_source IS NULL") {
6295 $translationKey = 'CompanyHasAbsoluteDiscount'; // If we want deposit to be subtracted to payments only and not to total of final invoice
6296 } else {
6297 $translationKey = 'CompanyHasCreditNote';
6298 }
6299 } else {
6300 if (!$filter || $filter == "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6301 $translationKey = 'CompanyHasAbsoluteDiscount';
6302 } else {
6303 $translationKey = 'CompanyHasCreditNote';
6304 }
6305 }
6306 }
6307 print $langs->trans($translationKey, price($amount, 0, $langs, 0, 0, -1, $conf->currency));
6308 if (empty($hidelist)) {
6309 print ' ';
6310 }
6311 print '</div>';
6312 if (empty($hidelist)) {
6313 print '<div class="inline-block" style="padding-right: 10px">';
6314 $newfilter = 'discount_type=' . intval($discount_type);
6315 if (!empty($discount_type)) {
6316 $newfilter .= ' AND fk_invoice_supplier IS NULL AND fk_invoice_supplier_line IS NULL'; // Supplier discounts available
6317 } else {
6318 $newfilter .= ' AND fk_facture IS NULL AND fk_facture_line IS NULL'; // Customer discounts available
6319 }
6320 if ($filter) {
6321 $newfilter .= ' AND (' . $filter . ')';
6322 }
6323 // output the combo of discounts
6324 $nbqualifiedlines = $this->select_remises($selected, $htmlname, $newfilter, $socid, $maxvalue);
6325 if ($nbqualifiedlines > 0) {
6326 print ' &nbsp; <input type="submit" class="button smallpaddingimp" value="' . dol_escape_htmltag($langs->trans("UseLine")) . '"';
6327 if (!empty($discount_type) && $filter && $filter != "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6328 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6329 }
6330 if (empty($discount_type) && $filter && $filter != "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6331 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6332 }
6333
6334 print '>';
6335 }
6336 print '</div>';
6337 }
6338 if ($more) {
6339 print '<div class="inline-block">';
6340 print $more;
6341 print '</div>';
6342 }
6343 print '</form>';
6344 } else {
6345 if ($selected) {
6346 print $selected;
6347 } else {
6348 print "0";
6349 }
6350 }
6351 }
6352
6353
6354 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6355
6365 public function form_contacts($page, $societe, $selected = '', $htmlname = 'contactid')
6366 {
6367 // phpcs:enable
6368 global $langs;
6369
6370 if ($htmlname != "none") {
6371 print '<form method="post" action="' . $page . '">';
6372 print '<input type="hidden" name="action" value="set_contact">';
6373 print '<input type="hidden" name="token" value="' . newToken() . '">';
6374 print '<table class="nobordernopadding">';
6375 print '<tr><td>';
6376 print $this->selectcontacts($societe->id, $selected, $htmlname);
6377 $num = $this->num;
6378 if ($num == 0) {
6379 $addcontact = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("AddContact") : $langs->trans("AddContactAddress"));
6380 print '<a href="' . DOL_URL_ROOT . '/contact/card.php?socid=' . $societe->id . '&amp;action=create&amp;backtoreferer=1">' . $addcontact . '</a>';
6381 }
6382 print '</td>';
6383 print '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6384 print '</tr></table></form>';
6385 } else {
6386 if ($selected) {
6387 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
6388 $contact = new Contact($this->db);
6389 $contact->fetch($selected);
6390 print $contact->getFullName($langs);
6391 } else {
6392 print "&nbsp;";
6393 }
6394 }
6395 }
6396
6397 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6398
6415 public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0, $excludeids = array(), $textifnothirdparty = '')
6416 {
6417 // phpcs:enable
6418 global $langs;
6419
6420 $out = '';
6421 if ($htmlname != "none") {
6422 $out .= '<form method="post" action="' . $page . '">';
6423 $out .= '<input type="hidden" name="action" value="set_thirdparty">';
6424 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6425 $out .= $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, 0, 'minwidth100', '', '', 1, array(), false, $excludeids);
6426 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6427 $out .= '</form>';
6428 } else {
6429 if ($selected) {
6430 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
6431 $soc = new Societe($this->db);
6432 $soc->fetch($selected);
6433 $out .= $soc->getNomUrl(0, '');
6434 } else {
6435 $out .= '<span class="opacitymedium">' . $textifnothirdparty . '</span>';
6436 }
6437 }
6438
6439 if ($nooutput) {
6440 return $out;
6441 } else {
6442 print $out;
6443 }
6444
6445 return '';
6446 }
6447
6448 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6449
6458 public function select_currency($selected = '', $htmlname = 'currency_id')
6459 {
6460 // phpcs:enable
6461 print $this->selectCurrency($selected, $htmlname);
6462 }
6463
6473 public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0, $useempty = '')
6474 {
6475 global $langs, $user;
6476
6477 $langs->loadCacheCurrencies('');
6478
6479 $out = '';
6480
6481 if ($selected == 'euro' || $selected == 'euros') {
6482 $selected = 'EUR'; // Pour compatibilite
6483 }
6484
6485 $out .= '<select class="flat maxwidth200onsmartphone minwidth300" name="' . $htmlname . '" id="' . $htmlname . '">';
6486 if ($useempty) {
6487 $out .= '<option value="-1" selected></option>';
6488 }
6489 foreach ($langs->cache_currencies as $code_iso => $currency) {
6490 $labeltoshow = $currency['label'];
6491 if ($mode == 1) {
6492 $labeltoshow .= ' <span class="opacitymedium">(' . $code_iso . ')</span>';
6493 } else {
6494 $labeltoshow .= ' <span class="opacitymedium">(' . $langs->getCurrencySymbol($code_iso) . ')</span>';
6495 }
6496
6497 if ($selected && $selected == $code_iso) {
6498 $out .= '<option value="' . $code_iso . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6499 } else {
6500 $out .= '<option value="' . $code_iso . '" data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6501 }
6502 $out .= $labeltoshow;
6503 $out .= '</option>';
6504 }
6505 $out .= '</select>';
6506 if ($user->admin) {
6507 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
6508 }
6509
6510 // Make select dynamic
6511 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6512 $out .= ajax_combobox($htmlname);
6513
6514 return $out;
6515 }
6516
6529 public function selectMultiCurrency($selected = '', $htmlname = 'multicurrency_code', $useempty = 0, $filter = '', $excludeConfCurrency = false, $morecss = '')
6530 {
6531 global $conf, $langs;
6532
6533 $langs->loadCacheCurrencies(''); // Load ->cache_currencies
6534
6535 $TCurrency = array();
6536
6537 $sql = "SELECT code FROM " . $this->db->prefix() . "multicurrency";
6538 $sql .= " WHERE entity IN ('" . getEntity('multicurrency') . "')";
6539 if ($filter) {
6540 $sql .= " AND " . $filter;
6541 }
6542 $resql = $this->db->query($sql);
6543 if ($resql) {
6544 while ($obj = $this->db->fetch_object($resql)) {
6545 $TCurrency[$obj->code] = $obj->code;
6546 }
6547 }
6548
6549 $out = '';
6550 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
6551 if ($useempty) {
6552 $out .= '<option value="">&nbsp;</option>';
6553 }
6554 // If company current currency not in table, we add it into list. Should always be available.
6555 if (!in_array($conf->currency, $TCurrency) && !$excludeConfCurrency) {
6556 $TCurrency[$conf->currency] = $conf->currency;
6557 }
6558 if (count($TCurrency) > 0) {
6559 foreach ($langs->cache_currencies as $code_iso => $currency) {
6560 if (isset($TCurrency[$code_iso])) {
6561 if (!empty($selected) && $selected == $code_iso) {
6562 $out .= '<option value="' . $code_iso . '" selected="selected">';
6563 } else {
6564 $out .= '<option value="' . $code_iso . '">';
6565 }
6566
6567 $out .= $currency['label'];
6568 $out .= ' (' . $langs->getCurrencySymbol($code_iso) . ')';
6569 $out .= '</option>';
6570 }
6571 }
6572 }
6573
6574 $out .= '</select>';
6575
6576 // Make select dynamic
6577 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6578 $out .= ajax_combobox($htmlname);
6579
6580 return $out;
6581 }
6582
6583 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6584
6591 public function load_cache_vatrates($country_code)
6592 {
6593 // phpcs:enable
6594 global $langs, $user;
6595
6596 $num = count($this->cache_vatrates);
6597 if ($num > 0) {
6598 return $num; // Cache already loaded
6599 }
6600
6601 dol_syslog(__METHOD__, LOG_DEBUG);
6602
6603 $sql = "SELECT t.rowid, t.type_vat, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
6604 $sql .= " FROM ".$this->db->prefix()."c_tva as t, ".$this->db->prefix()."c_country as c";
6605 $sql .= " WHERE t.fk_pays = c.rowid";
6606 $sql .= " AND t.active > 0";
6607 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
6608 $sql .= " AND c.code IN (" . $this->db->sanitize($country_code, 1) . ")";
6609 $sql .= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC";
6610
6611 $resql = $this->db->query($sql);
6612 if ($resql) {
6613 $num = $this->db->num_rows($resql);
6614 if ($num) {
6615 for ($i = 0; $i < $num; $i++) {
6616 $obj = $this->db->fetch_object($resql);
6617
6618 $tmparray = array();
6619 $tmparray['rowid'] = $obj->rowid;
6620 $tmparray['type_vat'] = $obj->type_vat;
6621 $tmparray['code'] = $obj->code;
6622 $tmparray['txtva'] = $obj->taux;
6623 $tmparray['nprtva'] = $obj->recuperableonly;
6624 $tmparray['localtax1'] = $obj->localtax1;
6625 $tmparray['localtax1_type'] = $obj->localtax1_type;
6626 $tmparray['localtax2'] = $obj->localtax2;
6627 $tmparray['localtax2_type'] = $obj->localtax1_type;
6628 $tmparray['label'] = $obj->taux . '%' . ($obj->code ? ' (' . $obj->code . ')' : ''); // Label must contains only 0-9 , . % or *
6629 $tmparray['labelallrates'] = $obj->taux . '/' . ($obj->localtax1 ? $obj->localtax1 : '0') . '/' . ($obj->localtax2 ? $obj->localtax2 : '0') . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
6630 $positiverates = '';
6631 if ($obj->taux) {
6632 $positiverates .= ($positiverates ? '/' : '') . $obj->taux;
6633 }
6634 if ($obj->localtax1) {
6635 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax1;
6636 }
6637 if ($obj->localtax2) {
6638 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax2;
6639 }
6640 if (empty($positiverates)) {
6641 $positiverates = '0';
6642 }
6643 $tmparray['labelpositiverates'] = $positiverates . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
6644
6645 $this->cache_vatrates[$obj->rowid] = $tmparray;
6646 }
6647
6648 return $num;
6649 } else {
6650 $this->error = '<span class="error">';
6651 $this->error .= $langs->trans("ErrorNoVATRateDefinedForSellerCountry", $country_code);
6652 $reg = array();
6653 if (!empty($user) && $user->admin && preg_match('/\'(..)\'/', $country_code, $reg)) {
6654 $langs->load("errors");
6655 $new_country_code = $reg[1];
6656 $country_id = dol_getIdFromCode($this->db, $new_country_code, 'c_pays', 'code', 'rowid');
6657 $this->error .= '<br>'.$langs->trans("ErrorFixThisHere", DOL_URL_ROOT.'/admin/dict.php?id=10'.($country_id > 0 ? '&countryidforinsert='.$country_id : ''));
6658 }
6659 $this->error .= '</span>';
6660 return -1;
6661 }
6662 } else {
6663 $this->error = '<span class="error">' . $this->db->error() . '</span>';
6664 return -2;
6665 }
6666 }
6667
6668 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6669
6692 public function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = null, $societe_acheteuse = null, $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0, $type_vat = 0)
6693 {
6694 // phpcs:enable
6695 global $langs, $mysoc;
6696
6697 $langs->load('errors');
6698
6699 $return = '';
6700
6701 // Define defaultnpr, defaultttx and defaultcode
6702 $defaultnpr = ($info_bits & 0x01);
6703 $defaultnpr = (preg_match('/\*/', $selectedrate) ? 1 : $defaultnpr);
6704 $defaulttx = str_replace('*', '', $selectedrate);
6705 $defaultcode = '';
6706 $reg = array();
6707 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6708 $defaultcode = $reg[1];
6709 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6710 }
6711 //var_dump($selectedrate.'-'.$defaulttx.'-'.$defaultnpr.'-'.$defaultcode);
6712
6713 // Check parameters
6714 if (is_object($societe_vendeuse) && !$societe_vendeuse->country_code) {
6715 if ($societe_vendeuse->id == $mysoc->id) {
6716 $return .= '<span class="error">' . $langs->trans("ErrorYourCountryIsNotDefined") . '</span>';
6717 } else {
6718 $return .= '<span class="error">' . $langs->trans("ErrorSupplierCountryIsNotDefined") . '</span>';
6719 }
6720 return $return;
6721 }
6722
6723 //var_dump($societe_acheteuse);
6724 //print "name=$name, selectedrate=$selectedrate, seller=".$societe_vendeuse->country_code." buyer=".$societe_acheteuse->country_code." buyer is company=".$societe_acheteuse->isACompany()." idprod=$idprod, info_bits=$info_bits type=$type";
6725 //exit;
6726
6727 // Define list of countries to use to search VAT rates to show
6728 // First we defined code_country to use to find list
6729 if (is_object($societe_vendeuse)) {
6730 $code_country = "'" . $societe_vendeuse->country_code . "'";
6731 } else {
6732 $code_country = "'" . $mysoc->country_code . "'"; // Pour compatibilite ascendente
6733 }
6734 if (getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC')) { // If option to have vat for end customer for services is on
6735 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6736 // If SERVICE_ARE_ECOMMERCE_200238EC=1 combo list vat rate of purchaser and seller countries
6737 // If SERVICE_ARE_ECOMMERCE_200238EC=2 combo list only the vat rate of the purchaser country
6738 $selectVatComboMode = getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC');
6739 if (is_object($societe_vendeuse) && is_object($societe_acheteuse) && isInEEC($societe_vendeuse) && isInEEC($societe_acheteuse) && !$societe_acheteuse->isACompany()) {
6740 // We also add the buyer country code
6741 if (is_numeric($type)) {
6742 if ($type == 1) { // We know product is a service
6743 switch ($selectVatComboMode) {
6744 case '1':
6745 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6746 break;
6747 case '2':
6748 $code_country = "'" . $societe_acheteuse->country_code . "'";
6749 break;
6750 }
6751 }
6752 } elseif (!$idprod) { // We don't know type of product
6753 switch ($selectVatComboMode) {
6754 case '1':
6755 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6756 break;
6757 case '2':
6758 $code_country = "'" . $societe_acheteuse->country_code . "'";
6759 break;
6760 }
6761 } else {
6762 $prodstatic = new Product($this->db);
6763 $prodstatic->fetch($idprod);
6764 if ($prodstatic->type == Product::TYPE_SERVICE) { // We know product is a service
6765 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6766 }
6767 }
6768 }
6769 }
6770
6771 // Now we load the list of VAT
6772 $this->load_cache_vatrates($code_country); // If no vat defined, return -1 with message into this->error
6773
6774 // Keep only the VAT qualified for $type_vat
6775 $arrayofvatrates = array();
6776 foreach ($this->cache_vatrates as $cachevalue) {
6777 if (empty($cachevalue['type_vat']) || $cachevalue['type_vat'] == $type_vat) {
6778 $arrayofvatrates[] = $cachevalue;
6779 }
6780 }
6781
6782 $num = count($arrayofvatrates);
6783
6784 if ($num > 0) {
6785 // Define the rate to pre-select (if defaulttx not forced so is -1 or '')
6786 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6787 // Define a default thirdparty to use if the seller or buyer is not defined
6788 $tmpthirdparty = new Societe($this->db);
6789 $tmpthirdparty->country_code = $mysoc->country_code;
6790
6791 $defaulttx = get_default_tva(is_object($societe_vendeuse) ? $societe_vendeuse : $tmpthirdparty, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6792 $defaultnpr = get_default_npr(is_object($societe_vendeuse) ? $societe_vendeuse : $tmpthirdparty, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6793
6794 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6795 $defaultcode = $reg[1];
6796 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6797 }
6798 if (empty($defaulttx)) {
6799 $defaultnpr = 0;
6800 }
6801 }
6802
6803 // If we fails to find a default vat rate, we take the last one in list
6804 // Because they are sorted in ascending order, the last one will be the higher one (we suppose the higher one is the current rate)
6805 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6806 if (!getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS')) {
6807 // We take the last one found in list
6808 $defaulttx = $arrayofvatrates[$num - 1]['txtva'];
6809 } else {
6810 // We will use the rate defined into MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS
6811 $defaulttx = '';
6812 if (getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS') != 'none') {
6813 $defaulttx = getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS');
6814 }
6815 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6816 $defaultcode = $reg[1];
6817 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6818 }
6819 }
6820 }
6821
6822 // Disabled if seller is not subject to VAT
6823 $disabled = false;
6824 $title = '';
6825 if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0") {
6826 // Override/enable VAT for expense report regardless of global setting - needed if expense report used for business expenses instead
6827 // of using supplier invoices (this is a very bad idea !)
6828 if (!getDolGlobalString('EXPENSEREPORT_OVERRIDE_VAT')) {
6829 $title = ' title="' . dol_escape_htmltag($langs->trans('VATIsNotUsed')) . '"';
6830 $disabled = true;
6831 }
6832 }
6833
6834 if (!$options_only) {
6835 $return .= '<select class="flat minwidth75imp maxwidth100 right" id="' . $htmlname . '" name="' . $htmlname . '"' . ($disabled ? ' disabled' : '') . $title . '>';
6836 }
6837
6838 $selectedfound = false;
6839 foreach ($arrayofvatrates as $rate) {
6840 // Keep only 0 if seller is not subject to VAT
6841 if ($disabled && $rate['txtva'] != 0) {
6842 continue;
6843 }
6844
6845 // Define key to use into select list
6846 $key = $rate['txtva'];
6847 $key .= $rate['nprtva'] ? '*' : '';
6848 if ($mode > 0 && $rate['code']) {
6849 $key .= ' (' . $rate['code'] . ')';
6850 }
6851 if ($mode < 0) {
6852 $key = $rate['rowid'];
6853 }
6854
6855 $return .= '<option value="' . $key . '"';
6856 if (!$selectedfound) {
6857 if ($defaultcode) { // If defaultcode is defined, we used it in priority to select combo option instead of using rate+npr flag
6858 if ($defaultcode == $rate['code']) {
6859 $return .= ' selected';
6860 $selectedfound = true;
6861 }
6862 } elseif ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr) {
6863 $return .= ' selected';
6864 $selectedfound = true;
6865 }
6866 }
6867 $return .= '>';
6868
6869 // Show label of VAT
6870 if ($mysoc->country_code == 'IN' || getDolGlobalString('MAIN_VAT_LABEL_IS_POSITIVE_RATES')) {
6871 // Label with all localtax and code. For example: x.y / a.b / c.d (CODE)'
6872 $return .= $rate['labelpositiverates'];
6873 } else {
6874 // Simple label
6875 $return .= vatrate($rate['label']);
6876 }
6877
6878 //$return.=($rate['code']?' '.$rate['code']:'');
6879 $return .= (empty($rate['code']) && $rate['nprtva']) ? ' *' : ''; // We show the * (old behaviour only if new vat code is not used)
6880
6881 $return .= '</option>';
6882 }
6883
6884 if (!$options_only) {
6885 $return .= '</select>';
6886 //$return .= ajax_combobox($htmlname); // This break for the moment the dynamic autoselection of a value when selecting a product in object lines
6887 }
6888 } else {
6889 $return .= $this->error;
6890 }
6891
6892 $this->num = $num;
6893 return $return;
6894 }
6895
6896
6897 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6898
6923 public function select_date($set_time = '', $prefix = 're', $h = 0, $m = 0, $empty = 0, $form_name = "", $d = 1, $addnowlink = 0, $nooutput = 0, $disabled = 0, $fullday = 0, $addplusone = '', $adddateof = '')
6924 {
6925 // phpcs:enable
6926 dol_syslog(__METHOD__ . ': using select_date is deprecated. Use selectDate instead.', LOG_WARNING);
6927 $retstring = $this->selectDate($set_time, $prefix, $h, $m, $empty, $form_name, $d, $addnowlink, $disabled, $fullday, $addplusone, $adddateof);
6928 if (!empty($nooutput)) {
6929 return $retstring;
6930 }
6931 print $retstring;
6932
6933 return '';
6934 }
6935
6951 public function selectDateToDate($set_time = '', $set_time_end = '', $prefix = 're', $empty = 0, $forcenewline = 0)
6952 {
6953 global $langs;
6954
6955 $ret = $this->selectDate($set_time, $prefix . '_start', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("from"), 'tzuserrel');
6956 if ($forcenewline) {
6957 $ret .= '<br>';
6958 }
6959 $ret .= $this->selectDate($set_time_end, $prefix . '_end', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"), 'tzuserrel');
6960 return $ret;
6961 }
6962
6990 public function selectDate($set_time = '', $prefix = 're', $h = 0, $m = 0, $empty = 0, $form_name = "", $d = 1, $addnowlink = 0, $disabled = 0, $fullday = '', $addplusone = '', $adddateof = '', $openinghours = '', $stepminutes = 1, $labeladddateof = '', $placeholder = '', $gm = 'auto')
6991 {
6992 global $conf, $langs;
6993
6994 if ($gm === 'auto') {
6995 $gm = (empty($conf) ? 'tzserver' : $conf->tzuserinputkey);
6996 }
6997
6998 $retstring = '';
6999
7000 if ($prefix == '') {
7001 $prefix = 're';
7002 }
7003 if ($h == '') {
7004 $h = 0;
7005 }
7006 if ($m == '') {
7007 $m = 0;
7008 }
7009 $emptydate = 0;
7010 $emptyhours = 0;
7011 if ($stepminutes <= 0 || $stepminutes > 30) {
7012 $stepminutes = 1;
7013 }
7014 if ($empty == 1) {
7015 $emptydate = 1;
7016 $emptyhours = 1;
7017 }
7018 if ($empty == 2) {
7019 $emptydate = 0;
7020 $emptyhours = 1;
7021 }
7022 $orig_set_time = $set_time;
7023
7024 if ($set_time === '' && $emptydate == 0) {
7025 include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7026 if ($gm == 'tzuser' || $gm == 'tzuserrel') {
7027 $set_time = dol_now($gm);
7028 } else {
7029 $set_time = dol_now('tzuser') - (getServerTimeZoneInt('now') * 3600); // set_time must be relative to PHP server timezone
7030 }
7031 }
7032
7033 // Analysis of the pre-selection date
7034 $reg = array();
7035 $shour = '';
7036 $smin = '';
7037 $ssec = '';
7038 if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', $set_time, $reg)) { // deprecated usage
7039 // Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'
7040 $syear = (!empty($reg[1]) ? $reg[1] : '');
7041 $smonth = (!empty($reg[2]) ? $reg[2] : '');
7042 $sday = (!empty($reg[3]) ? $reg[3] : '');
7043 $shour = (!empty($reg[4]) ? $reg[4] : '');
7044 $smin = (!empty($reg[5]) ? $reg[5] : '');
7045 } elseif (strval($set_time) != '' && $set_time != -1) {
7046 // set_time est un timestamps (0 possible)
7047 $syear = dol_print_date($set_time, "%Y", $gm);
7048 $smonth = dol_print_date($set_time, "%m", $gm);
7049 $sday = dol_print_date($set_time, "%d", $gm);
7050 if ($orig_set_time != '') {
7051 $shour = dol_print_date($set_time, "%H", $gm);
7052 $smin = dol_print_date($set_time, "%M", $gm);
7053 $ssec = dol_print_date($set_time, "%S", $gm);
7054 }
7055 } else {
7056 // Date est '' ou vaut -1
7057 $syear = '';
7058 $smonth = '';
7059 $sday = '';
7060 $shour = getDolGlobalString('MAIN_DEFAULT_DATE_HOUR', ($h == -1 ? '23' : ''));
7061 $smin = getDolGlobalString('MAIN_DEFAULT_DATE_MIN', ($h == -1 ? '59' : ''));
7062 $ssec = getDolGlobalString('MAIN_DEFAULT_DATE_SEC', ($h == -1 ? '59' : ''));
7063 }
7064 if ($h == 3 || $h == 4) {
7065 $shour = '';
7066 }
7067 if ($m == 3) {
7068 $smin = '';
7069 }
7070
7071 $nowgmt = dol_now('gmt');
7072 //var_dump(dol_print_date($nowgmt, 'dayhourinputnoreduce', 'tzuserrel'));
7073
7074 // You can set MAIN_POPUP_CALENDAR to 'eldy' or 'jquery'
7075 $usecalendar = 'combo';
7076 if (!empty($conf->use_javascript_ajax) && (!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') != "none")) {
7077 $usecalendar = ((!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') == 'eldy') ? 'jquery' : $conf->global->MAIN_POPUP_CALENDAR);
7078 }
7079 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7080 // If we use a text browser or screen reader, we use the 'combo' date selector
7081 $usecalendar = 'html';
7082 }
7083
7084 if ($d) {
7085 // Show date with popup
7086 if ($usecalendar != 'combo') {
7087 $formatted_date = '';
7088 //print "e".$set_time." t ".$conf->format_date_short;
7089 if (strval($set_time) != '' && $set_time != -1) {
7090 //$formatted_date=dol_print_date($set_time,$conf->format_date_short);
7091 $formatted_date = dol_print_date($set_time, $langs->trans("FormatDateShortInput"), $gm); // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7092 }
7093
7094 // Calendrier popup version eldy
7095 if ($usecalendar == "eldy") {
7096 // Input area to enter date manually
7097 $retstring .= '<input id="' . $prefix . '" name="' . $prefix . '" type="text" class="maxwidthdate center" maxlength="11" value="' . $formatted_date . '"';
7098 $retstring .= ($disabled ? ' disabled' : '');
7099 $retstring .= ' onChange="dpChangeDay(\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7100 $retstring .= ' autocomplete="off">';
7101
7102 // Icon calendar
7103 $retstringbuttom = '';
7104 if (!$disabled) {
7105 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons"';
7106 $base = DOL_URL_ROOT . '/core/';
7107 $retstringbuttom .= ' onClick="showDP(\'' . $base . '\',\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\',\'' . $langs->defaultlang . '\');"';
7108 $retstringbuttom .= '>' . img_object($langs->trans("SelectDate"), 'calendarday', 'class="datecallink"') . '</button>';
7109 } else {
7110 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
7111 }
7112 $retstring = $retstringbuttom . $retstring;
7113
7114 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
7115 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
7116 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
7117 } elseif ($usecalendar == 'jquery' || $usecalendar == 'html') {
7118 if (!$disabled && $usecalendar != 'html') {
7119 // Output javascript for datepicker
7120 $minYear = getDolGlobalInt('MIN_YEAR_SELECT_DATE', (idate('Y') - 100));
7121 $maxYear = getDolGlobalInt('MAX_YEAR_SELECT_DATE', (idate('Y') + 100));
7122
7123 $retstring .= '<script nonce="' . getNonce() . '" type="text/javascript">';
7124 $retstring .= "$(function(){ $('#" . $prefix . "').datepicker({
7125 dateFormat: '" . $langs->trans("FormatDateShortJQueryInput") . "',
7126 autoclose: true,
7127 todayHighlight: true,
7128 yearRange: '" . $minYear . ":" . $maxYear . "',";
7129 if (!empty($conf->dol_use_jmobile)) {
7130 $retstring .= "
7131 beforeShow: function (input, datePicker) {
7132 input.disabled = true;
7133 },
7134 onClose: function (dateText, datePicker) {
7135 this.disabled = false;
7136 },
7137 ";
7138 }
7139 // Note: We don't need monthNames, monthNamesShort, dayNames, dayNamesShort, dayNamesMin, they are set globally on datepicker component in lib_head.js.php
7140 if (!getDolGlobalString('MAIN_POPUP_CALENDAR_ON_FOCUS')) {
7141 $retstring .= "
7142 showOn: 'button', /* both has problem with autocompletion */
7143 buttonImage: '" . DOL_URL_ROOT . "/theme/" . dol_escape_js($conf->theme) . "/img/object_calendarday.png',
7144 buttonImageOnly: true";
7145 }
7146 $retstring .= "
7147 }) });";
7148 $retstring .= "</script>";
7149 }
7150
7151 // Input area to enter date manually
7152 $retstring .= '<div class="nowraponall inline-block divfordateinput">';
7153 $retstring .= '<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidthdate center" maxlength="11" value="'.$formatted_date.'"';
7154 $retstring .= ($disabled ? ' disabled' : '');
7155 $retstring .= ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '');
7156 $retstring .= ' onChange="dpChangeDay(\'' . dol_escape_js($prefix) . '\',\'' . dol_escape_js($langs->trans("FormatDateShortJavaInput")) . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7157 $retstring .= ' autocomplete="off">';
7158
7159 // Icone calendrier
7160 if ($disabled) {
7161 $retstringbutton = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
7162 $retstring = $retstringbutton . $retstring;
7163 }
7164
7165 $retstring .= '</div>';
7166 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
7167 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
7168 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
7169 } else {
7170 $retstring .= "Bad value of MAIN_POPUP_CALENDAR";
7171 }
7172 } else {
7173 // Show date with combo selects
7174 // Day
7175 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50imp" id="' . $prefix . 'day" name="' . $prefix . 'day">';
7176
7177 if ($emptydate || $set_time == -1) {
7178 $retstring .= '<option value="0" selected>&nbsp;</option>';
7179 }
7180
7181 for ($day = 1; $day <= 31; $day++) {
7182 $retstring .= '<option value="' . $day . '"' . ($day == $sday ? ' selected' : '') . '>' . $day . '</option>';
7183 }
7184
7185 $retstring .= "</select>";
7186
7187 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'month" name="' . $prefix . 'month">';
7188 if ($emptydate || $set_time == -1) {
7189 $retstring .= '<option value="0" selected>&nbsp;</option>';
7190 }
7191
7192 // Month
7193 for ($month = 1; $month <= 12; $month++) {
7194 $retstring .= '<option value="' . $month . '"' . ($month == $smonth ? ' selected' : '') . '>';
7195 $retstring .= dol_print_date(mktime(12, 0, 0, $month, 1, 2000), "%b");
7196 $retstring .= "</option>";
7197 }
7198 $retstring .= "</select>";
7199
7200 // Year
7201 if ($emptydate || $set_time == -1) {
7202 $retstring .= '<input' . ($disabled ? ' disabled' : '') . ' placeholder="' . dol_escape_htmltag($langs->trans("Year")) . '" class="flat maxwidth50imp valignmiddle" type="number" min="0" max="3000" maxlength="4" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">';
7203 } else {
7204 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'year" name="' . $prefix . 'year">';
7205
7206 $syear = (int) $syear;
7207 for ($year = $syear - 10; $year < (int) $syear + 10; $year++) {
7208 $retstring .= '<option value="' . $year . '"' . ($year == $syear ? ' selected' : '') . '>' . $year . '</option>';
7209 }
7210 $retstring .= "</select>\n";
7211 }
7212 }
7213 }
7214
7215 if ($d && $h) {
7216 $retstring .= (($h == 2 || $h == 4) ? '<br>' : ' ');
7217 $retstring .= '<span class="nowraponall">';
7218 }
7219
7220 if ($h) {
7221 $hourstart = 0;
7222 $hourend = 24;
7223 if ($openinghours != '') {
7224 $openinghours = explode(',', $openinghours);
7225 $hourstart = $openinghours[0];
7226 $hourend = $openinghours[1];
7227 if ($hourend < $hourstart) {
7228 $hourend = $hourstart;
7229 }
7230 }
7231 // Show hour
7232 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'hour' : '') . '" id="' . $prefix . 'hour" name="' . $prefix . 'hour">';
7233 if ($emptyhours) {
7234 $retstring .= '<option value="-1">&nbsp;</option>';
7235 }
7236 for ($hour = $hourstart; $hour < $hourend; $hour++) {
7237 if (strlen($hour) < 2) {
7238 $hour = "0" . $hour;
7239 }
7240 $retstring .= '<option value="' . $hour . '"' . (($hour == $shour) ? ' selected' : '') . '>' . $hour;
7241 //$retstring .= (empty($conf->dol_optimize_smallscreen) ? '' : 'H');
7242 $retstring .= '</option>';
7243 }
7244 $retstring .= '</select>';
7245 //if ($m && empty($conf->dol_optimize_smallscreen)) $retstring .= ":";
7246 if ($m) {
7247 $retstring .= ":";
7248 }
7249 }
7250
7251 if ($m) {
7252 // Show minutes
7253 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'min' : '') . '" id="' . $prefix . 'min" name="' . $prefix . 'min">';
7254 if ($emptyhours) {
7255 $retstring .= '<option value="-1">&nbsp;</option>';
7256 }
7257 for ($min = 0; $min < 60; $min += $stepminutes) {
7258 $min_str = sprintf("%02d", $min);
7259 $retstring .= '<option value="' . $min_str . '"' . (($min_str == $smin) ? ' selected' : '') . '>' . $min_str . '</option>';
7260 }
7261 $retstring .= '</select>';
7262
7263 $retstring .= '<input type="hidden" name="' . $prefix . 'sec" value="' . $ssec . '">';
7264 }
7265
7266 if ($d && $h) {
7267 $retstring .= '</span>';
7268 }
7269
7270 // Add a "Now" link
7271 if (!empty($conf->use_javascript_ajax) && $addnowlink) {
7272 // Script which will be inserted in the onClick of the "Now" link
7273 $reset_scripts = "";
7274 if ($addnowlink == 2) { // local computer time
7275 // pad add leading 0 on numbers
7276 $reset_scripts .= "Number.prototype.pad = function(size) {
7277 var s = String(this);
7278 while (s.length < (size || 2)) {s = '0' + s;}
7279 return s;
7280 };
7281 var d = new Date();";
7282 }
7283
7284 // Generate the date part, depending on the use or not of the javascript calendar
7285 if ($addnowlink == 1) { // server time expressed in user time setup
7286 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7287 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7288 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7289 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7290 } elseif ($addnowlink == 2) {
7291 /* Disabled because the output does not use the string format defined by FormatDateShort key to forge the value into #prefix.
7292 * This break application for foreign languages.
7293 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(d.toLocaleDateString(\''.str_replace('_', '-', $langs->defaultlang).'\'));';
7294 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(d.getDate().pad());';
7295 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(parseInt(d.getMonth().pad()) + 1);';
7296 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(d.getFullYear());';
7297 */
7298 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7299 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7300 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7301 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7302 }
7303 /*if ($usecalendar == "eldy")
7304 {
7305 $base=DOL_URL_ROOT.'/core/';
7306 $reset_scripts .= 'resetDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');';
7307 }
7308 else
7309 {
7310 $reset_scripts .= 'this.form.elements[\''.$prefix.'day\'].value=formatDate(new Date(), \'d\'); ';
7311 $reset_scripts .= 'this.form.elements[\''.$prefix.'month\'].value=formatDate(new Date(), \'M\'); ';
7312 $reset_scripts .= 'this.form.elements[\''.$prefix.'year\'].value=formatDate(new Date(), \'yyyy\'); ';
7313 }*/
7314 // Update the hour part
7315 if ($h) {
7316 if ($fullday) {
7317 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7318 }
7319 //$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); ';
7320 if ($addnowlink == 1) {
7321 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7322 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7323 } elseif ($addnowlink == 2) {
7324 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(d.getHours().pad());';
7325 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7326 }
7327
7328 if ($fullday) {
7329 $reset_scripts .= ' } ';
7330 }
7331 }
7332 // Update the minute part
7333 if ($m) {
7334 if ($fullday) {
7335 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7336 }
7337 //$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); ';
7338 if ($addnowlink == 1) {
7339 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7340 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7341 } elseif ($addnowlink == 2) {
7342 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(d.getMinutes().pad());';
7343 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7344 }
7345 if ($fullday) {
7346 $reset_scripts .= ' } ';
7347 }
7348 }
7349 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7350 if ($reset_scripts && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7351 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonNow" type="button" name="_useless" value="now" onClick="' . $reset_scripts . '">';
7352 $retstring .= $langs->trans("Now");
7353 $retstring .= '</button> ';
7354 }
7355 }
7356
7357 // Add a "Plus one hour" link
7358 if ($conf->use_javascript_ajax && $addplusone) {
7359 // Script which will be inserted in the onClick of the "Add plusone" link
7360 $reset_scripts = "";
7361
7362 // Generate the date part, depending on the use or not of the javascript calendar
7363 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'dayinputnoreduce', 'tzuserrel') . '\');';
7364 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7365 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7366 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7367 // Update the hour part
7368 if ($h) {
7369 if ($fullday) {
7370 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7371 }
7372 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7373 if ($fullday) {
7374 $reset_scripts .= ' } ';
7375 }
7376 }
7377 // Update the minute part
7378 if ($m) {
7379 if ($fullday) {
7380 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7381 }
7382 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7383 if ($fullday) {
7384 $reset_scripts .= ' } ';
7385 }
7386 }
7387 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7388 if ($reset_scripts && empty($conf->dol_optimize_smallscreen)) {
7389 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonPlusOne" type="button" name="_useless2" value="plusone" onClick="' . $reset_scripts . '">';
7390 $retstring .= $langs->trans("DateStartPlusOne");
7391 $retstring .= '</button> ';
7392 }
7393 }
7394
7395 // Add a link to set data
7396 if ($conf->use_javascript_ajax && !empty($adddateof)) {
7397 if (!is_array($adddateof)) {
7398 $arrayofdateof = array(array('adddateof' => $adddateof, 'labeladddateof' => $labeladddateof));
7399 } else {
7400 $arrayofdateof = $adddateof;
7401 }
7402 foreach ($arrayofdateof as $valuedateof) {
7403 $tmpadddateof = empty($valuedateof['adddateof']) ? 0 : $valuedateof['adddateof'];
7404 $tmplabeladddateof = empty($valuedateof['labeladddateof']) ? '' : $valuedateof['labeladddateof'];
7405 $tmparray = dol_getdate($tmpadddateof);
7406 if (empty($tmplabeladddateof)) {
7407 $tmplabeladddateof = $langs->trans("DateInvoice");
7408 }
7409 $reset_scripts = 'console.log(\'Click on now link\'); ';
7410 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date($tmpadddateof, 'dayinputnoreduce').'\');';
7411 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.$tmparray['mday'].'\');';
7412 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.$tmparray['mon'].'\');';
7413 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.$tmparray['year'].'\');';
7414 $retstring .= ' - <button class="dpInvisibleButtons datenowlink" id="dateofinvoice" type="button" name="_dateofinvoice" value="now" onclick="'.$reset_scripts.'">'.$tmplabeladddateof.'</button>';
7415 }
7416 }
7417
7418 return $retstring;
7419 }
7420
7429 public function selectTypeDuration($prefix, $selected = 'i', $excludetypes = array())
7430 {
7431 global $langs;
7432
7433 $TDurationTypes = array(
7434 'y' => $langs->trans('Years'),
7435 'm' => $langs->trans('Month'),
7436 'w' => $langs->trans('Weeks'),
7437 'd' => $langs->trans('Days'),
7438 'h' => $langs->trans('Hours'),
7439 'i' => $langs->trans('Minutes')
7440 );
7441
7442 // Removed undesired duration types
7443 foreach ($excludetypes as $value) {
7444 unset($TDurationTypes[$value]);
7445 }
7446
7447 $retstring = '<select class="flat minwidth75 maxwidth100" id="select_' . $prefix . 'type_duration" name="' . $prefix . 'type_duration">';
7448 foreach ($TDurationTypes as $key => $typeduration) {
7449 $retstring .= '<option value="' . $key . '"';
7450 if ($key == $selected) {
7451 $retstring .= " selected";
7452 }
7453 $retstring .= ">" . $typeduration . "</option>";
7454 }
7455 $retstring .= "</select>";
7456
7457 $retstring .= ajax_combobox('select_' . $prefix . 'type_duration');
7458
7459 return $retstring;
7460 }
7461
7462 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
7463
7477 public function select_duration($prefix, $iSecond = '', $disabled = 0, $typehour = 'select', $minunderhours = 0, $nooutput = 0)
7478 {
7479 // phpcs:enable
7480 global $langs;
7481
7482 $retstring = '<span class="nowraponall">';
7483
7484 $hourSelected = '';
7485 $minSelected = '';
7486
7487 // Hours
7488 if ($iSecond != '') {
7489 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7490
7491 $hourSelected = convertSecondToTime($iSecond, 'allhour');
7492 $minSelected = convertSecondToTime($iSecond, 'min');
7493 }
7494
7495 if ($typehour == 'select') {
7496 $retstring .= '<select class="flat" id="select_' . $prefix . 'hour" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . '>';
7497 for ($hour = 0; $hour < 25; $hour++) { // For a duration, we allow 24 hours
7498 $retstring .= '<option value="' . $hour . '"';
7499 if (is_numeric($hourSelected) && $hourSelected == $hour) {
7500 $retstring .= " selected";
7501 }
7502 $retstring .= ">" . $hour . "</option>";
7503 }
7504 $retstring .= "</select>";
7505 } elseif ($typehour == 'text' || $typehour == 'textselect') {
7506 $retstring .= '<input placeholder="' . $langs->trans('HourShort') . '" type="number" min="0" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputhour right" value="' . (($hourSelected != '') ? ((int) $hourSelected) : '') . '">';
7507 } else {
7508 return 'BadValueForParameterTypeHour';
7509 }
7510
7511 if ($typehour != 'text') {
7512 $retstring .= ' ' . $langs->trans('HourShort');
7513 } else {
7514 $retstring .= '<span class="">:</span>';
7515 }
7516
7517 // Minutes
7518 if ($minunderhours) {
7519 $retstring .= '<br>';
7520 } else {
7521 if ($typehour != 'text') {
7522 $retstring .= '<span class="hideonsmartphone">&nbsp;</span>';
7523 }
7524 }
7525
7526 if ($typehour == 'select' || $typehour == 'textselect') {
7527 $retstring .= '<select class="flat" id="select_' . $prefix . 'min" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . '>';
7528 for ($min = 0; $min <= 55; $min += 5) {
7529 $retstring .= '<option value="' . $min . '"';
7530 if (is_numeric($minSelected) && $minSelected == $min) {
7531 $retstring .= ' selected';
7532 }
7533 $retstring .= '>' . $min . '</option>';
7534 }
7535 $retstring .= "</select>";
7536 } elseif ($typehour == 'text') {
7537 $retstring .= '<input placeholder="' . $langs->trans('MinuteShort') . '" type="number" min="0" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputminute right" value="' . (($minSelected != '') ? ((int) $minSelected) : '') . '">';
7538 }
7539
7540 if ($typehour != 'text') {
7541 $retstring .= ' ' . $langs->trans('MinuteShort');
7542 }
7543
7544 $retstring .= "</span>";
7545
7546 if (!empty($nooutput)) {
7547 return $retstring;
7548 }
7549
7550 print $retstring;
7551
7552 return '';
7553 }
7554
7574 public function selectTickets($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0)
7575 {
7576 global $langs, $conf;
7577
7578 $out = '';
7579
7580 // check parameters
7581 if (is_null($ajaxoptions)) {
7582 $ajaxoptions = array();
7583 }
7584
7585 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7586 $placeholder = '';
7587
7588 if ($selected && empty($selected_input_value)) {
7589 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7590 $tickettmpselect = new Ticket($this->db);
7591 $tickettmpselect->fetch($selected);
7592 $selected_input_value = $tickettmpselect->ref;
7593 unset($tickettmpselect);
7594 }
7595
7596 $urloption = '';
7597 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/ticket/ajax/tickets.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7598
7599 if (empty($hidelabel)) {
7600 $out .= $langs->trans("RefOrLabel") . ' : ';
7601 } elseif ($hidelabel > 1) {
7602 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7603 if ($hidelabel == 2) {
7604 $out .= img_picto($langs->trans("Search"), 'search');
7605 }
7606 }
7607 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7608 if ($hidelabel == 3) {
7609 $out .= img_picto($langs->trans("Search"), 'search');
7610 }
7611 } else {
7612 $out .= $this->selectTicketsList($selected, $htmlname, $filtertype, $limit, '', $status, 0, $showempty, $forcecombo, $morecss);
7613 }
7614
7615 if (empty($nooutput)) {
7616 print $out;
7617 } else {
7618 return $out;
7619 }
7620 return '';
7621 }
7622
7623
7640 public function selectTicketsList($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7641 {
7642 global $langs, $conf;
7643
7644 $out = '';
7645 $outarray = array();
7646
7647 $selectFields = " p.rowid, p.ref, p.message";
7648
7649 $sql = "SELECT ";
7650 $sql .= $selectFields;
7651 $sql .= " FROM " . $this->db->prefix() . "ticket as p";
7652 $sql .= ' WHERE p.entity IN (' . getEntity('ticket') . ')';
7653
7654 // Add criteria on ref/label
7655 if ($filterkey != '') {
7656 $sql .= ' AND (';
7657 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7658 // For natural search
7659 $search_crit = explode(' ', $filterkey);
7660 $i = 0;
7661 if (count($search_crit) > 1) {
7662 $sql .= "(";
7663 }
7664 foreach ($search_crit as $crit) {
7665 if ($i > 0) {
7666 $sql .= " AND ";
7667 }
7668 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.subject LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7669 $sql .= ")";
7670 $i++;
7671 }
7672 if (count($search_crit) > 1) {
7673 $sql .= ")";
7674 }
7675 $sql .= ')';
7676 }
7677
7678 $sql .= $this->db->plimit($limit, 0);
7679
7680 // Build output string
7681 dol_syslog(get_class($this) . "::selectTicketsList search tickets", LOG_DEBUG);
7682 $result = $this->db->query($sql);
7683 if ($result) {
7684 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7685 require_once DOL_DOCUMENT_ROOT . '/core/lib/ticket.lib.php';
7686
7687 $num = $this->db->num_rows($result);
7688
7689 $events = array();
7690
7691 if (!$forcecombo) {
7692 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7693 $out .= ajax_combobox($htmlname, $events, $conf->global->TICKET_USE_SEARCH_TO_SELECT);
7694 }
7695
7696 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7697
7698 $textifempty = '';
7699 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7700 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7701 if (getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7702 if ($showempty && !is_numeric($showempty)) {
7703 $textifempty = $langs->trans($showempty);
7704 } else {
7705 $textifempty .= $langs->trans("All");
7706 }
7707 } else {
7708 if ($showempty && !is_numeric($showempty)) {
7709 $textifempty = $langs->trans($showempty);
7710 }
7711 }
7712 if ($showempty) {
7713 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7714 }
7715
7716 $i = 0;
7717 while ($num && $i < $num) {
7718 $opt = '';
7719 $optJson = array();
7720 $objp = $this->db->fetch_object($result);
7721
7722 $this->constructTicketListOption($objp, $opt, $optJson, $selected, $filterkey);
7723 // Add new entry
7724 // "key" value of json key array is used by jQuery automatically as selected value
7725 // "label" value of json key array is used by jQuery automatically as text for combo box
7726 $out .= $opt;
7727 array_push($outarray, $optJson);
7728
7729 $i++;
7730 }
7731
7732 $out .= '</select>';
7733
7734 $this->db->free($result);
7735
7736 if (empty($outputmode)) {
7737 return $out;
7738 }
7739 return $outarray;
7740 } else {
7741 dol_print_error($this->db);
7742 }
7743
7744 return array();
7745 }
7746
7758 protected function constructTicketListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7759 {
7760 $outkey = '';
7761 $outref = '';
7762 $outtype = '';
7763
7764 $outkey = $objp->rowid;
7765 $outref = $objp->ref;
7766 $outtype = $objp->fk_product_type;
7767
7768 $opt = '<option value="' . $objp->rowid . '"';
7769 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7770 $opt .= '>';
7771 $opt .= $objp->ref;
7772 $objRef = $objp->ref;
7773 if (!empty($filterkey) && $filterkey != '') {
7774 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
7775 }
7776
7777 $opt .= "</option>\n";
7778 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
7779 }
7780
7800 public function selectProjects($selected = '', $htmlname = 'projectid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0)
7801 {
7802 global $langs, $conf;
7803
7804 $out = '';
7805
7806 // check parameters
7807 if (is_null($ajaxoptions)) {
7808 $ajaxoptions = array();
7809 }
7810
7811 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7812 $placeholder = '';
7813
7814 if ($selected && empty($selected_input_value)) {
7815 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7816 $projecttmpselect = new Project($this->db);
7817 $projecttmpselect->fetch($selected);
7818 $selected_input_value = $projecttmpselect->ref;
7819 unset($projecttmpselect);
7820 }
7821
7822 $urloption = '';
7823 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/projet/ajax/projects.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7824
7825 if (empty($hidelabel)) {
7826 $out .= $langs->trans("RefOrLabel") . ' : ';
7827 } elseif ($hidelabel > 1) {
7828 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7829 if ($hidelabel == 2) {
7830 $out .= img_picto($langs->trans("Search"), 'search');
7831 }
7832 }
7833 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7834 if ($hidelabel == 3) {
7835 $out .= img_picto($langs->trans("Search"), 'search');
7836 }
7837 } else {
7838 $out .= $this->selectProjectsList($selected, $htmlname, $filtertype, $limit, '', $status, 0, $showempty, $forcecombo, $morecss);
7839 }
7840
7841 if (empty($nooutput)) {
7842 print $out;
7843 } else {
7844 return $out;
7845 }
7846 return '';
7847 }
7848
7865 public function selectProjectsList($selected = '', $htmlname = 'projectid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7866 {
7867 global $langs, $conf;
7868
7869 $out = '';
7870 $outarray = array();
7871
7872 $selectFields = " p.rowid, p.ref";
7873
7874 $sql = "SELECT ";
7875 $sql .= $selectFields;
7876 $sql .= " FROM " . $this->db->prefix() . "projet as p";
7877 $sql .= ' WHERE p.entity IN (' . getEntity('project') . ')';
7878
7879 // Add criteria on ref/label
7880 if ($filterkey != '') {
7881 $sql .= ' AND (';
7882 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7883 // For natural search
7884 $search_crit = explode(' ', $filterkey);
7885 $i = 0;
7886 if (count($search_crit) > 1) {
7887 $sql .= "(";
7888 }
7889 foreach ($search_crit as $crit) {
7890 if ($i > 0) {
7891 $sql .= " AND ";
7892 }
7893 $sql .= "p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7894 $sql .= "";
7895 $i++;
7896 }
7897 if (count($search_crit) > 1) {
7898 $sql .= ")";
7899 }
7900 $sql .= ')';
7901 }
7902
7903 $sql .= $this->db->plimit($limit, 0);
7904
7905 // Build output string
7906 dol_syslog(get_class($this) . "::selectProjectsList search projects", LOG_DEBUG);
7907 $result = $this->db->query($sql);
7908 if ($result) {
7909 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7910 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
7911
7912 $num = $this->db->num_rows($result);
7913
7914 $events = array();
7915
7916 if (!$forcecombo) {
7917 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7918 $out .= ajax_combobox($htmlname, $events, $conf->global->PROJECT_USE_SEARCH_TO_SELECT);
7919 }
7920
7921 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7922
7923 $textifempty = '';
7924 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7925 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7926 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
7927 if ($showempty && !is_numeric($showempty)) {
7928 $textifempty = $langs->trans($showempty);
7929 } else {
7930 $textifempty .= $langs->trans("All");
7931 }
7932 } else {
7933 if ($showempty && !is_numeric($showempty)) {
7934 $textifempty = $langs->trans($showempty);
7935 }
7936 }
7937 if ($showempty) {
7938 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7939 }
7940
7941 $i = 0;
7942 while ($num && $i < $num) {
7943 $opt = '';
7944 $optJson = array();
7945 $objp = $this->db->fetch_object($result);
7946
7947 $this->constructProjectListOption($objp, $opt, $optJson, $selected, $filterkey);
7948 // Add new entry
7949 // "key" value of json key array is used by jQuery automatically as selected value
7950 // "label" value of json key array is used by jQuery automatically as text for combo box
7951 $out .= $opt;
7952 array_push($outarray, $optJson);
7953
7954 $i++;
7955 }
7956
7957 $out .= '</select>';
7958
7959 $this->db->free($result);
7960
7961 if (empty($outputmode)) {
7962 return $out;
7963 }
7964 return $outarray;
7965 } else {
7966 dol_print_error($this->db);
7967 }
7968
7969 return array();
7970 }
7971
7983 protected function constructProjectListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7984 {
7985 $outkey = '';
7986 $outref = '';
7987 $outtype = '';
7988
7989 $label = $objp->label;
7990
7991 $outkey = $objp->rowid;
7992 $outref = $objp->ref;
7993 $outlabel = $objp->label;
7994 $outtype = $objp->fk_product_type;
7995
7996 $opt = '<option value="' . $objp->rowid . '"';
7997 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7998 $opt .= '>';
7999 $opt .= $objp->ref;
8000 $objRef = $objp->ref;
8001 if (!empty($filterkey) && $filterkey != '') {
8002 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
8003 }
8004
8005 $opt .= "</option>\n";
8006 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
8007 }
8008
8009
8029 public function selectMembers($selected = '', $htmlname = 'adherentid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0)
8030 {
8031 global $langs, $conf;
8032
8033 $out = '';
8034
8035 // check parameters
8036 if (is_null($ajaxoptions)) {
8037 $ajaxoptions = array();
8038 }
8039
8040 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
8041 $placeholder = '';
8042
8043 if ($selected && empty($selected_input_value)) {
8044 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
8045 $adherenttmpselect = new Adherent($this->db);
8046 $adherenttmpselect->fetch($selected);
8047 $selected_input_value = $adherenttmpselect->ref;
8048 unset($adherenttmpselect);
8049 }
8050
8051 $urloption = '';
8052
8053 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/adherents/ajax/adherents.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
8054
8055 if (empty($hidelabel)) {
8056 $out .= $langs->trans("RefOrLabel") . ' : ';
8057 } elseif ($hidelabel > 1) {
8058 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
8059 if ($hidelabel == 2) {
8060 $out .= img_picto($langs->trans("Search"), 'search');
8061 }
8062 }
8063 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
8064 if ($hidelabel == 3) {
8065 $out .= img_picto($langs->trans("Search"), 'search');
8066 }
8067 } else {
8068 $filterkey = '';
8069
8070 $out .= $this->selectMembersList($selected, $htmlname, $filtertype, $limit, $filterkey, $status, 0, $showempty, $forcecombo, $morecss);
8071 }
8072
8073 if (empty($nooutput)) {
8074 print $out;
8075 } else {
8076 return $out;
8077 }
8078 return '';
8079 }
8080
8097 public function selectMembersList($selected = '', $htmlname = 'adherentid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
8098 {
8099 global $langs, $conf;
8100
8101 $out = '';
8102 $outarray = array();
8103
8104 $selectFields = " p.rowid, p.ref, p.firstname, p.lastname, p.fk_adherent_type";
8105
8106 $sql = "SELECT ";
8107 $sql .= $selectFields;
8108 $sql .= " FROM " . $this->db->prefix() . "adherent as p";
8109 $sql .= ' WHERE p.entity IN (' . getEntity('adherent') . ')';
8110
8111 // Add criteria on ref/label
8112 if ($filterkey != '') {
8113 $sql .= ' AND (';
8114 $prefix = !getDolGlobalString('MEMBER_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
8115 // For natural search
8116 $search_crit = explode(' ', $filterkey);
8117 $i = 0;
8118 if (count($search_crit) > 1) {
8119 $sql .= "(";
8120 }
8121 foreach ($search_crit as $crit) {
8122 if ($i > 0) {
8123 $sql .= " AND ";
8124 }
8125 $sql .= "(p.firstname LIKE '" . $this->db->escape($prefix . $crit) . "%'";
8126 $sql .= " OR p.lastname LIKE '" . $this->db->escape($prefix . $crit) . "%')";
8127 $i++;
8128 }
8129 if (count($search_crit) > 1) {
8130 $sql .= ")";
8131 }
8132 $sql .= ')';
8133 }
8134 if ($status != -1) {
8135 $sql .= ' AND statut = ' . ((int) $status);
8136 }
8137 $sql .= $this->db->plimit($limit, 0);
8138
8139 // Build output string
8140 dol_syslog(get_class($this) . "::selectMembersList search adherents", LOG_DEBUG);
8141 $result = $this->db->query($sql);
8142 if ($result) {
8143 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
8144 require_once DOL_DOCUMENT_ROOT . '/core/lib/member.lib.php';
8145
8146 $num = $this->db->num_rows($result);
8147
8148 $events = array();
8149
8150 if (!$forcecombo) {
8151 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8152 $out .= ajax_combobox($htmlname, $events, getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT') ? $conf->global->PROJECT_USE_SEARCH_TO_SELECT : '');
8153 }
8154
8155 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
8156
8157 $textifempty = '';
8158 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
8159 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8160 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
8161 if ($showempty && !is_numeric($showempty)) {
8162 $textifempty = $langs->trans($showempty);
8163 } else {
8164 $textifempty .= $langs->trans("All");
8165 }
8166 } else {
8167 if ($showempty && !is_numeric($showempty)) {
8168 $textifempty = $langs->trans($showempty);
8169 }
8170 }
8171 if ($showempty) {
8172 $out .= '<option value="-1" selected>' . $textifempty . '</option>';
8173 }
8174
8175 $i = 0;
8176 while ($num && $i < $num) {
8177 $opt = '';
8178 $optJson = array();
8179 $objp = $this->db->fetch_object($result);
8180
8181 $this->constructMemberListOption($objp, $opt, $optJson, $selected, $filterkey);
8182
8183 // Add new entry
8184 // "key" value of json key array is used by jQuery automatically as selected value
8185 // "label" value of json key array is used by jQuery automatically as text for combo box
8186 $out .= $opt;
8187 array_push($outarray, $optJson);
8188
8189 $i++;
8190 }
8191
8192 $out .= '</select>';
8193
8194 $this->db->free($result);
8195
8196 if (empty($outputmode)) {
8197 return $out;
8198 }
8199 return $outarray;
8200 } else {
8201 dol_print_error($this->db);
8202 }
8203
8204 return array();
8205 }
8206
8218 protected function constructMemberListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
8219 {
8220 $outkey = '';
8221 $outlabel = '';
8222 $outtype = '';
8223
8224 $outkey = $objp->rowid;
8225 $outlabel = dolGetFirstLastname($objp->firstname, $objp->lastname);
8226 $outtype = $objp->fk_adherent_type;
8227
8228 $opt = '<option value="' . $objp->rowid . '"';
8229 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
8230 $opt .= '>';
8231 if (!empty($filterkey) && $filterkey != '') {
8232 $outlabel = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $outlabel, 1);
8233 }
8234 $opt .= $outlabel;
8235 $opt .= "</option>\n";
8236
8237 $optJson = array('key' => $outkey, 'value' => $outlabel, 'type' => $outtype);
8238 }
8239
8260 public function selectForForms($objectdesc, $htmlname, $preSelectedValue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '', $objectfield = '')
8261 {
8262 global $conf, $extrafields, $user;
8263
8264 // Example of common usage for a link to a thirdparty
8265
8266 // We got this in a modulebuilder form of "MyObject" of module "mymodule".
8267 // ->fields is array( ... "fk_soc" => array("type"=>"integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))" ...)
8268 // $objectdesc = 'Societe'
8269 // $objectfield = 'myobject@mymodule:fk_soc' ('fk_soc' is code to retrieve myobject->fields['fk_soc'])
8270
8271 // We got this when showing an extrafields on resource that is a link to societe
8272 // extrafields 'link_to_societe' of Resource is 'link' to 'Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))" ...)'
8273 // $objectdesc = 'Societe'
8274 // $objectfield = 'resource:options_link_to_societe'
8275
8276 // With old usage:
8277 // $objectdesc = 'Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))'
8278 // $objectfield = ''
8279
8280 //var_dump($objectdesc.' '.$objectfield);
8281 //debug_print_backtrace();
8282
8283 $objectdescorig = $objectdesc;
8284 $objecttmp = null;
8285 $InfoFieldList = array();
8286 $classname = '';
8287 $filter = ''; // Ensure filter has value (for static analysis)
8288 $sortfield = ''; // Ensure filter has value (for static analysis)
8289
8290 if ($objectfield) { // We must retrieve the objectdesc from the field or extrafield
8291 // Example: $objectfield = 'product:options_package' or 'myobject@mymodule:options_myfield'
8292 $tmparray = explode(':', $objectfield);
8293
8294 // Get instance of object from $element
8295 $objectforfieldstmp = fetchObjectByElement(0, strtolower($tmparray[0]));
8296
8297 if (is_object($objectforfieldstmp)) {
8298 $objectdesc = '';
8299
8300 $reg = array();
8301 if (preg_match('/^options_(.*)$/', $tmparray[1], $reg)) {
8302 // For a property in extrafields
8303 $key = $reg[1];
8304 // fetch optionals attributes and labels
8305 $extrafields->fetch_name_optionals_label($objectforfieldstmp->table_element);
8306
8307 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key]) && $extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key] == 'link') {
8308 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options'])) {
8309 $tmpextrafields = array_keys($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options']);
8310 $objectdesc = $tmpextrafields[0];
8311 }
8312 }
8313 } else {
8314 // For a property in ->fields
8315 if (array_key_exists($tmparray[1], $objectforfieldstmp->fields)) {
8316 $objectdesc = $objectforfieldstmp->fields[$tmparray[1]]['type'];
8317 $objectdesc = preg_replace('/^integer[^:]*:/', '', $objectdesc);
8318 }
8319 }
8320 }
8321 }
8322
8323 if ($objectdesc) {
8324 // Example of value for $objectdesc:
8325 // Bom:bom/class/bom.class.php:0:t.status=1
8326 // Bom:bom/class/bom.class.php:0:t.status=1:ref
8327 // Bom:bom/class/bom.class.php:0:(t.status:=:1) OR (t.field2:=:2):ref
8328 $InfoFieldList = explode(":", $objectdesc, 4);
8329 $vartmp = (empty($InfoFieldList[3]) ? '' : $InfoFieldList[3]);
8330 $reg = array();
8331 if (preg_match('/^.*:(\w*)$/', $vartmp, $reg)) {
8332 $InfoFieldList[4] = $reg[1]; // take the sort field
8333 }
8334 $InfoFieldList[3] = preg_replace('/:\w*$/', '', $vartmp); // take the filter field
8335
8336 $classname = $InfoFieldList[0];
8337 $classpath = empty($InfoFieldList[1]) ? '' : $InfoFieldList[1];
8338 //$addcreatebuttonornot = empty($InfoFieldList[2]) ? 0 : $InfoFieldList[2];
8339 $filter = empty($InfoFieldList[3]) ? '' : $InfoFieldList[3];
8340 $sortfield = empty($InfoFieldList[4]) ? '' : $InfoFieldList[4];
8341
8342 // Load object according to $id and $element
8343 $objecttmp = fetchObjectByElement(0, strtolower($InfoFieldList[0]));
8344
8345 // Fallback to another solution to get $objecttmp
8346 if (empty($objecttmp) && !empty($classpath)) {
8347 dol_include_once($classpath);
8348
8349 if ($classname && class_exists($classname)) {
8350 $objecttmp = new $classname($this->db);
8351 }
8352 }
8353 }
8354
8355 // Make some replacement in $filter. May not be used if we used the ajax mode with $objectfield. In such a case
8356 // we propagate the $objectfield and not the filter and replacement is done by the ajax/selectobject.php component.
8357 $sharedentities = (is_object($objecttmp) && property_exists($objecttmp, 'element')) ? getEntity($objecttmp->element) : strtolower($classname);
8358 $filter = str_replace(
8359 array('__ENTITY__', '__SHARED_ENTITIES__', '__USER_ID__'),
8360 array($conf->entity, $sharedentities, $user->id),
8361 $filter
8362 );
8363
8364 if (!is_object($objecttmp)) {
8365 dol_syslog('selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc, LOG_WARNING);
8366 return 'selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc;
8367 }
8368 '@phan-var-force CommonObject $objecttmp';
8369
8370 //var_dump($filter);
8371 $prefixforautocompletemode = $objecttmp->element;
8372 if ($prefixforautocompletemode == 'societe') {
8373 $prefixforautocompletemode = 'company';
8374 }
8375 if ($prefixforautocompletemode == 'product') {
8376 $prefixforautocompletemode = 'produit';
8377 }
8378 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8379
8380 dol_syslog(get_class($this) . "::selectForForms filter=" . $filter, LOG_DEBUG);
8381
8382 // Generate the combo HTML component
8383 $out = '';
8384 if (!empty($conf->use_javascript_ajax) && getDolGlobalString($confkeyforautocompletemode) && !$forcecombo) {
8385 // No immediate load of all database
8386 $placeholder = '';
8387
8388 if ($preSelectedValue && empty($selected_input_value)) {
8389 $objecttmp->fetch($preSelectedValue);
8390 $selected_input_value = ($prefixforautocompletemode == 'company' ? $objecttmp->name : $objecttmp->ref);
8391
8392 $oldValueForShowOnCombobox = 0;
8393 foreach ($objecttmp->fields as $fieldK => $fielV) {
8394 if (!array_key_exists('showoncombobox', $fielV) || !$fielV['showoncombobox'] || empty($objecttmp->$fieldK)) {
8395 continue;
8396 }
8397
8398 if (!$oldValueForShowOnCombobox) {
8399 $selected_input_value = '';
8400 }
8401
8402 $selected_input_value .= $oldValueForShowOnCombobox ? ' - ' : '';
8403 $selected_input_value .= $objecttmp->$fieldK;
8404 $oldValueForShowOnCombobox = empty($fielV['showoncombobox']) ? 0 : $fielV['showoncombobox'];
8405 }
8406 }
8407
8408 // Set url and param to call to get json of the search results
8409 $urlforajaxcall = DOL_URL_ROOT . '/core/ajax/selectobject.php';
8410 $urloption = 'htmlname=' . urlencode($htmlname) . '&outjson=1&objectdesc=' . urlencode($objectdescorig) . '&objectfield='.urlencode($objectfield) . ($sortfield ? '&sortfield=' . urlencode($sortfield) : '');
8411
8412 // Activate the auto complete using ajax call.
8413 $out .= ajax_autocompleter($preSelectedValue, $htmlname, $urlforajaxcall, $urloption, getDolGlobalString($confkeyforautocompletemode), 0);
8414 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
8415 $out .= '<input type="text" class="' . $morecss . '"' . ($disabled ? ' disabled="disabled"' : '') . ' name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '') . ' />';
8416 } else {
8417 // Immediate load of table record.
8418 $out .= $this->selectForFormsList($objecttmp, $htmlname, $preSelectedValue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, 0, $disabled, $sortfield, $filter);
8419 }
8420
8421 return $out;
8422 }
8423
8424
8445 public function selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $outputmode = 0, $disabled = 0, $sortfield = '', $filter = '')
8446 {
8447 global $langs, $user, $hookmanager;
8448
8449 //print "$htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, $outputmode, $disabled";
8450
8451 $prefixforautocompletemode = $objecttmp->element;
8452 if ($prefixforautocompletemode == 'societe') {
8453 $prefixforautocompletemode = 'company';
8454 }
8455 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8456
8457 if (!empty($objecttmp->fields)) { // For object that declare it, it is better to use declared fields (like societe, contact, ...)
8458 $tmpfieldstoshow = '';
8459 foreach ($objecttmp->fields as $key => $val) {
8460 if (! (int) dol_eval($val['enabled'], 1, 1, '1')) {
8461 continue;
8462 }
8463 if (!empty($val['showoncombobox'])) {
8464 $tmpfieldstoshow .= ($tmpfieldstoshow ? ',' : '') . 't.' . $key;
8465 }
8466 }
8467 if ($tmpfieldstoshow) {
8468 $fieldstoshow = $tmpfieldstoshow;
8469 }
8470 } elseif ($objecttmp->element === 'category') {
8471 $fieldstoshow = 't.label';
8472 } else {
8473 // For backward compatibility
8474 $objecttmp->fields['ref'] = array('type' => 'varchar(30)', 'label' => 'Ref', 'showoncombobox' => 1);
8475 }
8476
8477 if (empty($fieldstoshow)) {
8478 if (isset($objecttmp->fields['ref'])) {
8479 $fieldstoshow = 't.ref';
8480 } else {
8481 $langs->load("errors");
8482 $this->error = $langs->trans("ErrorNoFieldWithAttributeShowoncombobox");
8483 return $langs->trans('ErrorNoFieldWithAttributeShowoncombobox');
8484 }
8485 }
8486
8487 $out = '';
8488 $outarray = array();
8489 $tmparray = array();
8490
8491 $num = 0;
8492
8493 // Search data
8494 $sql = "SELECT t.rowid, " . $fieldstoshow . " FROM " . $this->db->prefix() . $objecttmp->table_element . " as t";
8495 if (!empty($objecttmp->isextrafieldmanaged)) {
8496 $sql .= " LEFT JOIN " . $this->db->prefix() . $objecttmp->table_element . "_extrafields as e ON t.rowid=e.fk_object";
8497 }
8498 if (isset($objecttmp->ismultientitymanaged)) {
8499 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8500 $tmparray = explode('@', $objecttmp->ismultientitymanaged);
8501 $sql .= " INNER JOIN " . $this->db->prefix() . $tmparray[1] . " as parenttable ON parenttable.rowid = t." . $tmparray[0];
8502 }
8503 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8504 if (!$user->hasRight('societe', 'client', 'voir')) {
8505 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
8506 }
8507 }
8508 }
8509
8510 // Add where from hooks
8511 $parameters = array(
8512 'object' => $objecttmp,
8513 'htmlname' => $htmlname,
8514 'filter' => $filter,
8515 'searchkey' => $searchkey
8516 );
8517
8518 $reshook = $hookmanager->executeHooks('selectForFormsListWhere', $parameters); // Note that $action and $object may have been modified by hook
8519 if (!empty($hookmanager->resPrint)) {
8520 $sql .= $hookmanager->resPrint;
8521 } else {
8522 $sql .= " WHERE 1=1";
8523 if (isset($objecttmp->ismultientitymanaged)) {
8524 if ($objecttmp->ismultientitymanaged == 1) {
8525 $sql .= " AND t.entity IN (" . getEntity($objecttmp->table_element) . ")";
8526 }
8527 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8528 $sql .= " AND parenttable.entity = t." . $tmparray[0];
8529 }
8530 if ($objecttmp->ismultientitymanaged == 1 && !empty($user->socid)) {
8531 if ($objecttmp->element == 'societe') {
8532 $sql .= " AND t.rowid = " . ((int) $user->socid);
8533 } else {
8534 $sql .= " AND t.fk_soc = " . ((int) $user->socid);
8535 }
8536 }
8537 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8538 if (!$user->hasRight('societe', 'client', 'voir')) {
8539 $sql .= " AND t.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
8540 }
8541 }
8542 }
8543 if ($searchkey != '') {
8544 $sql .= natural_search(explode(',', $fieldstoshow), $searchkey);
8545 }
8546
8547 if ($filter) { // Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
8548 $errormessage = '';
8549 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
8550 if ($errormessage) {
8551 return 'Error forging a SQL request from an universal criteria: ' . $errormessage;
8552 }
8553 }
8554 }
8555 $sql .= $this->db->order($sortfield ? $sortfield : $fieldstoshow, "ASC");
8556 //$sql.=$this->db->plimit($limit, 0);
8557 //print $sql;
8558
8559 // Build output string
8560 $resql = $this->db->query($sql);
8561 if ($resql) {
8562 // Construct $out and $outarray
8563 $out .= '<select id="' . $htmlname . '" class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ($moreparams ? ' ' . $moreparams : '') . ' name="' . $htmlname . '">' . "\n";
8564
8565 // Warning: Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'. Seems it is no more true with selec2 v4
8566 $textifempty = '&nbsp;';
8567
8568 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8569 if (getDolGlobalInt($confkeyforautocompletemode)) {
8570 if ($showempty && !is_numeric($showempty)) {
8571 $textifempty = $langs->trans($showempty);
8572 } else {
8573 $textifempty .= $langs->trans("All");
8574 }
8575 }
8576 if ($showempty) {
8577 $out .= '<option value="-1">' . $textifempty . '</option>' . "\n";
8578 }
8579
8580 $num = $this->db->num_rows($resql);
8581 $i = 0;
8582 if ($num) {
8583 while ($i < $num) {
8584 $obj = $this->db->fetch_object($resql);
8585 $label = '';
8586 $labelhtml = '';
8587 $tmparray = explode(',', $fieldstoshow);
8588 $oldvalueforshowoncombobox = 0;
8589 foreach ($tmparray as $key => $val) {
8590 $val = preg_replace('/t\./', '', $val);
8591 $label .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8592 $labelhtml .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8593 $label .= $obj->$val;
8594 $labelhtml .= $obj->$val;
8595
8596 $oldvalueforshowoncombobox = empty($objecttmp->fields[$val]['showoncombobox']) ? 0 : $objecttmp->fields[$val]['showoncombobox'];
8597 }
8598 if (empty($outputmode)) {
8599 if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid) {
8600 $out .= '<option value="' . $obj->rowid . '" selected data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
8601 } else {
8602 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
8603 }
8604 } else {
8605 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label));
8606 }
8607
8608 $i++;
8609 if (($i % 10) == 0) {
8610 $out .= "\n";
8611 }
8612 }
8613 }
8614
8615 $out .= '</select>' . "\n";
8616
8617 if (!$forcecombo) {
8618 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8619 $out .= ajax_combobox($htmlname, array(), getDolGlobalInt($confkeyforautocompletemode, 0));
8620 }
8621 } else {
8622 dol_print_error($this->db);
8623 }
8624
8625 $this->result = array('nbofelement' => $num);
8626
8627 if ($outputmode) {
8628 return $outarray;
8629 }
8630 return $out;
8631 }
8632
8633
8657 public static function selectarray($htmlname, $array, $id = '', $show_empty = 0, $key_in_label = 0, $value_as_key = 0, $moreparam = '', $translate = 0, $maxlen = 0, $disabled = 0, $sort = '', $morecss = 'minwidth75', $addjscombo = 1, $moreparamonempty = '', $disablebademail = 0, $nohtmlescape = 0)
8658 {
8659 global $conf, $langs;
8660
8661 // Do we want a multiselect ?
8662 //$jsbeautify = 0;
8663 //if (preg_match('/^multi/',$htmlname)) $jsbeautify = 1;
8664 $jsbeautify = 1;
8665
8666 if ($value_as_key) {
8667 $array = array_combine($array, $array);
8668 }
8669
8670 '@phan-var-force array{label:string,data-html:string,disable?:int<0,1>,css?:string} $array'; // Array combine breaks information
8671
8672 $out = '';
8673
8674 if ($addjscombo < 0) {
8675 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8676 $addjscombo = 1;
8677 } else {
8678 $addjscombo = 0;
8679 }
8680 }
8681 $idname = str_replace(array('[', ']'), array('', ''), $htmlname);
8682 $out .= '<select id="' . preg_replace('/^\./', '', $idname) . '" ' . ($disabled ? 'disabled="disabled" ' : '') . 'class="flat ' . (preg_replace('/^\./', '', $htmlname)) . ($morecss ? ' ' . $morecss : '') . ' selectformat"';
8683 $out .= ' name="' . preg_replace('/^\./', '', $htmlname) . '" ' . ($moreparam ? $moreparam : '');
8684 $out .= '>'."\n";
8685
8686 if ($show_empty) {
8687 $textforempty = ' ';
8688 if (!empty($conf->use_javascript_ajax)) {
8689 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
8690 }
8691 if (!is_numeric($show_empty)) {
8692 $textforempty = $show_empty;
8693 }
8694 $out .= '<option class="optiongrey" ' . ($moreparamonempty ? $moreparamonempty . ' ' : '') . 'value="' . (((int) $show_empty) < 0 ? $show_empty : -1) . '"' . ($id == $show_empty ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
8695 }
8696 if (is_array($array)) {
8697 // Translate
8698 if ($translate) {
8699 foreach ($array as $key => $value) {
8700 if (!is_array($value)) {
8701 $array[$key] = $langs->trans($value);
8702 } else {
8703 $array[$key]['label'] = $langs->trans($value['label']);
8704 }
8705 }
8706 }
8707 // Sort
8708 if ($sort == 'ASC') {
8709 asort($array);
8710 } elseif ($sort == 'DESC') {
8711 arsort($array);
8712 }
8713
8714 foreach ($array as $key => $tmpvalue) {
8715 if (is_array($tmpvalue)) {
8716 $value = $tmpvalue['label'];
8717 //$valuehtml = empty($tmpvalue['data-html']) ? $value : $tmpvalue['data-html'];
8718 $disabled = empty($tmpvalue['disabled']) ? '' : ' disabled';
8719 $style = empty($tmpvalue['css']) ? '' : ' class="' . $tmpvalue['css'] . '"';
8720 } else {
8721 $value = $tmpvalue;
8722 //$valuehtml = $tmpvalue;
8723 $disabled = '';
8724 $style = '';
8725 }
8726 if (!empty($disablebademail)) {
8727 if (($disablebademail == 1 && !preg_match('/&lt;.+@.+&gt;/', $value))
8728 || ($disablebademail == 2 && preg_match('/---/', $value))) {
8729 $disabled = ' disabled';
8730 $style = ' class="warning"';
8731 }
8732 }
8733 if ($key_in_label) {
8734 if (empty($nohtmlescape)) {
8735 $selectOptionValue = dol_escape_htmltag($key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value));
8736 } else {
8737 $selectOptionValue = $key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value);
8738 }
8739 } else {
8740 if (empty($nohtmlescape)) {
8741 $selectOptionValue = dol_escape_htmltag($maxlen ? dol_trunc($value, $maxlen) : $value);
8742 } else {
8743 $selectOptionValue = $maxlen ? dol_trunc($value, $maxlen) : $value;
8744 }
8745 if ($value == '' || $value == '-') {
8746 $selectOptionValue = '&nbsp;';
8747 }
8748 }
8749 $out .= '<option value="' . $key . '"';
8750 $out .= $style . $disabled;
8751 if (is_array($id)) {
8752 if (in_array($key, $id) && !$disabled) {
8753 $out .= ' selected'; // To preselect a value
8754 }
8755 } else {
8756 $id = (string) $id; // if $id = 0, then $id = '0'
8757 if ($id != '' && (($id == (string) $key) || ($id == 'ifone' && count($array) == 1)) && !$disabled) {
8758 $out .= ' selected'; // To preselect a value
8759 }
8760 }
8761 if (!empty($nohtmlescape)) { // deprecated. Use instead the key 'data-html' into input $array, managed at next step to use HTML content.
8762 $out .= ' data-html="' . dol_escape_htmltag($selectOptionValue) . '"';
8763 }
8764
8765 if (is_array($tmpvalue)) {
8766 foreach ($tmpvalue as $keyforvalue => $valueforvalue) {
8767 if (preg_match('/^data-/', $keyforvalue)) { // The best solution if you want to use HTML values into the list is to use data-html.
8768 $out .= ' '.dol_escape_htmltag($keyforvalue).'="'.dol_escape_htmltag($valueforvalue).'"';
8769 }
8770 }
8771 }
8772 $out .= '>';
8773 $out .= $selectOptionValue;
8774 $out .= "</option>\n";
8775 }
8776 }
8777 $out .= "</select>";
8778
8779 // Add code for jquery to use multiselect
8780 if ($addjscombo && $jsbeautify) {
8781 // Enhance with select2
8782 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8783 $out .= ajax_combobox($idname, array(), 0, 0, 'resolve', (((int) $show_empty) < 0 ? (string) $show_empty : '-1'), $morecss);
8784 }
8785
8786 return $out;
8787 }
8788
8807 public static function selectArrayAjax($htmlname, $url, $id = '', $moreparam = '', $moreparamtourl = '', $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0)
8808 {
8809 global $conf, $langs;
8810 global $delayedhtmlcontent; // Will be used later outside of this function
8811
8812 // TODO Use an internal dolibarr component instead of select2
8813 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8814 return '';
8815 }
8816
8817 $out = '<select type="text" class="' . $htmlname . ($morecss ? ' ' . $morecss : '') . '" ' . ($moreparam ? $moreparam . ' ' : '') . 'name="' . $htmlname . '"></select>';
8818
8819 $outdelayed = '';
8820 if (!empty($conf->use_javascript_ajax)) {
8821 $tmpplugin = 'select2';
8822 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8823 <script nonce="' . getNonce() . '">
8824 $(document).ready(function () {
8825
8826 ' . ($callurlonselect ? 'var saveRemoteData = [];' : '') . '
8827
8828 $(".' . $htmlname . '").select2({
8829 ajax: {
8830 dir: "ltr",
8831 url: "' . $url . '",
8832 dataType: \'json\',
8833 delay: 250,
8834 data: function (params) {
8835 return {
8836 q: params.term, // search term
8837 page: params.page
8838 }
8839 },
8840 processResults: function (data) {
8841 // parse the results into the format expected by Select2.
8842 // since we are using custom formatting functions we do not need to alter the remote JSON data
8843 //console.log(data);
8844 saveRemoteData = data;
8845 /* format json result for select2 */
8846 result = []
8847 $.each( data, function( key, value ) {
8848 result.push({id: key, text: value.text});
8849 });
8850 //return {results:[{id:\'none\', text:\'aa\'}, {id:\'rrr\', text:\'Red\'},{id:\'bbb\', text:\'Search a into projects\'}], more:false}
8851 //console.log(result);
8852 return {results: result, more: false}
8853 },
8854 cache: true
8855 },
8856 language: (typeof select2arrayoflanguage === \'undefined\') ? \'en\' : select2arrayoflanguage,
8857 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8858 placeholder: "' . dol_escape_js($placeholder) . '",
8859 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8860 minimumInputLength: ' . ((int) $minimumInputLength) . ',
8861 formatResult: function (result, container, query, escapeMarkup) {
8862 return escapeMarkup(result.text);
8863 },
8864 });
8865
8866 ' . ($callurlonselect ? '
8867 /* Code to execute a GET when we select a value */
8868 $(".' . $htmlname . '").change(function() {
8869 var selected = $(".' . $htmlname . '").val();
8870 console.log("We select in selectArrayAjax the entry "+selected)
8871 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8872 $.each( saveRemoteData, function( key, value ) {
8873 if (key == selected)
8874 {
8875 console.log("selectArrayAjax - Do a redirect to "+value.url)
8876 location.assign(value.url);
8877 }
8878 });
8879 });' : '') . '
8880
8881 });
8882 </script>';
8883 }
8884
8885 if ($acceptdelayedhtml) {
8886 $delayedhtmlcontent .= $outdelayed;
8887 } else {
8888 $out .= $outdelayed;
8889 }
8890 return $out;
8891 }
8892
8912 public static function selectArrayFilter($htmlname, $array, $id = '', $moreparam = '', $disableFiltering = 0, $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0, $textfortitle = '')
8913 {
8914 global $conf, $langs;
8915 global $delayedhtmlcontent; // Will be used later outside of this function
8916
8917 // TODO Use an internal dolibarr component instead of select2
8918 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8919 return '';
8920 }
8921
8922 $out = '<select type="text"'.($textfortitle ? ' title="'.dol_escape_htmltag($textfortitle).'"' : '').' id="'.$htmlname.'" class="'.$htmlname.($morecss ? ' ' . $morecss : '').'"'.($moreparam ? ' '.$moreparam : '').' name="'.$htmlname.'"><option></option></select>';
8923
8924 $formattedarrayresult = array();
8925
8926 foreach ($array as $key => $value) {
8927 $o = new stdClass();
8928 $o->id = $key;
8929 $o->text = $value['text'];
8930 $o->url = $value['url'];
8931 $formattedarrayresult[] = $o;
8932 }
8933
8934 $outdelayed = '';
8935 if (!empty($conf->use_javascript_ajax)) {
8936 $tmpplugin = 'select2';
8937 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8938 <script nonce="' . getNonce() . '">
8939 $(document).ready(function () {
8940 var data = ' . json_encode($formattedarrayresult) . ';
8941
8942 ' . ($callurlonselect ? 'var saveRemoteData = ' . json_encode($array) . ';' : '') . '
8943
8944 $(".' . $htmlname . '").select2({
8945 data: data,
8946 language: (typeof select2arrayoflanguage === \'undefined\') ? \'en\' : select2arrayoflanguage,
8947 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8948 placeholder: "' . dol_escape_js($placeholder) . '",
8949 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8950 minimumInputLength: ' . $minimumInputLength . ',
8951 formatResult: function (result, container, query, escapeMarkup) {
8952 return escapeMarkup(result.text);
8953 },
8954 matcher: function (params, data) {
8955
8956 if(! data.id) return null;';
8957
8958 if ($callurlonselect) {
8959 // We forge the url with 'sall='
8960 $outdelayed .= '
8961
8962 var urlBase = data.url;
8963 var separ = urlBase.indexOf("?") >= 0 ? "&" : "?";
8964 /* console.log("params.term="+params.term); */
8965 /* console.log("params.term encoded="+encodeURIComponent(params.term)); */
8966 saveRemoteData[data.id].url = urlBase + separ + "search_all=" + encodeURIComponent(params.term.replace(/\"/g, ""));';
8967 }
8968
8969 if (!$disableFiltering) {
8970 $outdelayed .= '
8971
8972 if(data.text.match(new RegExp(params.term))) {
8973 return data;
8974 }
8975
8976 return null;';
8977 } else {
8978 $outdelayed .= '
8979
8980 return data;';
8981 }
8982
8983 $outdelayed .= '
8984 }
8985 });
8986
8987 ' . ($callurlonselect ? '
8988 /* Code to execute a GET when we select a value */
8989 $(".' . $htmlname . '").change(function() {
8990 var selected = $(".' . $htmlname . '").val();
8991 console.log("We select "+selected)
8992
8993 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8994 $.each( saveRemoteData, function( key, value ) {
8995 if (key == selected)
8996 {
8997 console.log("selectArrayFilter - Do a redirect to "+value.url)
8998 location.assign(value.url);
8999 }
9000 });
9001 });' : '') . '
9002
9003 });
9004 </script>';
9005 }
9006
9007 if ($acceptdelayedhtml) {
9008 $delayedhtmlcontent .= $outdelayed;
9009 } else {
9010 $out .= $outdelayed;
9011 }
9012 return $out;
9013 }
9014
9033 public static function multiselectarray($htmlname, $array, $selected = array(), $key_in_label = 0, $value_as_key = 0, $morecss = '', $translate = 0, $width = 0, $moreattrib = '', $elemtype = '', $placeholder = '', $addjscombo = -1)
9034 {
9035 global $conf, $langs;
9036
9037 $out = '';
9038
9039 if ($addjscombo < 0) {
9040 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
9041 $addjscombo = 1;
9042 } else {
9043 $addjscombo = 0;
9044 }
9045 }
9046
9047 $useenhancedmultiselect = 0;
9048 if (!empty($conf->use_javascript_ajax) && !defined('MAIN_DO_NOT_USE_JQUERY_MULTISELECT') && (getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT'))) {
9049 if ($addjscombo) {
9050 $useenhancedmultiselect = 1; // Use the js multiselect in one line. Possible only if $addjscombo not 0.
9051 }
9052 }
9053
9054 // We need a hidden field because when using the multiselect, if we unselect all, there is no
9055 // variable submitted at all, so no way to make a difference between variable not submitted and variable
9056 // submitted to nothing.
9057 $out .= '<input type="hidden" name="'.$htmlname.'_multiselect" value="1">';
9058 // Output select component
9059 $out .= '<select id="' . $htmlname . '" class="multiselect' . ($useenhancedmultiselect ? ' multiselectononeline' : '') . ($morecss ? ' ' . $morecss : '') . '" multiple name="' . $htmlname . '[]"' . ($moreattrib ? ' ' . $moreattrib : '') . ($width ? ' style="width: ' . (preg_match('/%/', (string) $width) ? $width : $width . 'px') . '"' : '') . '>' . "\n";
9060 if (is_array($array) && !empty($array)) {
9061 if ($value_as_key) {
9062 $array = array_combine($array, $array);
9063 }
9064
9065 if (!empty($array)) {
9066 foreach ($array as $key => $value) {
9067 $tmpkey = $key;
9068 $tmpvalue = $value;
9069 $tmpcolor = '';
9070 $tmppicto = '';
9071 $tmplabelhtml = '';
9072 if (is_array($value) && array_key_exists('id', $value) && array_key_exists('label', $value)) {
9073 $tmpkey = $value['id'];
9074 $tmpvalue = empty($value['label']) ? '' : $value['label'];
9075 $tmpcolor = empty($value['color']) ? '' : $value['color'];
9076 $tmppicto = empty($value['picto']) ? '' : $value['picto'];
9077 $tmplabelhtml = empty($value['labelhtml']) ? (empty($value['data-html']) ? '' : $value['data-html']): $value['labelhtml'];
9078 }
9079 $newval = ($translate ? $langs->trans($tmpvalue) : $tmpvalue);
9080 $newval = ($key_in_label ? $tmpkey . ' - ' . $newval : $newval);
9081
9082 $out .= '<option value="' . $tmpkey . '"';
9083 if (is_array($selected) && !empty($selected) && in_array((string) $tmpkey, $selected) && ((string) $tmpkey != '')) {
9084 $out .= ' selected';
9085 }
9086 if (!empty($tmplabelhtml)) {
9087 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
9088 } else {
9089 $tmplabelhtml = ($tmppicto ? img_picto('', $tmppicto, 'class="pictofixedwidth" style="color: #' . $tmpcolor . '"') : '') . $newval;
9090 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
9091 }
9092 $out .= '>';
9093 $out .= dol_htmlentitiesbr($newval);
9094 $out .= '</option>' . "\n";
9095 }
9096 }
9097 }
9098 $out .= '</select>' . "\n";
9099
9100 // Add code for jquery to use multiselect
9101 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT')) {
9102 $out .= "\n" . '<!-- JS CODE TO ENABLE select for id ' . $htmlname . ', addjscombo=' . $addjscombo . ' -->';
9103 $out .= "\n" . '<script nonce="' . getNonce() . '">' . "\n";
9104 if ($addjscombo == 1) {
9105 $tmpplugin = !getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT;
9106 $out .= 'function formatResult(record, container) {' . "\n";
9107 // If property data-html set, we decode html entities and use this.
9108 // Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, '', 0, 1) when building the select option.
9109 $out .= ' if ($(record.element).attr("data-html") != undefined && typeof htmlEntityDecodeJs === "function") {';
9110 //$out .= ' console.log("aaa");';
9111 $out .= ' return htmlEntityDecodeJs($(record.element).attr("data-html"));';
9112 $out .= ' }'."\n";
9113 $out .= ' return record.text;';
9114 $out .= '}' . "\n";
9115 $out .= 'function formatSelection(record) {' . "\n";
9116 if ($elemtype == 'category') {
9117 $out .= 'return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';';
9118 } else {
9119 $out .= 'return record.text;';
9120 }
9121 $out .= '}' . "\n";
9122 $out .= '$(document).ready(function () {
9123 $(\'#' . $htmlname . '\').' . $tmpplugin . '({';
9124 if ($placeholder) {
9125 $out .= '
9126 placeholder: {
9127 id: \'-1\',
9128 text: \'' . dol_escape_js($placeholder) . '\'
9129 },';
9130 }
9131 $out .= ' dir: \'ltr\',
9132 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag (ko with multiselect) */
9133 dropdownCssClass: \'' . $morecss . '\', /* Line to add class on the new <span class="select2-selection...> tag (ok with multiselect). Need full version of select2. */
9134 // Specify format function for dropdown item
9135 formatResult: formatResult,
9136 templateResult: formatResult, /* For 4.0 */
9137 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
9138 // Specify format function for selected item
9139 formatSelection: formatSelection,
9140 templateSelection: formatSelection, /* For 4.0 */
9141 language: select2arrayoflanguage
9142 });
9143
9144 /* Add also morecss to the css .select2 that is after the #htmlname, for component that are show dynamically after load, because select2 set
9145 the size only if component is not hidden by default on load */
9146 $(\'#' . $htmlname . ' + .select2\').addClass(\'' . $morecss . '\');
9147 });' . "\n";
9148 } elseif ($addjscombo == 2 && !defined('DISABLE_MULTISELECT')) {
9149 // Add other js lib
9150 // TODO external lib multiselect/jquery.multi-select.js must have been loaded to use this multiselect plugin
9151 // ...
9152 $out .= 'console.log(\'addjscombo=2 for htmlname=' . $htmlname . '\');';
9153 $out .= '$(document).ready(function () {
9154 $(\'#' . $htmlname . '\').multiSelect({
9155 containerHTML: \'<div class="multi-select-container">\',
9156 menuHTML: \'<div class="multi-select-menu">\',
9157 buttonHTML: \'<span class="multi-select-button ' . $morecss . '">\',
9158 menuItemHTML: \'<label class="multi-select-menuitem">\',
9159 activeClass: \'multi-select-container--open\',
9160 noneText: \'' . $placeholder . '\'
9161 });
9162 })';
9163 }
9164 $out .= '</script>';
9165 }
9166
9167 return $out;
9168 }
9169
9170
9182 public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage, $pos = '')
9183 {
9184 global $langs, $user;
9185
9186 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
9187 return '';
9188 }
9189 if (empty($array)) {
9190 return '';
9191 }
9192
9193 $tmpvar = "MAIN_SELECTEDFIELDS_" . $varpage; // To get list of saved selected fields to show
9194
9195 if (!empty($user->conf->$tmpvar)) { // A list of fields was already customized for user
9196 $tmparray = explode(',', $user->conf->$tmpvar);
9197 foreach ($array as $key => $val) {
9198 //var_dump($key);
9199 //var_dump($tmparray);
9200 if (in_array($key, $tmparray)) {
9201 $array[$key]['checked'] = 1;
9202 } else {
9203 $array[$key]['checked'] = 0;
9204 }
9205 }
9206 } else { // There is no list of fields already customized for user
9207 foreach ($array as $key => $val) {
9208 if (!empty($array[$key]['checked']) && $array[$key]['checked'] < 0) {
9209 $array[$key]['checked'] = 0;
9210 }
9211 }
9212 }
9213
9214 $listoffieldsforselection = '';
9215 $listcheckedstring = '';
9216
9217 foreach ($array as $key => $val) {
9218 // var_dump($val);
9219 // var_dump(array_key_exists('enabled', $val));
9220 // var_dump(!$val['enabled']);
9221 if (array_key_exists('enabled', $val) && isset($val['enabled']) && !$val['enabled']) {
9222 unset($array[$key]); // We don't want this field
9223 continue;
9224 }
9225 if (!empty($val['type']) && $val['type'] == 'separate') {
9226 // Field remains in array but we don't add it into $listoffieldsforselection
9227 //$listoffieldsforselection .= '<li>-----</li>';
9228 continue;
9229 }
9230 if (!empty($val['label']) && $val['label']) {
9231 if (!empty($val['langfile']) && is_object($langs)) {
9232 $langs->load($val['langfile']);
9233 }
9234
9235 // Note: $val['checked'] <> 0 means we must show the field into the combo list @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset
9236 $listoffieldsforselection .= '<li><input type="checkbox" id="checkbox' . $key . '" value="' . $key . '"' . ((!array_key_exists('checked', $val) || empty($val['checked']) || $val['checked'] == '-1') ? '' : ' checked="checked"') . '/><label for="checkbox' . $key . '">' . dol_escape_htmltag($langs->trans($val['label'])) . '</label></li>';
9237 $listcheckedstring .= (empty($val['checked']) ? '' : $key . ',');
9238 }
9239 }
9240
9241 $out = '<!-- Component multiSelectArrayWithCheckbox ' . $htmlname . ' -->
9242
9243 <dl class="dropdown">
9244 <dt>
9245 <a href="#' . $htmlname . '">
9246 ' . img_picto('', 'list') . '
9247 </a>
9248 <input type="hidden" class="' . $htmlname . '" name="' . $htmlname . '" value="' . $listcheckedstring . '">
9249 </dt>
9250 <dd class="dropdowndd">
9251 <div class="multiselectcheckbox'.$htmlname.'">
9252 <ul class="'.$htmlname.($pos == '1' ? 'left' : '').'">
9253 <li><input class="inputsearch_dropdownselectedfields width90p minwidth200imp" style="width:90%;" type="text" placeholder="'.$langs->trans('Search').'"></li>
9254 '.$listoffieldsforselection.'
9255 </ul>
9256 </div>
9257 </dd>
9258 </dl>
9259
9260 <script nonce="' . getNonce() . '" type="text/javascript">
9261 jQuery(document).ready(function () {
9262 $(\'.multiselectcheckbox' . $htmlname . ' input[type="checkbox"]\').on(\'click\', function () {
9263 console.log("A new field was added/removed, we edit field input[name=formfilteraction]");
9264
9265 $("input:hidden[name=formfilteraction]").val(\'listafterchangingselectedfields\'); // Update field so we know we changed something on selected fields after POST
9266
9267 var title = $(this).val() + ",";
9268 if ($(this).is(\':checked\')) {
9269 $(\'.' . $htmlname . '\').val(title + $(\'.' . $htmlname . '\').val());
9270 }
9271 else {
9272 $(\'.' . $htmlname . '\').val( $(\'.' . $htmlname . '\').val().replace(title, \'\') )
9273 }
9274 // Now, we submit page
9275 //$(this).parents(\'form:first\').submit();
9276 });
9277 $("input.inputsearch_dropdownselectedfields").on("keyup", function() {
9278 var value = $(this).val().toLowerCase();
9279 $(\'.multiselectcheckbox'.$htmlname.' li > label\').filter(function() {
9280 $(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
9281 });
9282 });
9283
9284
9285 });
9286 </script>
9287
9288 ';
9289 return $out;
9290 }
9291
9301 public function showCategories($id, $type, $rendermode = 0, $nolink = 0)
9302 {
9303 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
9304
9305 $cat = new Categorie($this->db);
9306 $categories = $cat->containing($id, $type);
9307
9308 if ($rendermode == 1) {
9309 $toprint = array();
9310 foreach ($categories as $c) {
9311 $ways = $c->print_all_ways(' &gt;&gt; ', ($nolink ? 'none' : ''), 0, 1); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
9312 foreach ($ways as $way) {
9313 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . $way . '</li>';
9314 }
9315 }
9316 if (empty($toprint)) {
9317 return '';
9318 } else {
9319 return '<div class="select2-container-multi-dolibarr"><ul class="select2-choices-dolibarr">' . implode(' ', $toprint) . '</ul></div>';
9320 }
9321 }
9322
9323 if ($rendermode == 0) {
9324 $arrayselected = array();
9325 $cate_arbo = $this->select_all_categories($type, '', 'parent', 64, 0, 3);
9326 foreach ($categories as $c) {
9327 $arrayselected[] = $c->id;
9328 }
9329
9330 return $this->multiselectarray('categories', $cate_arbo, $arrayselected, 0, 0, '', 0, '100%', 'disabled', 'category');
9331 }
9332
9333 return 'ErrorBadValueForParameterRenderMode'; // Should not happened
9334 }
9335
9345 public function showLinkedObjectBlock($object, $morehtmlright = '', $compatibleImportElementsList = array(), $title = 'RelatedObjects')
9346 {
9347 global $conf, $langs, $hookmanager;
9348 global $bc, $action;
9349
9350 $object->fetchObjectLinked();
9351
9352 // Bypass the default method
9353 $hookmanager->initHooks(array('commonobject'));
9354 $parameters = array(
9355 'morehtmlright' => $morehtmlright,
9356 'compatibleImportElementsList' => &$compatibleImportElementsList,
9357 );
9358 $reshook = $hookmanager->executeHooks('showLinkedObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9359
9360 $nbofdifferenttypes = count($object->linkedObjects);
9361
9362 if (empty($reshook)) {
9363 print '<!-- showLinkedObjectBlock -->';
9364 print load_fiche_titre($langs->trans($title), $morehtmlright, '', 0, 0, 'showlinkedobjectblock');
9365
9366
9367 print '<div class="div-table-responsive-no-min">';
9368 print '<table class="noborder allwidth" data-block="showLinkedObject" data-element="' . $object->element . '" data-elementid="' . $object->id . '" >';
9369
9370 print '<tr class="liste_titre">';
9371 print '<td>' . $langs->trans("Type") . '</td>';
9372 print '<td>' . $langs->trans("Ref") . '</td>';
9373 print '<td class="center"></td>';
9374 print '<td class="center">' . $langs->trans("Date") . '</td>';
9375 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9376 print '<td class="right">' . $langs->trans("Status") . '</td>';
9377 print '<td></td>';
9378 print '</tr>';
9379
9380 $nboftypesoutput = 0;
9381
9382 foreach ($object->linkedObjects as $objecttype => $objects) {
9383 $tplpath = $element = $subelement = $objecttype;
9384
9385 // to display import button on tpl
9386 $showImportButton = false;
9387 if (!empty($compatibleImportElementsList) && in_array($element, $compatibleImportElementsList)) {
9388 $showImportButton = true;
9389 }
9390
9391 $regs = array();
9392 if ($objecttype != 'supplier_proposal' && preg_match('/^([^_]+)_([^_]+)/i', $objecttype, $regs)) {
9393 $element = $regs[1];
9394 $subelement = $regs[2];
9395 $tplpath = $element . '/' . $subelement;
9396 }
9397 $tplname = 'linkedobjectblock';
9398
9399 // To work with non standard path
9400 if ($objecttype == 'facture') {
9401 $tplpath = 'compta/' . $element;
9402 if (!isModEnabled('invoice')) {
9403 continue; // Do not show if module disabled
9404 }
9405 } elseif ($objecttype == 'facturerec') {
9406 $tplpath = 'compta/facture';
9407 $tplname = 'linkedobjectblockForRec';
9408 if (!isModEnabled('invoice')) {
9409 continue; // Do not show if module disabled
9410 }
9411 } elseif ($objecttype == 'propal') {
9412 $tplpath = 'comm/' . $element;
9413 if (!isModEnabled('propal')) {
9414 continue; // Do not show if module disabled
9415 }
9416 } elseif ($objecttype == 'supplier_proposal') {
9417 if (!isModEnabled('supplier_proposal')) {
9418 continue; // Do not show if module disabled
9419 }
9420 } elseif ($objecttype == 'shipping' || $objecttype == 'shipment' || $objecttype == 'expedition') {
9421 $tplpath = 'expedition';
9422 if (!isModEnabled('shipping')) {
9423 continue; // Do not show if module disabled
9424 }
9425 } elseif ($objecttype == 'reception') {
9426 $tplpath = 'reception';
9427 if (!isModEnabled('reception')) {
9428 continue; // Do not show if module disabled
9429 }
9430 } elseif ($objecttype == 'delivery') {
9431 $tplpath = 'delivery';
9432 if (!getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) {
9433 continue; // Do not show if sub module disabled
9434 }
9435 } elseif ($objecttype == 'ficheinter') {
9436 $tplpath = 'fichinter';
9437 if (!isModEnabled('intervention')) {
9438 continue; // Do not show if module disabled
9439 }
9440 } elseif ($objecttype == 'invoice_supplier') {
9441 $tplpath = 'fourn/facture';
9442 } elseif ($objecttype == 'order_supplier') {
9443 $tplpath = 'fourn/commande';
9444 } elseif ($objecttype == 'expensereport') {
9445 $tplpath = 'expensereport';
9446 } elseif ($objecttype == 'subscription') {
9447 $tplpath = 'adherents';
9448 } elseif ($objecttype == 'conferenceorbooth') {
9449 $tplpath = 'eventorganization';
9450 } elseif ($objecttype == 'conferenceorboothattendee') {
9451 $tplpath = 'eventorganization';
9452 } elseif ($objecttype == 'mo') {
9453 $tplpath = 'mrp';
9454 if (!isModEnabled('mrp')) {
9455 continue; // Do not show if module disabled
9456 }
9457 }
9458
9459 global $linkedObjectBlock;
9460 $linkedObjectBlock = $objects;
9461
9462 // Output template part (modules that overwrite templates must declare this into descriptor)
9463 $dirtpls = array_merge($conf->modules_parts['tpl'], array('/' . $tplpath . '/tpl'));
9464 foreach ($dirtpls as $reldir) {
9465 $reldir = rtrim($reldir, '/');
9466 if ($nboftypesoutput == ($nbofdifferenttypes - 1)) { // No more type to show after
9467 global $noMoreLinkedObjectBlockAfter;
9468 $noMoreLinkedObjectBlockAfter = 1;
9469 }
9470
9471 $res = @include dol_buildpath($reldir . '/' . $tplname . '.tpl.php');
9472 if ($res) {
9473 $nboftypesoutput++;
9474 break;
9475 }
9476 }
9477 }
9478
9479 if (!$nboftypesoutput) {
9480 print '<tr><td class="impair" colspan="7"><span class="opacitymedium">' . $langs->trans("None") . '</span></td></tr>';
9481 }
9482
9483 print '</table>';
9484
9485 if (!empty($compatibleImportElementsList)) {
9486 $res = @include dol_buildpath('core/tpl/objectlinked_lineimport.tpl.php');
9487 }
9488
9489 print '</div>';
9490 }
9491
9492 return $nbofdifferenttypes;
9493 }
9494
9503 public function showLinkToObjectBlock($object, $restrictlinksto = array(), $excludelinksto = array())
9504 {
9505 global $conf, $langs, $hookmanager;
9506 global $action;
9507
9508 $linktoelem = '';
9509 $linktoelemlist = '';
9510 $listofidcompanytoscan = '';
9511
9512 if (!is_object($object->thirdparty)) {
9513 $object->fetch_thirdparty();
9514 }
9515
9516 $possiblelinks = array();
9517 if (is_object($object->thirdparty) && !empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
9518 $listofidcompanytoscan = $object->thirdparty->id;
9519 if (($object->thirdparty->parent > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PARENT_IN_LINKTO')) {
9520 $listofidcompanytoscan .= ',' . $object->thirdparty->parent;
9521 }
9522 if (($object->fk_project > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PROJECT_THIRDPARY_IN_LINKTO')) {
9523 include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
9524 $tmpproject = new Project($this->db);
9525 $tmpproject->fetch($object->fk_project);
9526 if ($tmpproject->socid > 0 && ($tmpproject->socid != $object->thirdparty->id)) {
9527 $listofidcompanytoscan .= ',' . $tmpproject->socid;
9528 }
9529 unset($tmpproject);
9530 }
9531
9532 $possiblelinks = array(
9533 'propal' => array(
9534 'enabled' => isModEnabled('propal'),
9535 'perms' => 1,
9536 'label' => 'LinkToProposal',
9537 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "propal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('propal') . ')'),
9538 'shipping' => array(
9539 'enabled' => isModEnabled('shipping'),
9540 'perms' => 1,
9541 'label' => 'LinkToExpedition',
9542 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "expedition as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('shipping') . ')'),
9543 'order' => array(
9544 'enabled' => isModEnabled('order'),
9545 'perms' => 1,
9546 'label' => 'LinkToOrder',
9547 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "commande as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('commande') . ')'),
9548 'invoice' => array(
9549 'enabled' => isModEnabled('invoice'),
9550 'perms' => 1,
9551 'label' => 'LinkToInvoice',
9552 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('invoice') . ')'),
9553 'invoice_template' => array(
9554 'enabled' => isModEnabled('invoice'),
9555 'perms' => 1,
9556 'label' => 'LinkToTemplateInvoice',
9557 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.titre as ref, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture_rec as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('invoice') . ')'),
9558 'contrat' => array(
9559 'enabled' => isModEnabled('contract'),
9560 'perms' => 1,
9561 'label' => 'LinkToContract',
9562 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_customer as ref_client, t.ref_supplier, SUM(td.total_ht) as total_ht
9563 FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "contrat as t, " . $this->db->prefix() . "contratdet as td WHERE t.fk_soc = s.rowid AND td.fk_contrat = t.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('contract') . ') GROUP BY s.rowid, s.nom, s.client, t.rowid, t.ref, t.ref_customer, t.ref_supplier'
9564 ),
9565 'fichinter' => array(
9566 'enabled' => isModEnabled('intervention'),
9567 'perms' => 1,
9568 'label' => 'LinkToIntervention',
9569 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "fichinter as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('intervention') . ')'),
9570 'supplier_proposal' => array(
9571 'enabled' => isModEnabled('supplier_proposal'),
9572 'perms' => 1,
9573 'label' => 'LinkToSupplierProposal',
9574 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, '' as ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "supplier_proposal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('supplier_proposal') . ')'),
9575 'order_supplier' => array(
9576 'enabled' => isModEnabled("supplier_order"),
9577 'perms' => 1,
9578 'label' => 'LinkToSupplierOrder',
9579 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('commande_fournisseur') . ')'),
9580 'invoice_supplier' => array(
9581 'enabled' => isModEnabled("supplier_invoice"),
9582 'perms' => 1, 'label' => 'LinkToSupplierInvoice',
9583 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture_fourn as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('facture_fourn') . ')'),
9584 'ticket' => array(
9585 'enabled' => isModEnabled('ticket'),
9586 'perms' => 1,
9587 'label' => 'LinkToTicket',
9588 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.track_id, '0' as total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "ticket as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('ticket') . ')'),
9589 'mo' => array(
9590 'enabled' => isModEnabled('mrp'),
9591 'perms' => 1,
9592 'label' => 'LinkToMo',
9593 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.rowid, '0' as total_ht FROM " . $this->db->prefix() . "societe as s INNER JOIN " . $this->db->prefix() . "mrp_mo as t ON t.fk_soc = s.rowid WHERE t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('mo') . ')')
9594 );
9595 }
9596
9597 if ($object->table_element == 'commande_fournisseur') {
9598 $possiblelinks['mo']['sql'] = "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.rowid, '0' as total_ht FROM ".$this->db->prefix()."societe as s INNER JOIN ".$this->db->prefix().'mrp_mo as t ON t.fk_soc = s.rowid WHERE t.entity IN ('.getEntity('mo').')';
9599 } elseif ($object->table_element == 'mrp_mo') {
9600 $possiblelinks['order_supplier']['sql'] = "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix().'commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.entity IN ('.getEntity('commande_fournisseur').')';
9601 }
9602
9603 $reshook = 0; // Ensure $reshook is defined for static analysis
9604 if (!empty($listofidcompanytoscan)) { // If empty, we don't have criteria to scan the object we can link to
9605 // Can complete the possiblelink array
9606 $hookmanager->initHooks(array('commonobject'));
9607 $parameters = array('listofidcompanytoscan' => $listofidcompanytoscan, 'possiblelinks' => $possiblelinks);
9608 $reshook = $hookmanager->executeHooks('showLinkToObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9609 }
9610
9611 if (empty($reshook)) {
9612 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9613 $possiblelinks = array_merge($possiblelinks, $hookmanager->resArray);
9614 }
9615 } elseif ($reshook > 0) {
9616 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9617 $possiblelinks = $hookmanager->resArray;
9618 }
9619 }
9620
9621 foreach ($possiblelinks as $key => $possiblelink) {
9622 $num = 0;
9623
9624 if (empty($possiblelink['enabled'])) {
9625 continue;
9626 }
9627
9628 if (!empty($possiblelink['perms']) && (empty($restrictlinksto) || in_array($key, $restrictlinksto)) && (empty($excludelinksto) || !in_array($key, $excludelinksto))) {
9629 print '<div id="' . $key . 'list"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display:none"') . '>';
9630
9631 if (getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9632 print '<br>'."\n";
9633 print '<!-- form to add a link from anywhere -->'."\n";
9634 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinkedbyref' . $key . '">';
9635 print '<input type="hidden" name="id" value="' . $object->id . '">';
9636 print '<input type="hidden" name="action" value="addlinkbyref">';
9637 print '<input type="hidden" name="token" value="' . newToken() . '">';
9638 print '<input type="hidden" name="addlink" value="' . $key . '">';
9639 print '<table class="noborder">';
9640 print '<tr>';
9641 //print '<td>' . $langs->trans("Ref") . '</td>';
9642 print '<td class="center"><input type="text" placeholder="'.dol_escape_htmltag($langs->trans("Ref")).'" name="reftolinkto" value="' . dol_escape_htmltag(GETPOST('reftolinkto', 'alpha')) . '">&nbsp;';
9643 print '<input type="submit" class="button small valignmiddle" value="' . $langs->trans('ToLink') . '">&nbsp;';
9644 print '<input type="submit" class="button small" name="cancel" value="' . $langs->trans('Cancel') . '"></td>';
9645 print '</tr>';
9646 print '</table>';
9647 print '</form>';
9648 }
9649
9650 $sql = $possiblelink['sql'];
9651
9652 $resqllist = $this->db->query($sql);
9653 if ($resqllist) {
9654 $num = $this->db->num_rows($resqllist);
9655 $i = 0;
9656
9657 print '<br>';
9658 print '<!-- form to add a link from object to same thirdparty -->'."\n";
9659 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinked' . $key . '">';
9660 print '<input type="hidden" name="action" value="addlink">';
9661 print '<input type="hidden" name="token" value="' . newToken() . '">';
9662 print '<input type="hidden" name="id" value="' . $object->id . '">';
9663 print '<input type="hidden" name="addlink" value="' . $key . '">';
9664 print '<table class="noborder">';
9665 print '<tr class="liste_titre">';
9666 print '<td class="nowrap"></td>';
9667 print '<td class="center">' . $langs->trans("Ref") . '</td>';
9668 print '<td class="left">' . $langs->trans("RefCustomer") . '</td>';
9669 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9670 print '<td class="left">' . $langs->trans("Company") . '</td>';
9671 print '</tr>';
9672 while ($i < $num) {
9673 $objp = $this->db->fetch_object($resqllist);
9674
9675 print '<tr class="oddeven">';
9676 print '<td class="left">';
9677 print '<input type="radio" name="idtolinkto" id="' . $key . '_' . $objp->rowid . '" value="' . $objp->rowid . '">';
9678 print '</td>';
9679 print '<td class="center"><label for="' . $key . '_' . $objp->rowid . '">' . $objp->ref . '</label></td>';
9680 print '<td>' . (!empty($objp->ref_client) ? $objp->ref_client : (!empty($objp->ref_supplier) ? $objp->ref_supplier : '')) . '</td>';
9681 print '<td class="right">';
9682 if ($possiblelink['label'] == 'LinkToContract') {
9683 $form = new Form($this->db);
9684 print $form->textwithpicto('', $langs->trans("InformationOnLinkToContract")) . ' ';
9685 }
9686 print '<span class="amount">' . (isset($objp->total_ht) ? price($objp->total_ht) : '') . '</span>';
9687 print '</td>';
9688 print '<td>' . $objp->name . '</td>';
9689 print '</tr>';
9690 $i++;
9691 }
9692 print '</table>';
9693 print '<div class="center">';
9694 if ($num) {
9695 print '<input type="submit" class="button valignmiddle marginleftonly marginrightonly small" value="' . $langs->trans('ToLink') . '">';
9696 }
9697 if (empty($conf->use_javascript_ajax)) {
9698 print '<input type="submit" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9699 } else {
9700 print '<input type="submit" onclick="jQuery(\'#' . $key . 'list\').toggle(); return false;" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9701 }
9702 print '</form>';
9703 $this->db->free($resqllist);
9704 } else {
9705 dol_print_error($this->db);
9706 }
9707 print '</div>';
9708
9709 //$linktoelem.=($linktoelem?' &nbsp; ':'');
9710 if ($num > 0 || getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9711 $linktoelemlist .= '<li><a href="#linkto' . $key . '" class="linkto dropdowncloseonclick" rel="' . $key . '">' . $langs->trans($possiblelink['label']) . ' (' . $num . ')</a></li>';
9712 // } else $linktoelem.=$langs->trans($possiblelink['label']);
9713 } else {
9714 $linktoelemlist .= '<li><span class="linktodisabled">' . $langs->trans($possiblelink['label']) . ' (0)</span></li>';
9715 }
9716 }
9717 }
9718
9719 if ($linktoelemlist) {
9720 $linktoelem = '
9721 <dl class="dropdown" id="linktoobjectname">
9722 ';
9723 if (!empty($conf->use_javascript_ajax)) {
9724 $linktoelem .= '<dt><a href="#linktoobjectname"><span class="fas fa-link paddingrightonly"></span>' . $langs->trans("LinkTo") . '...</a></dt>';
9725 }
9726 $linktoelem .= '<dd>
9727 <div class="multiselectlinkto">
9728 <ul class="ulselectedfields">' . $linktoelemlist . '
9729 </ul>
9730 </div>
9731 </dd>
9732 </dl>';
9733 } else {
9734 $linktoelem = '';
9735 }
9736
9737 if (!empty($conf->use_javascript_ajax)) {
9738 print '<!-- Add js to show linkto box -->
9739 <script nonce="' . getNonce() . '">
9740 jQuery(document).ready(function() {
9741 jQuery(".linkto").click(function() {
9742 console.log("We choose to show/hide links for rel="+jQuery(this).attr(\'rel\')+" so #"+jQuery(this).attr(\'rel\')+"list");
9743 jQuery("#"+jQuery(this).attr(\'rel\')+"list").toggle();
9744 });
9745 });
9746 </script>
9747 ';
9748 }
9749
9750 return $linktoelem;
9751 }
9752
9767 public function selectyesno($htmlname, $value = '', $option = 0, $disabled = false, $useempty = 0, $addjscombo = 0, $morecss = '', $labelyes = 'Yes', $labelno = 'No')
9768 {
9769 global $langs;
9770
9771 $yes = "yes";
9772 $no = "no";
9773 if ($option) {
9774 $yes = "1";
9775 $no = "0";
9776 }
9777
9778 $disabled = ($disabled ? ' disabled' : '');
9779
9780 $resultyesno = '<select class="flat width75' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '"' . $disabled . '>' . "\n";
9781 if ($useempty) {
9782 $resultyesno .= '<option value="-1"' . (($value < 0) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
9783 }
9784 if (("$value" == 'yes') || ($value == 1)) {
9785 $resultyesno .= '<option value="' . $yes . '" selected>' . $langs->trans($labelyes) . '</option>' . "\n";
9786 $resultyesno .= '<option value="' . $no . '">' . $langs->trans($labelno) . '</option>' . "\n";
9787 } else {
9788 $selected = (($useempty && $value != '0' && $value != 'no') ? '' : ' selected');
9789 $resultyesno .= '<option value="' . $yes . '">' . $langs->trans($labelyes) . '</option>' . "\n";
9790 $resultyesno .= '<option value="' . $no . '"' . $selected . '>' . $langs->trans($labelno) . '</option>' . "\n";
9791 }
9792 $resultyesno .= '</select>' . "\n";
9793
9794 if ($addjscombo) {
9795 $resultyesno .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($useempty < 0 ? (string) $useempty : '-1'), $morecss);
9796 }
9797
9798 return $resultyesno;
9799 }
9800
9801 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
9802
9812 public function select_export_model($selected = '', $htmlname = 'exportmodelid', $type = '', $useempty = 0)
9813 {
9814 // phpcs:enable
9815 $sql = "SELECT rowid, label";
9816 $sql .= " FROM " . $this->db->prefix() . "export_model";
9817 $sql .= " WHERE type = '" . $this->db->escape($type) . "'";
9818 $sql .= " ORDER BY rowid";
9819 $result = $this->db->query($sql);
9820 if ($result) {
9821 print '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
9822 if ($useempty) {
9823 print '<option value="-1">&nbsp;</option>';
9824 }
9825
9826 $num = $this->db->num_rows($result);
9827 $i = 0;
9828 while ($i < $num) {
9829 $obj = $this->db->fetch_object($result);
9830 if ($selected == $obj->rowid) {
9831 print '<option value="' . $obj->rowid . '" selected>';
9832 } else {
9833 print '<option value="' . $obj->rowid . '">';
9834 }
9835 print $obj->label;
9836 print '</option>';
9837 $i++;
9838 }
9839 print "</select>";
9840 } else {
9841 dol_print_error($this->db);
9842 }
9843 }
9844
9863 public function showrefnav($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $morehtmlright = '')
9864 {
9865 global $conf, $langs, $hookmanager, $extralanguages;
9866
9867 $ret = '';
9868 if (empty($fieldid)) {
9869 $fieldid = 'rowid';
9870 }
9871 if (empty($fieldref)) {
9872 $fieldref = 'ref';
9873 }
9874
9875 // Preparing gender's display if there is one
9876 $addgendertxt = '';
9877 if (property_exists($object, 'gender') && !empty($object->gender)) {
9878 $addgendertxt = ' ';
9879 switch ($object->gender) {
9880 case 'man':
9881 $addgendertxt .= '<i class="fas fa-mars"></i>';
9882 break;
9883 case 'woman':
9884 $addgendertxt .= '<i class="fas fa-venus"></i>';
9885 break;
9886 case 'other':
9887 $addgendertxt .= '<i class="fas fa-transgender"></i>';
9888 break;
9889 }
9890 }
9891
9892 // Add where from hooks
9893 if (is_object($hookmanager)) {
9894 $parameters = array('showrefnav' => true);
9895 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
9896 if (!empty($hookmanager->resPrint)) {
9897 if (empty($object->next_prev_filter) && preg_match('/^\s*AND/i', $hookmanager->resPrint)) {
9898 $object->next_prev_filter = preg_replace('/^\s*AND\s*/i', '', $hookmanager->resPrint);
9899 } elseif (!empty($object->next_prev_filter) && !preg_match('/^\s*AND/i', $hookmanager->resPrint)) {
9900 $object->next_prev_filter .= ' AND '.$hookmanager->resPrint;
9901 } else {
9902 $object->next_prev_filter .= $hookmanager->resPrint;
9903 }
9904 }
9905 }
9906
9907 $previous_ref = $next_ref = '';
9908 if ($shownav) {
9909 //print "paramid=$paramid,morehtml=$morehtml,shownav=$shownav,$fieldid,$fieldref,$morehtmlref,$moreparam";
9910 $object->load_previous_next_ref((isset($object->next_prev_filter) ? $object->next_prev_filter : ''), $fieldid, $nodbprefix);
9911
9912 $navurl = $_SERVER["PHP_SELF"];
9913 // Special case for project/task page
9914 if ($paramid == 'project_ref') {
9915 if (preg_match('/\/tasks\/(task|contact|note|document)\.php/', $navurl)) { // TODO Remove this when nav with project_ref on task pages are ok
9916 $navurl = preg_replace('/\/tasks\/(task|contact|time|note|document)\.php/', '/tasks.php', $navurl);
9917 $paramid = 'ref';
9918 }
9919 }
9920
9921 // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox
9922 // accesskey is for Mac: CTRL + key for all browsers
9923 $stringforfirstkey = $langs->trans("KeyboardShortcut");
9924 if ($conf->browser->name == 'chrome') {
9925 $stringforfirstkey .= ' ALT +';
9926 } elseif ($conf->browser->name == 'firefox') {
9927 $stringforfirstkey .= ' ALT + SHIFT +';
9928 } else {
9929 $stringforfirstkey .= ' CTL +';
9930 }
9931
9932 $previous_ref = $object->ref_previous ? '<a accesskey="p" alt="'.dol_escape_htmltag($langs->trans("Previous")).'" title="' . $stringforfirstkey . ' p" class="classfortooltip" href="' . $navurl . '?' . $paramid . '=' . urlencode($object->ref_previous) . $moreparam . '"><i class="fa fa-chevron-left"></i></a>' : '<span class="inactive"><i class="fa fa-chevron-left opacitymedium"></i></span>';
9933 $next_ref = $object->ref_next ? '<a accesskey="n" alt="'.dol_escape_htmltag($langs->trans("Next")).'" title="' . $stringforfirstkey . ' n" class="classfortooltip" href="' . $navurl . '?' . $paramid . '=' . urlencode($object->ref_next) . $moreparam . '"><i class="fa fa-chevron-right"></i></a>' : '<span class="inactive"><i class="fa fa-chevron-right opacitymedium"></i></span>';
9934 }
9935
9936 //print "xx".$previous_ref."x".$next_ref;
9937 $ret .= '<!-- Start banner content --><div style="vertical-align: middle">';
9938
9939 // Right part of banner
9940 if ($morehtmlright) {
9941 $ret .= '<div class="inline-block floatleft">' . $morehtmlright . '</div>';
9942 }
9943
9944 if ($previous_ref || $next_ref || $morehtml) {
9945 $ret .= '<div class="pagination paginationref"><ul class="right">';
9946 }
9947 if ($morehtml && getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2) {
9948 $ret .= '<!-- morehtml --><li class="noborder litext' . (($shownav && $previous_ref && $next_ref) ? ' clearbothonsmartphone' : '') . '">' . $morehtml . '</li>';
9949 }
9950 if ($shownav && ($previous_ref || $next_ref)) {
9951 $ret .= '<li class="pagination">' . $previous_ref . '</li>';
9952 $ret .= '<li class="pagination">' . $next_ref . '</li>';
9953 }
9954 if ($previous_ref || $next_ref || $morehtml) {
9955 $ret .= '</ul></div>';
9956 }
9957
9958 // Status
9959 $parameters = array('morehtmlstatus' => $morehtmlstatus);
9960 $reshook = $hookmanager->executeHooks('moreHtmlStatus', $parameters, $object); // Note that $action and $object may have been modified by hook
9961 if (empty($reshook)) {
9962 $morehtmlstatus .= $hookmanager->resPrint;
9963 } else {
9964 $morehtmlstatus = $hookmanager->resPrint;
9965 }
9966 if ($morehtmlstatus) {
9967 $ret .= '<div class="statusref">' . $morehtmlstatus . '</div>';
9968 }
9969
9970 $parameters = array();
9971 $reshook = $hookmanager->executeHooks('moreHtmlRef', $parameters, $object); // Note that $action and $object may have been modified by hook
9972 if (empty($reshook)) {
9973 $morehtmlref .= $hookmanager->resPrint;
9974 } elseif ($reshook > 0) {
9975 $morehtmlref = $hookmanager->resPrint;
9976 }
9977
9978 // Left part of banner
9979 if ($morehtmlleft) {
9980 if ($conf->browser->layout == 'phone') {
9981 $ret .= '<!-- morehtmlleft --><div class="floatleft">' . $morehtmlleft . '</div>';
9982 } else {
9983 $ret .= '<!-- morehtmlleft --><div class="inline-block floatleft">' . $morehtmlleft . '</div>';
9984 }
9985 }
9986
9987 //if ($conf->browser->layout == 'phone') $ret.='<div class="clearboth"></div>';
9988 $ret .= '<div class="inline-block floatleft valignmiddle maxwidth750 marginbottomonly refid' . (($shownav && ($previous_ref || $next_ref)) ? ' refidpadding' : '') . '">';
9989
9990 // For thirdparty, contact, user, member, the ref is the id, so we show something else
9991 if ($object->element == 'societe') {
9992 $ret .= dol_htmlentities($object->name);
9993
9994 // List of extra languages
9995 $arrayoflangcode = array();
9996 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
9997 $arrayoflangcode[] = getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE');
9998 }
9999
10000 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
10001 if (!is_object($extralanguages)) {
10002 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
10003 $extralanguages = new ExtraLanguages($this->db);
10004 }
10005 $extralanguages->fetch_name_extralanguages('societe');
10006
10007 if (!empty($extralanguages->attributes['societe']['name'])) {
10008 $object->fetchValuesForExtraLanguages();
10009
10010 $htmltext = '';
10011 // If there is extra languages
10012 foreach ($arrayoflangcode as $extralangcode) {
10013 $htmltext .= picto_from_langcode($extralangcode, 'class="pictoforlang paddingright"');
10014 if ($object->array_languages['name'][$extralangcode]) {
10015 $htmltext .= $object->array_languages['name'][$extralangcode];
10016 } else {
10017 $htmltext .= '<span class="opacitymedium">' . $langs->trans("SwitchInEditModeToAddTranslation") . '</span>';
10018 }
10019 }
10020 $ret .= '<!-- Show translations of name -->' . "\n";
10021 $ret .= $this->textwithpicto('', $htmltext, -1, 'language', 'opacitymedium paddingleft');
10022 }
10023 }
10024 } elseif ($object->element == 'member') {
10025 '@phan-var-force Adherent $object';
10026 $ret .= $object->ref . '<br>';
10027 $fullname = $object->getFullName($langs);
10028 if ($object->morphy == 'mor' && $object->societe) {
10029 $ret .= dol_htmlentities($object->societe) . ((!empty($fullname) && $object->societe != $fullname) ? ' (' . dol_htmlentities($fullname) . $addgendertxt . ')' : '');
10030 } else {
10031 $ret .= dol_htmlentities($fullname) . $addgendertxt . ((!empty($object->societe) && $object->societe != $fullname) ? ' (' . dol_htmlentities($object->societe) . ')' : '');
10032 }
10033 } elseif (in_array($object->element, array('contact', 'user'))) {
10034 $ret .= dol_htmlentities($object->getFullName($langs)) . $addgendertxt;
10035 } elseif ($object->element == 'usergroup') {
10036 $ret .= dol_htmlentities($object->name);
10037 } elseif (in_array($object->element, array('action', 'agenda'))) {
10038 '@phan-var-force ActionComm $object';
10039 $ret .= $object->ref . '<br>' . $object->label;
10040 } elseif (in_array($object->element, array('adherent_type'))) {
10041 $ret .= $object->label;
10042 } elseif ($object->element == 'ecm_directories') {
10043 $ret .= '';
10044 } elseif ($fieldref != 'none') {
10045 $ret .= dol_htmlentities(!empty($object->$fieldref) ? $object->$fieldref : "");
10046 }
10047 if ($morehtmlref) {
10048 // don't add a additional space, when "$morehtmlref" starts with a HTML div tag
10049 if (substr($morehtmlref, 0, 4) != '<div') {
10050 $ret .= ' ';
10051 }
10052
10053 $ret .= $morehtmlref;
10054 }
10055
10056 $ret .= '</div>';
10057
10058 $ret .= '</div><!-- End banner content -->';
10059
10060 return $ret;
10061 }
10062
10063
10072 public function showbarcode(&$object, $width = 100, $morecss = '')
10073 {
10074 global $conf;
10075
10076 //Check if barcode is filled in the card
10077 if (empty($object->barcode)) {
10078 return '';
10079 }
10080
10081 // Complete object if not complete
10082 if (empty($object->barcode_type_code) || empty($object->barcode_type_coder)) {
10083 // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
10084 $result = $object->fetch_barcode();
10085 //Check if fetch_barcode() failed
10086 if ($result < 1) {
10087 return '<!-- ErrorFetchBarcode -->';
10088 }
10089 }
10090
10091 // Barcode image @phan-suppress-next-line PhanUndeclaredProperty
10092 $url = DOL_URL_ROOT . '/viewimage.php?modulepart=barcode&generator=' . urlencode($object->barcode_type_coder) . '&code=' . urlencode($object->barcode) . '&encoding=' . urlencode($object->barcode_type_code);
10093 $out = '<!-- url barcode = ' . $url . ' -->';
10094 $out .= '<img src="' . $url . '"' . ($morecss ? ' class="' . $morecss . '"' : '') . '>';
10095
10096 return $out;
10097 }
10098
10116 public static function showphoto($modulepart, $object, $width = 100, $height = 0, $caneditfield = 0, $cssclass = 'photowithmargin', $imagesize = '', $addlinktofullsize = 1, $cache = 0, $forcecapture = '', $noexternsourceoverwrite = 0)
10117 {
10118 global $conf, $langs;
10119
10120 $entity = (empty($object->entity) ? $conf->entity : $object->entity);
10121 $id = (empty($object->id) ? $object->rowid : $object->id); // @phan-suppress-current-line PhanUndeclaredProperty (->rowid)
10122
10123 $dir = '';
10124 $file = '';
10125 $originalfile = '';
10126 $altfile = '';
10127 $email = '';
10128 $capture = '';
10129 if ($modulepart == 'societe') {
10130 $dir = $conf->societe->multidir_output[$entity];
10131 if (!empty($object->logo)) {
10132 if (dolIsAllowedForPreview($object->logo)) {
10133 if ((string) $imagesize == 'mini') {
10134 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_mini'); // getImageFileNameForSize include the thumbs
10135 } elseif ((string) $imagesize == 'small') {
10136 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_small');
10137 } else {
10138 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
10139 }
10140 $originalfile = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
10141 }
10142 }
10143 $email = $object->email;
10144 } elseif ($modulepart == 'contact') {
10145 $dir = $conf->societe->multidir_output[$entity] . '/contact';
10146 if (!empty($object->photo)) {
10147 if (dolIsAllowedForPreview($object->photo)) {
10148 if ((string) $imagesize == 'mini') {
10149 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10150 } elseif ((string) $imagesize == 'small') {
10151 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10152 } else {
10153 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
10154 }
10155 $originalfile = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
10156 }
10157 }
10158 $email = $object->email;
10159 $capture = 'user';
10160 } elseif ($modulepart == 'userphoto') {
10161 $dir = $conf->user->dir_output;
10162 if (!empty($object->photo)) {
10163 if (dolIsAllowedForPreview($object->photo)) {
10164 if ((string) $imagesize == 'mini') {
10165 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10166 } elseif ((string) $imagesize == 'small') {
10167 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10168 } else {
10169 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
10170 }
10171 $originalfile = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
10172 }
10173 }
10174 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
10175 $altfile = $object->id . ".jpg"; // For backward compatibility
10176 }
10177 $email = $object->email;
10178 $capture = 'user';
10179 } elseif ($modulepart == 'memberphoto') {
10180 $dir = $conf->adherent->dir_output;
10181 if (!empty($object->photo)) {
10182 if (dolIsAllowedForPreview($object->photo)) {
10183 if ((string) $imagesize == 'mini') {
10184 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10185 } elseif ((string) $imagesize == 'small') {
10186 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10187 } else {
10188 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
10189 }
10190 $originalfile = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
10191 }
10192 }
10193 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
10194 $altfile = $object->id . ".jpg"; // For backward compatibility
10195 }
10196 $email = $object->email;
10197 $capture = 'user';
10198 } else {
10199 // Generic case to show photos
10200 // TODO Implement this method in previous objects so we can always use this generic method.
10201 if ($modulepart != "unknown" && method_exists($object, 'getDataToShowPhoto')) {
10202 $tmpdata = $object->getDataToShowPhoto($modulepart, $imagesize);
10203
10204 $dir = $tmpdata['dir'];
10205 $file = $tmpdata['file'];
10206 $originalfile = $tmpdata['originalfile'];
10207 $altfile = $tmpdata['altfile'];
10208 $email = $tmpdata['email'];
10209 $capture = $tmpdata['capture'];
10210 }
10211 }
10212
10213 if ($forcecapture) {
10214 $capture = $forcecapture;
10215 }
10216
10217 $ret = '';
10218
10219 if ($dir) {
10220 if ($file && file_exists($dir . "/" . $file)) {
10221 if ($addlinktofullsize) {
10222 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
10223 if ($urladvanced) {
10224 $ret .= '<a href="' . $urladvanced . '">';
10225 } else {
10226 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
10227 }
10228 }
10229 $ret .= '<img alt="" class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . ' photologo' . (preg_replace('/[^a-z]/i', '_', $file)) . '" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($file) . '&cache=' . $cache . '">';
10230 if ($addlinktofullsize) {
10231 $ret .= '</a>';
10232 }
10233 } elseif ($altfile && file_exists($dir . "/" . $altfile)) {
10234 if ($addlinktofullsize) {
10235 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
10236 if ($urladvanced) {
10237 $ret .= '<a href="' . $urladvanced . '">';
10238 } else {
10239 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
10240 }
10241 }
10242 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="Photo alt" id="photologo' . (preg_replace('/[^a-z]/i', '_', $file)) . '" class="' . $cssclass . '" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($altfile) . '&cache=' . $cache . '">';
10243 if ($addlinktofullsize) {
10244 $ret .= '</a>';
10245 }
10246 } else {
10247 $nophoto = '/public/theme/common/nophoto.png';
10248 $defaultimg = 'identicon'; // For gravatar
10249 if (in_array($modulepart, array('societe', 'userphoto', 'contact', 'memberphoto'))) { // For modules that need a special image when photo not found
10250 if ($modulepart == 'societe' || ($modulepart == 'memberphoto' && !empty($object->morphy) && strpos($object->morphy, 'mor') !== false)) {
10251 $nophoto = 'company';
10252 } else {
10253 $nophoto = '/public/theme/common/user_anonymous.png';
10254 if (!empty($object->gender) && $object->gender == 'man') {
10255 $nophoto = '/public/theme/common/user_man.png';
10256 }
10257 if (!empty($object->gender) && $object->gender == 'woman') {
10258 $nophoto = '/public/theme/common/user_woman.png';
10259 }
10260 }
10261 }
10262
10263 if (isModEnabled('gravatar') && $email && empty($noexternsourceoverwrite)) {
10264 // see https://gravatar.com/site/implement/images/php/
10265 $ret .= '<!-- Put link to gravatar -->';
10266 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" title="' . $email . ' Gravatar avatar" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="https://www.gravatar.com/avatar/' . dol_hash(strtolower(trim($email)), 'sha256', 1) . '?s=' . $width . '&d=' . $defaultimg . '">'; // gravatar need md5 hash
10267 } else {
10268 if ($nophoto == 'company') {
10269 $ret .= '<div class="divforspanimg valignmiddle center photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . '>' . img_picto('', 'company') . '</div>';
10270 //$ret .= '<div class="difforspanimgright"></div>';
10271 } else {
10272 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . $nophoto . '">';
10273 }
10274 }
10275 }
10276
10277 if ($caneditfield) {
10278 if ($object->photo) {
10279 $ret .= "<br>\n";
10280 }
10281 $ret .= '<table class="nobordernopadding centpercent">';
10282 if ($object->photo) {
10283 $ret .= '<tr><td><input type="checkbox" class="flat photodelete" name="deletephoto" id="photodelete"> <label for="photodelete">' . $langs->trans("Delete") . '</label><br><br></td></tr>';
10284 }
10285 $ret .= '<tr><td class="tdoverflow">';
10286 $maxfilesizearray = getMaxFileSizeArray();
10287 $maxmin = $maxfilesizearray['maxmin'];
10288 if ($maxmin > 0) {
10289 $ret .= '<input type="hidden" name="MAX_FILE_SIZE" value="' . ($maxmin * 1024) . '">'; // MAX_FILE_SIZE must precede the field type=file
10290 }
10291 $ret .= '<input type="file" class="flat maxwidth200onsmartphone" name="photo" id="photoinput" accept="image/*"' . ($capture ? ' capture="' . $capture . '"' : '') . '>';
10292 $ret .= '</td></tr>';
10293 $ret .= '</table>';
10294 }
10295 }
10296
10297 return $ret;
10298 }
10299
10300 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
10301
10318 public function select_dolgroups($selected = 0, $htmlname = 'groupid', $show_empty = 0, $exclude = '', $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0', $multiple = false, $morecss = 'minwidth200')
10319 {
10320 // phpcs:enable
10321 global $conf, $user, $langs;
10322
10323 // Allow excluding groups
10324 $excludeGroups = null;
10325 if (is_array($exclude)) {
10326 $excludeGroups = implode(",", $exclude);
10327 }
10328 // Allow including groups
10329 $includeGroups = null;
10330 if (is_array($include)) {
10331 $includeGroups = implode(",", $include);
10332 }
10333
10334 if (!is_array($selected)) {
10335 $selected = array($selected);
10336 }
10337
10338 $out = '';
10339
10340 // Build sql to search groups
10341 $sql = "SELECT ug.rowid, ug.nom as name";
10342 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10343 $sql .= ", e.label";
10344 }
10345 $sql .= " FROM " . $this->db->prefix() . "usergroup as ug ";
10346 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10347 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid=ug.entity";
10348 if ($force_entity) {
10349 $sql .= " WHERE ug.entity IN (0, " . $force_entity . ")";
10350 } else {
10351 $sql .= " WHERE ug.entity IS NOT NULL";
10352 }
10353 } else {
10354 $sql .= " WHERE ug.entity IN (0, " . $conf->entity . ")";
10355 }
10356 if (is_array($exclude) && $excludeGroups) {
10357 $sql .= " AND ug.rowid NOT IN (" . $this->db->sanitize($excludeGroups) . ")";
10358 }
10359 if (is_array($include) && $includeGroups) {
10360 $sql .= " AND ug.rowid IN (" . $this->db->sanitize($includeGroups) . ")";
10361 }
10362 $sql .= " ORDER BY ug.nom ASC";
10363
10364 dol_syslog(get_class($this) . "::select_dolgroups", LOG_DEBUG);
10365 $resql = $this->db->query($sql);
10366 if ($resql) {
10367 // Enhance with select2
10368 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10369
10370 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
10371
10372 $num = $this->db->num_rows($resql);
10373 $i = 0;
10374 if ($num) {
10375 if ($show_empty && !$multiple) {
10376 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
10377 }
10378
10379 while ($i < $num) {
10380 $obj = $this->db->fetch_object($resql);
10381 $disableline = 0;
10382 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
10383 $disableline = 1;
10384 }
10385
10386 $label = $obj->name;
10387 $labelhtml = $obj->name;
10388 if (isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1) {
10389 $label .= " (" . $obj->label . ")";
10390 $labelhtml .= ' <span class="opacitymedium">(' . $obj->label . ')</span>';
10391 }
10392
10393 $out .= '<option value="' . $obj->rowid . '"';
10394 if ($disableline) {
10395 $out .= ' disabled';
10396 }
10397 if ((isset($selected[0]) && is_object($selected[0]) && $selected[0]->id == $obj->rowid)
10398 || ((!isset($selected[0]) || !is_object($selected[0])) && !empty($selected) && in_array($obj->rowid, $selected))) {
10399 $out .= ' selected';
10400 }
10401 $out .= ' data-html="'.dol_escape_htmltag($labelhtml).'"';
10402 $out .= '>';
10403 $out .= $label;
10404 $out .= '</option>';
10405 $i++;
10406 }
10407 } else {
10408 if ($show_empty) {
10409 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '></option>' . "\n";
10410 }
10411 $out .= '<option value="" disabled>' . $langs->trans("NoUserGroupDefined") . '</option>';
10412 }
10413 $out .= '</select>';
10414
10415 $out .= ajax_combobox($htmlname);
10416 } else {
10417 dol_print_error($this->db);
10418 }
10419
10420 return $out;
10421 }
10422
10423
10430 public function showFilterButtons($pos = '')
10431 {
10432 $out = '<div class="nowraponall">';
10433 $out .= '<button type="submit" class="liste_titre button_search reposition" name="button_search_x" value="x"><span class="fas fa-search"></span></button>';
10434 $out .= '<button type="submit" class="liste_titre button_removefilter reposition" name="button_removefilter_x" value="x"><span class="fas fa-times"></span></button>';
10435 $out .= '</div>';
10436
10437 return $out;
10438 }
10439
10448 public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10449 {
10450 global $conf;
10451
10452 $out = '';
10453
10454 if (!empty($conf->use_javascript_ajax)) {
10455 $out .= '<div class="inline-block checkallactions"><input type="checkbox" id="' . $cssclass . 's" name="' . $cssclass . 's" class="checkallactions"></div>';
10456 }
10457 $out .= '<script nonce="' . getNonce() . '">
10458 $(document).ready(function() {
10459 $("#' . $cssclass . 's").click(function() {
10460 if($(this).is(\':checked\')){
10461 console.log("We check all ' . $cssclass . ' and trigger the change method");
10462 $(".' . $cssclass . '").prop(\'checked\', true).trigger(\'change\');
10463 }
10464 else
10465 {
10466 console.log("We uncheck all");
10467 $(".' . $cssclass . '").prop(\'checked\', false).trigger(\'change\');
10468 }' . "\n";
10469 if ($calljsfunction) {
10470 $out .= 'if (typeof initCheckForSelect == \'function\') { initCheckForSelect(0, "' . $massactionname . '", "' . $cssclass . '"); } else { console.log("No function initCheckForSelect found. Call won\'t be done."); }';
10471 }
10472 $out .= ' });
10473 $(".' . $cssclass . '").change(function() {
10474 $(this).closest("tr").toggleClass("highlight", this.checked);
10475 });
10476 });
10477 </script>';
10478
10479 return $out;
10480 }
10481
10491 public function showFilterAndCheckAddButtons($addcheckuncheckall = 0, $cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10492 {
10493 $out = $this->showFilterButtons();
10494 if ($addcheckuncheckall) {
10495 $out .= $this->showCheckAddButtons($cssclass, $calljsfunction, $massactionname);
10496 }
10497 return $out;
10498 }
10499
10513 public function selectExpenseCategories($selected = '', $htmlname = 'fk_c_exp_tax_cat', $useempty = 0, $excludeid = array(), $target = '', $default_selected = 0, $params = array(), $info_admin = 1)
10514 {
10515 global $langs, $user;
10516
10517 $out = '';
10518 $sql = "SELECT rowid, label FROM " . $this->db->prefix() . "c_exp_tax_cat WHERE active = 1";
10519 $sql .= " AND entity IN (0," . getEntity('exp_tax_cat') . ")";
10520 if (!empty($excludeid)) {
10521 $sql .= " AND rowid NOT IN (" . $this->db->sanitize(implode(',', $excludeid)) . ")";
10522 }
10523 $sql .= " ORDER BY label";
10524
10525 $resql = $this->db->query($sql);
10526 if ($resql) {
10527 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp maxwidth200">';
10528 if ($useempty) {
10529 $out .= '<option value="0">&nbsp;</option>';
10530 }
10531
10532 while ($obj = $this->db->fetch_object($resql)) {
10533 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . $langs->trans($obj->label) . '</option>';
10534 }
10535 $out .= '</select>';
10536 $out .= ajax_combobox('select_' . $htmlname);
10537
10538 if (!empty($htmlname) && $user->admin && $info_admin) {
10539 $out .= ' ' . info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
10540 }
10541
10542 if (!empty($target)) {
10543 $sql = "SELECT c.id FROM " . $this->db->prefix() . "c_type_fees as c WHERE c.code = 'EX_KME' AND c.active = 1";
10544 $resql = $this->db->query($sql);
10545 if ($resql) {
10546 if ($this->db->num_rows($resql) > 0) {
10547 $obj = $this->db->fetch_object($resql);
10548 $out .= '<script nonce="' . getNonce() . '">
10549 $(function() {
10550 $("select[name=' . $target . ']").on("change", function() {
10551 var current_val = $(this).val();
10552 if (current_val == ' . $obj->id . ') {';
10553 if (!empty($default_selected) || !empty($selected)) {
10554 $out .= '$("select[name=' . $htmlname . ']").val("' . ($default_selected > 0 ? $default_selected : $selected) . '");';
10555 }
10556
10557 $out .= '
10558 $("select[name=' . $htmlname . ']").change();
10559 }
10560 });
10561
10562 $("select[name=' . $htmlname . ']").change(function() {
10563
10564 if ($("select[name=' . $target . ']").val() == ' . $obj->id . ') {
10565 // get price of kilometer to fill the unit price
10566 $.ajax({
10567 method: "POST",
10568 dataType: "json",
10569 data: { fk_c_exp_tax_cat: $(this).val(), token: \'' . currentToken() . '\' },
10570 url: "' . (DOL_URL_ROOT . '/expensereport/ajax/ajaxik.php?' . implode('&', $params)) . '",
10571 }).done(function( data, textStatus, jqXHR ) {
10572 console.log(data);
10573 if (typeof data.up != "undefined") {
10574 $("input[name=value_unit]").val(data.up);
10575 $("select[name=' . $htmlname . ']").attr("title", data.title);
10576 } else {
10577 $("input[name=value_unit]").val("");
10578 $("select[name=' . $htmlname . ']").attr("title", "");
10579 }
10580 });
10581 }
10582 });
10583 });
10584 </script>';
10585 }
10586 }
10587 }
10588 } else {
10589 dol_print_error($this->db);
10590 }
10591
10592 return $out;
10593 }
10594
10603 public function selectExpenseRanges($selected = '', $htmlname = 'fk_range', $useempty = 0)
10604 {
10605 global $conf, $langs;
10606
10607 $out = '';
10608 $sql = "SELECT rowid, range_ik FROM " . $this->db->prefix() . "c_exp_tax_range";
10609 $sql .= " WHERE entity = " . $conf->entity . " AND active = 1";
10610
10611 $resql = $this->db->query($sql);
10612 if ($resql) {
10613 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10614 if ($useempty) {
10615 $out .= '<option value="0"></option>';
10616 }
10617
10618 while ($obj = $this->db->fetch_object($resql)) {
10619 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . price($obj->range_ik, 0, $langs, 1, 0) . '</option>';
10620 }
10621 $out .= '</select>';
10622 } else {
10623 dol_print_error($this->db);
10624 }
10625
10626 return $out;
10627 }
10628
10639 public function selectExpense($selected = '', $htmlname = 'fk_c_type_fees', $useempty = 0, $allchoice = 1, $useid = 0)
10640 {
10641 global $langs;
10642
10643 $out = '';
10644 $sql = "SELECT id, code, label";
10645 $sql .= " FROM ".$this->db->prefix()."c_type_fees";
10646 $sql .= " WHERE active = 1";
10647
10648 $resql = $this->db->query($sql);
10649 if ($resql) {
10650 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10651 if ($useempty) {
10652 $out .= '<option value="0"></option>';
10653 }
10654 if ($allchoice) {
10655 $out .= '<option value="-1">' . $langs->trans('AllExpenseReport') . '</option>';
10656 }
10657
10658 $field = 'code';
10659 if ($useid) {
10660 $field = 'id';
10661 }
10662
10663 while ($obj = $this->db->fetch_object($resql)) {
10664 $key = $langs->trans($obj->code);
10665 $out .= '<option ' . ($selected == $obj->{$field} ? 'selected="selected"' : '') . ' value="' . $obj->{$field} . '">' . ($key != $obj->code ? $key : $obj->label) . '</option>';
10666 }
10667 $out .= '</select>';
10668
10669 $out .= ajax_combobox('select_'.$htmlname);
10670 } else {
10671 dol_print_error($this->db);
10672 }
10673
10674 return $out;
10675 }
10676
10695 public function selectInvoice($socid = -1, $selected = '', $htmlname = 'invoiceid', $maxlength = 24, $option_only = 0, $show_empty = '1', $discard_closed = 0, $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500', $projectsListId = '', $showproject = 'all', $usertofilter = null)
10696 {
10697 global $user, $conf, $langs;
10698
10699 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
10700
10701 if (is_null($usertofilter)) {
10702 $usertofilter = $user;
10703 }
10704
10705 $out = '';
10706
10707 $hideunselectables = false;
10708 if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
10709 $hideunselectables = true;
10710 }
10711
10712 if (empty($projectsListId)) {
10713 if (!$usertofilter->hasRight('projet', 'all', 'lire')) {
10714 $projectstatic = new Project($this->db);
10715 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertofilter, 0, 1);
10716 }
10717 }
10718
10719 // Search all projects
10720 $sql = "SELECT f.rowid, f.ref as fref, 'nolabel' as flabel, p.rowid as pid, f.ref,
10721 p.title, p.fk_soc, p.fk_statut, p.public,";
10722 $sql .= ' s.nom as name';
10723 $sql .= ' FROM ' . $this->db->prefix() . 'projet as p';
10724 $sql .= ' LEFT JOIN ' . $this->db->prefix() . 'societe as s ON s.rowid = p.fk_soc,';
10725 $sql .= ' ' . $this->db->prefix() . 'facture as f';
10726 $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
10727 $sql .= " AND f.fk_projet = p.rowid AND f.fk_statut=0"; //Brouillons seulement
10728 //if ($projectsListId) $sql.= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")";
10729 //if ($socid == 0) $sql.= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
10730 //if ($socid > 0) $sql.= " AND (p.fk_soc=".((int) $socid)." OR p.fk_soc IS NULL)";
10731 $sql .= " ORDER BY p.ref, f.ref ASC";
10732
10733 $resql = $this->db->query($sql);
10734 if ($resql) {
10735 // Use select2 selector
10736 if (!empty($conf->use_javascript_ajax)) {
10737 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10738 $comboenhancement = ajax_combobox($htmlname, array(), 0, $forcefocus);
10739 $out .= $comboenhancement;
10740 $morecss = 'minwidth200imp maxwidth500';
10741 }
10742
10743 if (empty($option_only)) {
10744 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10745 }
10746 if (!empty($show_empty)) {
10747 $out .= '<option value="0" class="optiongrey">';
10748 if (!is_numeric($show_empty)) {
10749 $out .= $show_empty;
10750 } else {
10751 $out .= '&nbsp;';
10752 }
10753 $out .= '</option>';
10754 }
10755 $num = $this->db->num_rows($resql);
10756 $i = 0;
10757 if ($num) {
10758 while ($i < $num) {
10759 $obj = $this->db->fetch_object($resql);
10760 // If we ask to filter on a company and user has no permission to see all companies and project is linked to another company, we hide project.
10761 if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$usertofilter->hasRight('societe', 'lire')) {
10762 // Do nothing
10763 } else {
10764 if ($discard_closed == 1 && $obj->fk_statut == Project::STATUS_CLOSED) {
10765 $i++;
10766 continue;
10767 }
10768
10769 $labeltoshow = '';
10770
10771 if ($showproject == 'all') {
10772 $labeltoshow .= dol_trunc($obj->ref, 18); // Invoice ref
10773 if ($obj->name) {
10774 $labeltoshow .= ' - ' . $obj->name; // Soc name
10775 }
10776
10777 $disabled = 0;
10778 if ($obj->fk_statut == Project::STATUS_DRAFT) {
10779 $disabled = 1;
10780 $labeltoshow .= ' - ' . $langs->trans("Draft");
10781 } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
10782 if ($discard_closed == 2) {
10783 $disabled = 1;
10784 }
10785 $labeltoshow .= ' - ' . $langs->trans("Closed");
10786 } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
10787 $disabled = 1;
10788 $labeltoshow .= ' - ' . $langs->trans("LinkedToAnotherCompany");
10789 }
10790 }
10791
10792 if (!empty($selected) && $selected == $obj->rowid) {
10793 $out .= '<option value="' . $obj->rowid . '" selected';
10794 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10795 $out .= '>' . $labeltoshow . '</option>';
10796 } else {
10797 if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
10798 $resultat = '';
10799 } else {
10800 $resultat = '<option value="' . $obj->rowid . '"';
10801 if ($disabled) {
10802 $resultat .= ' disabled';
10803 }
10804 //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
10805 //else $labeltoshow.=' ('.$langs->trans("Private").')';
10806 $resultat .= '>';
10807 $resultat .= $labeltoshow;
10808 $resultat .= '</option>';
10809 }
10810 $out .= $resultat;
10811 }
10812 }
10813 $i++;
10814 }
10815 }
10816 if (empty($option_only)) {
10817 $out .= '</select>';
10818 }
10819
10820 $this->db->free($resql);
10821
10822 return $out;
10823 } else {
10824 dol_print_error($this->db);
10825 return '';
10826 }
10827 }
10828
10842 public function selectInvoiceRec($selected = '', $htmlname = 'facrecid', $maxlength = 24, $option_only = 0, $show_empty = '1', $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500')
10843 {
10844 global $conf, $langs;
10845
10846 $out = '';
10847
10848 dol_syslog('FactureRec::fetch', LOG_DEBUG);
10849
10850 $sql = 'SELECT f.rowid, f.entity, f.titre as title, f.suspended, f.fk_soc';
10851 //$sql.= ', el.fk_source';
10852 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_rec as f';
10853 $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
10854 $sql .= " ORDER BY f.titre ASC";
10855
10856 $resql = $this->db->query($sql);
10857 if ($resql) {
10858 // Use select2 selector
10859 if (!empty($conf->use_javascript_ajax)) {
10860 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10861 $comboenhancement = ajax_combobox($htmlname, array(), 0, $forcefocus);
10862 $out .= $comboenhancement;
10863 $morecss = 'minwidth200imp maxwidth500';
10864 }
10865
10866 if (empty($option_only)) {
10867 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10868 }
10869 if (!empty($show_empty)) {
10870 $out .= '<option value="0" class="optiongrey">';
10871 if (!is_numeric($show_empty)) {
10872 $out .= $show_empty;
10873 } else {
10874 $out .= '&nbsp;';
10875 }
10876 $out .= '</option>';
10877 }
10878 $num = $this->db->num_rows($resql);
10879 if ($num) {
10880 while ($obj = $this->db->fetch_object($resql)) {
10881 $labeltoshow = dol_trunc($obj->title, 18); // Invoice ref
10882
10883 $disabled = 0;
10884 if (!empty($obj->suspended)) {
10885 $disabled = 1;
10886 $labeltoshow .= ' - ' . $langs->trans("Closed");
10887 }
10888
10889
10890 if (!empty($selected) && $selected == $obj->rowid) {
10891 $out .= '<option value="' . $obj->rowid . '" selected';
10892 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10893 $out .= '>' . $labeltoshow . '</option>';
10894 } else {
10895 if ($disabled && ($selected != $obj->rowid)) {
10896 $resultat = '';
10897 } else {
10898 $resultat = '<option value="' . $obj->rowid . '"';
10899 if ($disabled) {
10900 $resultat .= ' disabled';
10901 }
10902 $resultat .= '>';
10903 $resultat .= $labeltoshow;
10904 $resultat .= '</option>';
10905 }
10906 $out .= $resultat;
10907 }
10908 }
10909 }
10910 if (empty($option_only)) {
10911 $out .= '</select>';
10912 }
10913
10914 print $out;
10915
10916 $this->db->free($resql);
10917 return $num;
10918 } else {
10919 $this->errors[] = $this->db->lasterror;
10920 return -1;
10921 }
10922 }
10923
10933 public function searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput = array(), $search_component_params_hidden = '')
10934 {
10935 global $langs;
10936
10937 if ($search_component_params_hidden != '' && !preg_match('/^\‍(.*\‍)$/', $search_component_params_hidden)) { // If $search_component_params_hidden does not start and end with ()
10938 $search_component_params_hidden = '(' . $search_component_params_hidden . ')';
10939 }
10940
10941 $ret = '';
10942
10943 $ret .= '<div class="divadvancedsearchfieldcomp centpercent inline-block">';
10944 $ret .= '<a href="#" class="dropdownsearch-toggle unsetcolor">';
10945 $ret .= '<span class="fas fa-filter linkobject boxfilter paddingright pictofixedwidth" title="' . dol_escape_htmltag($langs->trans("Filters")) . '" id="idsubimgproductdistribution"></span>';
10946 $ret .= '</a>';
10947
10948 $ret .= '<div class="divadvancedsearchfieldcompinput inline-block minwidth500 maxwidth300onsmartphone">';
10949
10950 // Show select fields as tags.
10951 $ret .= '<div id="divsearch_component_params" name="divsearch_component_params" class="noborderbottom search_component_params inline-block valignmiddle">';
10952
10953 if ($search_component_params_hidden) {
10954 // Split the criteria on each AND
10955 //var_dump($search_component_params_hidden);
10956
10957 $arrayofandtags = dolForgeExplodeAnd($search_component_params_hidden);
10958
10959 // $arrayofandtags is now array( '...' , '...', ...)
10960 // Show each AND part
10961 foreach ($arrayofandtags as $tmpkey => $tmpval) {
10962 $errormessage = '';
10963 $searchtags = forgeSQLFromUniversalSearchCriteria($tmpval, $errormessage, 1, 1);
10964 if ($errormessage) {
10965 $this->error = 'ERROR in parsing search string: '.$errormessage;
10966 }
10967 // Remove first and last parenthesis but only if first is the opening and last the closing of the same group
10968 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
10969 $searchtags = removeGlobalParenthesis($searchtags);
10970
10971 $ret .= '<span class="marginleftonlyshort valignmiddle tagsearch" data-ufilterid="'.($tmpkey + 1).'" data-ufilter="'.dol_escape_htmltag($tmpval).'">';
10972 $ret .= '<span class="tagsearchdelete select2-selection__choice__remove" data-ufilterid="'.($tmpkey + 1).'">x</span> ';
10973 $ret .= dol_escape_htmltag($searchtags);
10974 $ret .= '</span>';
10975 }
10976 }
10977
10978 //$ret .= '<button type="submit" class="liste_titre button_search paddingleftonly" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
10979
10980 //$ret .= search_component_params
10981 //$texttoshow = '<div class="opacitymedium inline-block search_component_searchtext">'.$langs->trans("Search").'</div>';
10982 //$ret .= '<div class="search_component inline-block valignmiddle">'.$texttoshow.'</div>';
10983
10984 $show_search_component_params_hidden = 1;
10985 if ($show_search_component_params_hidden) {
10986 $ret .= '<input type="hidden" name="show_search_component_params_hidden" value="1">';
10987 }
10988 $ret .= "<!-- We store the full Universal Search String into this field. For example: (t.ref:like:'SO-%') AND ((t.ref:like:'CO-%') OR (t.ref:like:'AA%')) -->";
10989 $ret .= '<input type="hidden" id="search_component_params_hidden" name="search_component_params_hidden" value="' . dol_escape_htmltag($search_component_params_hidden) . '">';
10990 // $ret .= "<!-- sql= ".forgeSQLFromUniversalSearchCriteria($search_component_params_hidden, $errormessage)." -->";
10991
10992 // For compatibility with forms that show themself the search criteria in addition of this component, we output these fields
10993 foreach ($arrayofcriterias as $criteria) {
10994 foreach ($criteria as $criteriafamilykey => $criteriafamilyval) {
10995 if (in_array('search_' . $criteriafamilykey, $arrayofinputfieldsalreadyoutput)) {
10996 continue;
10997 }
10998 if (in_array($criteriafamilykey, array('rowid', 'ref_ext', 'entity', 'extraparams'))) {
10999 continue;
11000 }
11001 if (in_array($criteriafamilyval['type'], array('date', 'datetime', 'timestamp'))) {
11002 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_start">';
11003 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startyear">';
11004 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startmonth">';
11005 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startday">';
11006 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_end">';
11007 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endyear">';
11008 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endmonth">';
11009 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endday">';
11010 } else {
11011 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '">';
11012 }
11013 }
11014 }
11015
11016 $ret .= '</div>';
11017
11018 $ret .= "<!-- Field to enter a generic filter string: t.ref:like:'SO-%', t.date_creation:<:'20160101', t.date_creation:<:'2016-01-01 12:30:00', t.nature:is:NULL, t.field2:isnot:NULL -->\n";
11019 $ret .= '<input type="text" placeholder="' . $langs->trans("Filters") . '" id="search_component_params_input" name="search_component_params_input" class="noborderbottom search_component_input" value="">';
11020
11021 $ret .= '</div>';
11022 $ret .= '</div>';
11023
11024 $ret .= '<script>
11025 jQuery(".tagsearchdelete").click(function(e) {
11026 var filterid = $(this).parents().attr("data-ufilterid");
11027 console.log("We click to delete the criteria nb "+filterid);
11028
11029 // Regenerate the search_component_params_hidden with all data-ufilter except the one to delete, and post the page
11030 var newparamstring = \'\';
11031 $(\'.tagsearch\').each(function(index, element) {
11032 tmpfilterid = $(this).attr("data-ufilterid");
11033 if (tmpfilterid != filterid) {
11034 // We keep this criteria
11035 if (newparamstring == \'\') {
11036 newparamstring = $(this).attr("data-ufilter");
11037 } else {
11038 newparamstring = newparamstring + \' AND \' + $(this).attr("data-ufilter");
11039 }
11040 }
11041 });
11042 console.log("newparamstring = "+newparamstring);
11043
11044 jQuery("#search_component_params_hidden").val(newparamstring);
11045
11046 // We repost the form
11047 $(this).closest(\'form\').submit();
11048 });
11049
11050 jQuery("#search_component_params_input").keydown(function(e) {
11051 console.log("We press a key on the filter field that is "+jQuery("#search_component_params_input").val());
11052 console.log(e.which);
11053 if (jQuery("#search_component_params_input").val() == "" && e.which == 8) {
11054 /* We click on back when the input field is already empty */
11055 event.preventDefault();
11056 jQuery("#divsearch_component_params .tagsearch").last().remove();
11057 /* Regenerate content of search_component_params_hidden from remaining .tagsearch */
11058 var s = "";
11059 jQuery("#divsearch_component_params .tagsearch").each(function( index ) {
11060 if (s != "") {
11061 s = s + " AND ";
11062 }
11063 s = s + $(this).attr("data-ufilter");
11064 });
11065 console.log("New value for search_component_params_hidden = "+s);
11066 jQuery("#search_component_params_hidden").val(s);
11067 }
11068 });
11069
11070 </script>
11071 ';
11072
11073 return $ret;
11074 }
11075
11085 public function selectModelMail($prefix, $modelType = '', $default = 0, $addjscombo = 0)
11086 {
11087 global $langs, $user;
11088
11089 $retstring = '';
11090
11091 $TModels = array();
11092
11093 include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
11094 $formmail = new FormMail($this->db);
11095 $result = $formmail->fetchAllEMailTemplate($modelType, $user, $langs);
11096
11097 if ($default) {
11098 $TModels[0] = $langs->trans('DefaultMailModel');
11099 }
11100 if ($result > 0) {
11101 foreach ($formmail->lines_model as $model) {
11102 $TModels[$model->id] = $model->label;
11103 }
11104 }
11105
11106 $retstring .= '<select class="flat" id="select_' . $prefix . 'model_mail" name="' . $prefix . 'model_mail">';
11107
11108 foreach ($TModels as $id_model => $label_model) {
11109 $retstring .= '<option value="' . $id_model . '"';
11110 $retstring .= ">" . $label_model . "</option>";
11111 }
11112
11113 $retstring .= "</select>";
11114
11115 if ($addjscombo) {
11116 $retstring .= ajax_combobox('select_' . $prefix . 'model_mail');
11117 }
11118
11119 return $retstring;
11120 }
11121
11133 public function buttonsSaveCancel($save_label = 'Save', $cancel_label = 'Cancel', $morebuttons = array(), $withoutdiv = false, $morecss = '', $dol_openinpopup = '')
11134 {
11135 global $langs;
11136
11137 $buttons = array();
11138
11139 $save = array(
11140 'name' => 'save',
11141 'label_key' => $save_label,
11142 );
11143
11144 if ($save_label == 'Create' || $save_label == 'Add') {
11145 $save['name'] = 'add';
11146 } elseif ($save_label == 'Modify') {
11147 $save['name'] = 'edit';
11148 }
11149
11150 $cancel = array(
11151 'name' => 'cancel',
11152 'label_key' => 'Cancel',
11153 );
11154
11155 !empty($save_label) ? $buttons[] = $save : '';
11156
11157 if (!empty($morebuttons)) {
11158 $buttons[] = $morebuttons;
11159 }
11160
11161 !empty($cancel_label) ? $buttons[] = $cancel : '';
11162
11163 $retstring = $withoutdiv ? '' : '<div class="center">';
11164
11165 foreach ($buttons as $button) {
11166 $addclass = empty($button['addclass']) ? '' : $button['addclass'];
11167 $retstring .= '<input type="submit" class="button button-' . $button['name'] . ($morecss ? ' ' . $morecss : '') . ' ' . $addclass . '" name="' . $button['name'] . '" value="' . dol_escape_htmltag($langs->trans($button['label_key'])) . '">';
11168 }
11169 $retstring .= $withoutdiv ? '' : '</div>';
11170
11171 if ($dol_openinpopup) {
11172 $retstring .= '<!-- buttons are shown into a $dol_openinpopup=' . dol_escape_htmltag($dol_openinpopup) . ' context, so we enable the close of dialog on cancel -->' . "\n";
11173 $retstring .= '<script nonce="' . getNonce() . '">';
11174 $retstring .= 'jQuery(".button-cancel").click(function(e) {
11175 e.preventDefault(); console.log(\'We click on cancel in iframe popup ' . dol_escape_js($dol_openinpopup) . '\');
11176 window.parent.jQuery(\'#idfordialog' . dol_escape_js($dol_openinpopup) . '\').dialog(\'close\');
11177 });';
11178 $retstring .= '</script>';
11179 }
11180
11181 return $retstring;
11182 }
11183
11184
11185 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
11186
11193 {
11194 // phpcs:enable
11195 global $langs;
11196
11197 $num = count($this->cache_invoice_subtype);
11198 if ($num > 0) {
11199 return 0; // Cache already loaded
11200 }
11201
11202 dol_syslog(__METHOD__, LOG_DEBUG);
11203
11204 $sql = "SELECT rowid, code, label as label";
11205 $sql .= " FROM " . MAIN_DB_PREFIX . 'c_invoice_subtype';
11206 $sql .= " WHERE active = 1";
11207
11208 $resql = $this->db->query($sql);
11209 if ($resql) {
11210 $num = $this->db->num_rows($resql);
11211 $i = 0;
11212 while ($i < $num) {
11213 $obj = $this->db->fetch_object($resql);
11214
11215 // If translation exists, we use it, otherwise we take the default wording
11216 $label = ($langs->trans("InvoiceSubtype" . $obj->rowid) != "InvoiceSubtype" . $obj->rowid) ? $langs->trans("InvoiceSubtype" . $obj->rowid) : (($obj->label != '-') ? $obj->label : '');
11217 $this->cache_invoice_subtype[$obj->rowid]['rowid'] = $obj->rowid;
11218 $this->cache_invoice_subtype[$obj->rowid]['code'] = $obj->code;
11219 $this->cache_invoice_subtype[$obj->rowid]['label'] = $label;
11220 $i++;
11221 }
11222
11223 $this->cache_invoice_subtype = dol_sort_array($this->cache_invoice_subtype, 'code', 'asc', 0, 0, 1);
11224
11225 return $num;
11226 } else {
11227 dol_print_error($this->db);
11228 return -1;
11229 }
11230 }
11231
11232
11243 public function getSelectInvoiceSubtype($selected = 0, $htmlname = 'subtypeid', $addempty = 0, $noinfoadmin = 0, $morecss = '')
11244 {
11245 global $langs, $user;
11246
11247 $out = '';
11248 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
11249
11251
11252 $out .= '<select id="' . $htmlname . '" class="flat selectsubtype' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
11253 if ($addempty) {
11254 $out .= '<option value="0">&nbsp;</option>';
11255 }
11256
11257 foreach ($this->cache_invoice_subtype as $rowid => $subtype) {
11258 $label = $subtype['label'];
11259 $out .= '<option value="' . $subtype['rowid'] . '"';
11260 if ($selected == $subtype['rowid']) {
11261 $out .= ' selected="selected"';
11262 }
11263 $out .= '>';
11264 $out .= $label;
11265 $out .= '</option>';
11266 }
11267
11268 $out .= '</select>';
11269 if ($user->admin && empty($noinfoadmin)) {
11270 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
11271 }
11272 $out .= ajax_combobox($htmlname);
11273
11274 return $out;
11275 }
11276}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition security.php:637
ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLength=2, $autoselect=0, $ajaxoptions=array(), $moreparams='')
Generic function that return javascript to add to transform a common input text or select field into ...
Definition ajax.lib.php:48
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:456
ajax_multiautocompleter($htmlname, $fields, $url, $option='', $minLength=2, $autoselect=0)
Generic function that return javascript to add to a page to transform a common input text field into ...
Definition ajax.lib.php:305
ajax_event($htmlname, $events)
Add event management script.
Definition ajax.lib.php:559
$object ref
Definition info.php:79
Class to manage bank accounts.
Class to manage categories.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage contact/addresses.
Class to manage a WYSIWYG editor.
DAO Resource object.
const STATUS_OPEN_INTERNAL
Warehouse open and only operations for stock transfers/corrections allowed (not for customer shipping...
const STATUS_OPEN_ALL
Warehouse open and any operations are allowed (customer shipping, supplier dispatch,...
const STATUS_CLOSED
Warehouse closed, inactive.
Class to manage standard extra languages.
Class to manage invoices.
Class to manage generation of HTML components Only common components must be here.
selectModelMail($prefix, $modelType='', $default=0, $addjscombo=0)
selectModelMail
showFilterButtons($pos='')
Return HTML to show the search and clear search button.
selectyesno($htmlname, $value='', $option=0, $disabled=false, $useempty=0, $addjscombo=0, $morecss='', $labelyes='Yes', $labelno='No')
Return an html string with a select combo box to choose yes or no.
load_cache_vatrates($country_code)
Load into the cache ->cache_vatrates, all the vat rates of a country.
formInputReason($page, $selected='', $htmlname='demandreason', $addempty=0)
Output HTML form to select list of input reason (events that triggered an object creation,...
editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata='string', $editvalue='', $extObject=null, $custommsg=null, $moreparam='', $notabletag=1, $formatfunc='', $paramid='id', $gm='auto', $moreoptions=array(), $editaction='')
Output value of a field for an editable field.
form_availability($page, $selected='', $htmlname='availability', $addempty=0)
Show a form to select a delivery delay.
showLinkedObjectBlock($object, $morehtmlright='', $compatibleImportElementsList=array(), $title='RelatedObjects')
Show linked object block.
select_produits_fournisseurs($socid, $selected='', $htmlname='productid', $filtertype='', $filtre='', $ajaxoptions=array(), $hidelabel=0, $alsoproductwithnosupplierprice=0, $morecss='', $placeholder='')
Return list of products for customer (in Ajax if Ajax activated or go to select_produits_fournisseurs...
selectMassAction($selected, $arrayofaction, $alwaysvisible=0, $name='massaction', $cssclass='checkforselect')
Generate select HTML to choose massaction.
select_dolresources_forevent($action='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include=array(), $enableonly=array(), $force_entity='0', $maxlength=0, $showstatus=0, $morefilter='', $showproperties=0, $listofresourceid=array())
Return select list of resources.
formconfirm($page, $title, $question, $action, $formquestion='', $selectedchoice='', $useajax=0, $height=0, $width=500, $disableformtag=0, $labelbuttonyes='Yes', $labelbuttonno='No')
form_multicurrency_code($page, $selected='', $htmlname='multicurrency_code')
Show form with multicurrency code.
select_produits($selected=0, $htmlname='productid', $filtertype='', $limit=0, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(), $socid=0, $showempty='1', $forcecombo=0, $morecss='', $hidepriceinlabel=0, $warehouseStatus='', $selected_combinations=null, $nooutput=0, $status_purchase=-1)
Return list of products for customer.
showFilterAndCheckAddButtons($addcheckuncheckall=0, $cssclass='checkforaction', $calljsfunction=0, $massactionname="massaction")
Return HTML to show the search and clear search button.
select_company($selected='', $htmlname='socid', $filter='', $showempty='', $showtype=0, $forcecombo=0, $events=array(), $limit=0, $morecss='minwidth100', $moreparam='', $selected_input_value='', $hidelabel=1, $ajaxoptions=array(), $multiple=false, $excludeids=array(), $showcode=0)
Output html form to select a third party This call select_thirdparty_list() or ajax depending on setu...
textwithpicto($text, $htmltext, $direction=1, $type='help', $extracss='', $noencodehtmltext=0, $notabs=3, $tooltiptrigger='', $forcenowrap=0)
Show a text with a picto and a tooltip on picto.
select_dolgroups($selected=0, $htmlname='groupid', $show_empty=0, $exclude='', $disabled=0, $include='', $enableonly=array(), $force_entity='0', $multiple=false, $morecss='minwidth200')
Return select list of groups.
selectInputReason($selected='', $htmlname='demandreasonid', $exclude='', $addempty=0, $morecss='', $notooltip=0)
Return list of input reason (events that triggered an object creation, like after sending an emailing...
select_produits_list($selected=0, $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $filterkey='', $status=1, $finished=2, $outputmode=0, $socid=0, $showempty='1', $forcecombo=0, $morecss='maxwidth500', $hidepriceinlabel=0, $warehouseStatus='', $status_purchase=-1)
Return list of products for a customer.
select_dolusers_forevent($action='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include=array(), $enableonly=array(), $force_entity='0', $maxlength=0, $showstatus=0, $morefilter='', $showproperties=0, $listofuserid=array(), $listofcontactid=array(), $listofotherid=array())
Return select list of users.
select_contact($socid, $selected='', $htmlname='contactid', $showempty=0, $exclude='', $limitto='', $showfunction=0, $morecss='', $nokeyifsocid=true, $showsoc=0, $forcecombo=0, $events=array(), $moreparam='', $htmlid='', $selected_input_value='', $filter='')
Output html form to select a contact This call select_contacts() or ajax depending on setup.
select_incoterms($selected='', $location_incoterms='', $page='', $htmlname='incoterm_id', $htmloption='', $forcecombo=1, $events=array(), $disableautocomplete=0)
Return select list of incoterms.
selectDate($set_time='', $prefix='re', $h=0, $m=0, $empty=0, $form_name="", $d=1, $addnowlink=0, $disabled=0, $fullday='', $addplusone='', $adddateof='', $openinghours='', $stepminutes=1, $labeladddateof='', $placeholder='', $gm='auto')
Show a HTML widget to input a date or combo list for day, month, years and optionally hours and minut...
select_types_paiements($selected='', $htmlname='paiementtype', $filtertype='', $format=0, $empty=1, $noadmininfo=0, $maxlength=0, $active=1, $morecss='', $nooutput=0)
Return list of payment methods Constant MAIN_DEFAULT_PAYMENT_TYPE_ID can used to set default value bu...
select_currency($selected='', $htmlname='currency_id')
Retourne la liste des devises, dans la langue de l'utilisateur.
formSelectTransportMode($page, $selected='', $htmlname='transport_mode_id', $active=1, $addempty=0)
Show form with transport mode.
selectShippingMethod($selected='', $htmlname='shipping_method_id', $filtre='', $useempty=0, $moreattrib='', $noinfoadmin=0, $morecss='')
Return a HTML select list of shipping mode.
formSelectShippingMethod($page, $selected='', $htmlname='shipping_method_id', $addempty=0)
Display form to select shipping mode.
getSelectInvoiceSubtype($selected=0, $htmlname='subtypeid', $addempty=0, $noinfoadmin=0, $morecss='')
Return list of invoice subtypes.
form_contacts($page, $societe, $selected='', $htmlname='contactid')
Show forms to select a contact.
selectMultiCurrency($selected='', $htmlname='multicurrency_code', $useempty=0, $filter='', $excludeConfCurrency=false, $morecss='')
Return array of currencies in user language.
load_tva($htmlname='tauxtva', $selectedrate='', $societe_vendeuse=null, $societe_acheteuse=null, $idprod=0, $info_bits=0, $type='', $options_only=false, $mode=0, $type_vat=0)
Output an HTML select vat rate.
form_multicurrency_rate($page, $rate=0.0, $htmlname='multicurrency_tx', $currency='')
Show form with multicurrency rate.
load_cache_availability()
select_bom($selected='', $htmlname='bom_id', $limit=0, $status=1, $type=0, $showempty='1', $morecss='', $nooutput='', $forcecombo=0, $TProducts=[])
Return list of BOM for customer in Ajax if Ajax activated or go to select_produits_list.
selectcontacts($socid, $selected=array(), $htmlname='contactid', $showempty=0, $exclude='', $limitto='', $showfunction=0, $morecss='', $options_only=0, $showsoc=0, $forcecombo=0, $events=array(), $moreparam='', $htmlid='', $multiple=false, $disableifempty=0, $filter='')
Return HTML code of the SELECT of list of all contacts (for a third party or all).
static selectarray($htmlname, $array, $id='', $show_empty=0, $key_in_label=0, $value_as_key=0, $moreparam='', $translate=0, $maxlen=0, $disabled=0, $sort='', $morecss='minwidth75', $addjscombo=1, $moreparamonempty='', $disablebademail=0, $nohtmlescape=0)
Return a HTML select string, built from an array of key+value.
selectMembersList($selected='', $htmlname='adherentid', $filtertype='', $limit=20, $filterkey='', $status=1, $outputmode=0, $showempty='1', $forcecombo=0, $morecss='')
Return list of adherents.
select_type_fees($selected='', $htmlname='type', $showempty=0)
Return list of types of notes.
selectInvoiceRec($selected='', $htmlname='facrecid', $maxlength=24, $option_only=0, $show_empty='1', $forcefocus=0, $disabled=0, $morecss='maxwidth500')
Output a combo list with invoices qualified for a third party.
editInPlace($object, $value, $htmlname, $condition, $inputType='textarea', $editvalue=null, $extObject=null, $custommsg=null)
Output edit in place form.
selectUnits($selected='', $htmlname='units', $showempty=0, $unit_type='')
Creates HTML units selector (code => label)
select_produits_fournisseurs_list($socid, $selected='', $htmlname='productid', $filtertype='', $filtre='', $filterkey='', $statut=-1, $outputmode=0, $limit=100, $alsoproductwithnosupplierprice=0, $morecss='', $showstockinlist=0, $placeholder='')
Return list of suppliers products.
selectTicketsList($selected='', $htmlname='ticketid', $filtertype='', $limit=20, $filterkey='', $status=1, $outputmode=0, $showempty='1', $forcecombo=0, $morecss='')
Return list of tickets.
form_modes_reglement($page, $selected='', $htmlname='mode_reglement_id', $filtertype='', $active=1, $addempty=0, $type='', $nooutput=0)
Show form with payment mode.
constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel=0, $filterkey='', $novirtualstock=0)
Function to forge the string with OPTIONs of SELECT.
showLinkToObjectBlock($object, $restrictlinksto=array(), $excludelinksto=array())
Show block with links to link to other objects.
form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter='', $maxvalue=0, $more='', $hidelist=0, $discount_type=0)
Show a select box with available absolute discounts.
buttonsSaveCancel($save_label='Save', $cancel_label='Cancel', $morebuttons=array(), $withoutdiv=false, $morecss='', $dol_openinpopup='')
Output the buttons to submit a creation/edit form.
selectTransportMode($selected='', $htmlname='transportmode', $format=0, $empty=1, $noadmininfo=0, $maxlength=0, $active=1, $morecss='')
static showphoto($modulepart, $object, $width=100, $height=0, $caneditfield=0, $cssclass='photowithmargin', $imagesize='', $addlinktofullsize=1, $cache=0, $forcecapture='', $noexternsourceoverwrite=0)
Return HTML code to output a photo.
selectProjectsList($selected='', $htmlname='projectid', $filtertype='', $limit=20, $filterkey='', $status=1, $outputmode=0, $showempty='1', $forcecombo=0, $morecss='')
Return list of projects.
form_conditions_reglement($page, $selected='', $htmlname='cond_reglement_id', $addempty=0, $type='', $filtertype=-1, $deposit_percent=-1, $nooutput=0)
Show a form to select payment conditions.
selectSituationInvoices($selected='', $socid=0)
Creates HTML last in cycle situation invoices selector.
loadCacheInputReason()
Load into cache cache_demand_reason, array of input reasons.
selectPriceBaseType($selected='', $htmlname='price_base_type', $addjscombo=0)
Selection HT or TTC.
load_cache_transport_mode()
select_conditions_paiements($selected=0, $htmlname='condid', $filtertype=-1, $addempty=0, $noinfoadmin=0, $morecss='', $deposit_percent=-1, $noprint=0)
print list of payment modes.
select_remises($selected, $htmlname, $filter, $socid, $maxvalue=0)
Return HTML combo list of absolute discounts.
showbarcode(&$object, $width=100, $morecss='')
Return HTML code to output a barcode.
form_confirm($page, $title, $question, $action, $formquestion=array(), $selectedchoice="", $useajax=0, $height=170, $width=500)
load_cache_conditions_paiements()
form_project($page, $socid, $selected='', $htmlname='projectid', $discard_closed=0, $maxlength=20, $forcefocus=0, $nooutput=0, $textifnoproject='', $morecss='')
Show a form to select a project.
selectExpenseCategories($selected='', $htmlname='fk_c_exp_tax_cat', $useempty=0, $excludeid=array(), $target='', $default_selected=0, $params=array(), $info_admin=1)
Return HTML to show the select of expense categories.
select_product_fourn_price($productid, $htmlname='productfournpriceid', $selected_supplier=0)
Return list of suppliers prices for a product.
select_country($selected='', $htmlname='country_id', $htmloption='', $maxlength=0, $morecss='minwidth300', $usecodeaskey='', $showempty=1, $disablefavorites=0, $addspecialentries=0, $exclude_country_code=array(), $hideflags=0)
Return combo list of activated countries, into language of user.
select_type_of_lines($selected='', $htmlname='type', $showempty=0, $hidetext=0, $forceall=0, $morecss="")
Return list of types of lines (product or service) Example: 0=product, 1=service, 9=other (for extern...
form_date($page, $selected, $htmlname, $displayhour=0, $displaymin=0, $nooutput=0, $type='')
Show a form + html select a date.
showCheckAddButtons($cssclass='checkforaction', $calljsfunction=0, $massactionname="massaction")
Return HTML to show the search and clear search button.
__construct($db)
Constructor.
select_thirdparty_list($selected='', $htmlname='socid', $filter='', $showempty='', $showtype=0, $forcecombo=0, $events=array(), $filterkey='', $outputmode=0, $limit=0, $morecss='minwidth100', $moreparam='', $multiple=false, $excludeids=array(), $showcode=0)
Output html form to select a third party.
select_users($selected='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly=array(), $force_entity='0')
Return the HTML select list of users.
select_all_categories($type, $selected='', $htmlname="parent", $maxlength=64, $fromid=0, $outputmode=0, $include=0, $morecss='', $useempty=1)
Return list of categories having chosen type.
static selectArrayFilter($htmlname, $array, $id='', $moreparam='', $disableFiltering=0, $disabled=0, $minimumInputLength=1, $morecss='', $callurlonselect=0, $placeholder='', $acceptdelayedhtml=0, $textfortitle='')
Return a HTML select string, built from an array of key+value, but content returned into select is de...
select_date($set_time='', $prefix='re', $h=0, $m=0, $empty=0, $form_name="", $d=1, $addnowlink=0, $nooutput=0, $disabled=0, $fullday=0, $addplusone='', $adddateof='')
Show a HTML widget to input a date or combo list for day, month, years and optionally hours and minut...
load_cache_invoice_subtype()
Load into cache list of invoice subtypes.
select_export_model($selected='', $htmlname='exportmodelid', $type='', $useempty=0)
Return list of export templates.
selectDateToDate($set_time='', $set_time_end='', $prefix='re', $empty=0, $forcenewline=0)
Show 2 HTML widget to input a date or combo list for day, month, years and optionally hours and minut...
textwithtooltip($text, $htmltext, $tooltipon=1, $direction=0, $img='', $extracss='', $notabs=3, $incbefore='', $noencodehtmltext=0, $tooltiptrigger='', $forcenowrap=0)
Show a text and picto with tooltip on text or picto.
searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput=array(), $search_component_params_hidden='')
Output the component to make advanced search criteries.
select_dolusers($selected='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly='', $force_entity='', $maxlength=0, $showstatus=0, $morefilter='', $show_every=0, $enableonlytext='', $morecss='', $notdisabled=0, $outputmode=0, $multiple=false, $forcecombo=0)
Return select list of users.
getSelectConditionsPaiements($selected=0, $htmlname='condid', $filtertype=-1, $addempty=0, $noinfoadmin=0, $morecss='', $deposit_percent=-1)
Return list of payment modes.
widgetForTranslation($fieldname, $object, $perm, $typeofdata='string', $check='', $morecss='')
Output edit in place form.
load_cache_types_fees()
Load into cache cache_types_fees, array of types of fees.
static multiselectarray($htmlname, $array, $selected=array(), $key_in_label=0, $value_as_key=0, $morecss='', $translate=0, $width=0, $moreattrib='', $elemtype='', $placeholder='', $addjscombo=-1)
Show a multiselect form from an array.
form_thirdparty($page, $selected='', $htmlname='socid', $filter='', $showempty=0, $showtype=0, $forcecombo=0, $events=array(), $nooutput=0, $excludeids=array(), $textifnothirdparty='')
Output html select to select thirdparty.
selectEstablishments($selected='', $htmlname='entity', $status=0, $filtre='', $useempty=0, $moreattrib='')
Return a HTML select list of establishment.
formSelectAccount($page, $selected='', $htmlname='fk_account', $addempty=0)
Display form to select bank account.
form_users($page, $selected='', $htmlname='userid', $exclude=array(), $include=array())
Show a select form to choose a user.
editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata='string', $moreparam='', $fieldrequired=0, $notabletag=0, $paramid='id', $help='')
Output key field for an editable field.
showCategories($id, $type, $rendermode=0, $nolink=0)
Render list of categories linked to object with id $id and type $type.
load_cache_types_paiements()
selectAvailabilityDelay($selected='', $htmlname='availid', $filtertype='', $addempty=0, $morecss='')
Return the list of type of delay available.
selectCurrency($selected='', $htmlname='currency_id', $mode=0, $useempty='')
Retourne la liste des devises, dans la langue de l'utilisateur.
select_comptes($selected='', $htmlname='accountid', $status=0, $filtre='', $useempty=0, $moreattrib='', $showcurrency=0, $morecss='', $nooutput=0)
Return a HTML select list of bank accounts.
showrefnav($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $morehtmlright='')
Return a HTML area with the reference of object and a navigation bar for a business object Note: To c...
Class permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new Form...
Class to manage building of HTML components.
Class to manage forms for the module resource.
Class to manage hooks.
Class for MyObject.
Class to parse product price expressions.
Class to manage predefined suppliers products.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
currency_name($code_iso, $withcode=0, $outputlangs=null)
Return label of currency or code+label.
isInEEC($object)
Return if a country of an object is inside the EEC (European Economic Community)
getServerTimeZoneInt($refgmtdate='now')
Return server timezone int.
Definition date.lib.php:86
removeGlobalParenthesis($string)
Remove first and last parenthesis but only if first is the opening and last the closing of the same g...
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dolForgeExplodeAnd($sqlfilters)
Explode an universal search string with AND parts.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
dol_print_phone($phone, $countrycode='', $cid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0, $morecss='')
Format phone numbers according to country.
picto_from_langcode($codelang, $moreatt='', $notitlealt=0)
Return img flag of country for a language code or country code.
img_help($usehelpcursor=1, $usealttitle=1)
Show help logo with cursor "?".
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
currentToken()
Return the value of token currently saved into session with name 'token'.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
dol_print_url($url, $target='_blank', $max=32, $withpicto=0, $morecss='')
Show Url link.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
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.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_print_email($email, $cid=0, $socid=0, $addlink=0, $max=64, $showinvalid=1, $withpicto=0)
Show EMail link formatted for HTML output.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles=1, $removeclassattribute=1, $cleanalsojavascript=0, $allowiframe=0, $allowed_tags=array(), $allowlink=0)
Clean a string to keep only desirable HTML tags.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
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...
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
dol_string_neverthesehtmltags($stringtoclean, $disallowed_tags=array('textarea'), $cleanalsosomestyles=0)
Clean a string from some undesirable HTML tags.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that returns whether VAT must be recoverable collected VAT (e.g.: VAT NPR in France)
dol_htmlentities($string, $flags=ENT_QUOTES|ENT_SUBSTITUTE, $encoding='UTF-8', $double_encode=false)
Replace htmlentities functions.
getImageFileNameForSize($file, $extName, $extImgTarget='')
Return the filename of file to get the thumbs.
getAdvancedPreviewUrl($modulepart, $relativepath, $alldata=0, $param='')
Return URL we can use for advanced preview links.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dolIsAllowedForPreview($file)
Return if a file is qualified for preview.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getNonce()
Return a random string to be used as a nonce value for js.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox=0, $check='restricthtml')
Sanitize a HTML to remove js, dangerous content and external link.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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...
a disabled
ui state ui widget content ui state ui widget header ui state a ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
testSqlAndScriptInject($val, $type)
Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET,...
Definition main.inc.php:123
measuringUnitString($unit, $measuring_style='', $scale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:137
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140
getMaxFileSizeArray()
Return the max allowed for file upload.
dol_hash($chain, $type='0', $nosalt=0)
Returns a hash (non reversible encryption) of a string.