dolibarr 19.0.4
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-2021 Frédéric France <frederic.france@netlogic.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 *
27 * This program is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License as published by
29 * the Free Software Foundation; either version 3 of the License, or
30 * (at your option) any later version.
31 *
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with this program. If not, see <https://www.gnu.org/licenses/>.
39 */
40
54class Form
55{
59 public $db;
60
64 public $error = '';
65
69 public $errors = array();
70
71 // Some properties used to return data by some methods
72 public $result;
73 public $num;
74
75 // Cache arrays
76 public $cache_types_paiements = array();
77 public $cache_conditions_paiements = array();
78 public $cache_transport_mode = array();
79 public $cache_availability = array();
80 public $cache_demand_reason = array();
81 public $cache_types_fees = array();
82 public $cache_vatrates = array();
83 public $cache_invoice_subtype = array();
84
85
91 public function __construct($db)
92 {
93 $this->db = $db;
94 }
95
112 public function editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata = 'string', $moreparam = '', $fieldrequired = 0, $notabletag = 0, $paramid = 'id', $help = '')
113 {
114 global $conf, $langs;
115
116 $ret = '';
117
118 // TODO change for compatibility
119 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;/', $typeofdata)) {
120 if (!empty($perm)) {
121 $tmp = explode(':', $typeofdata);
122 $ret .= '<div class="editkey_' . $tmp[0] . (!empty($tmp[1]) ? ' ' . $tmp[1] : '') . '" id="' . $htmlname . '">';
123 if ($fieldrequired) {
124 $ret .= '<span class="fieldrequired">';
125 }
126 if ($help) {
127 $ret .= $this->textwithpicto($langs->trans($text), $help);
128 } else {
129 $ret .= $langs->trans($text);
130 }
131 if ($fieldrequired) {
132 $ret .= '</span>';
133 }
134 $ret .= '</div>' . "\n";
135 } else {
136 if ($fieldrequired) {
137 $ret .= '<span class="fieldrequired">';
138 }
139 if ($help) {
140 $ret .= $this->textwithpicto($langs->trans($text), $help);
141 } else {
142 $ret .= $langs->trans($text);
143 }
144 if ($fieldrequired) {
145 $ret .= '</span>';
146 }
147 }
148 } else {
149 if (empty($notabletag) && $perm) {
150 $ret .= '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
151 }
152 if ($fieldrequired) {
153 $ret .= '<span class="fieldrequired">';
154 }
155 if ($help) {
156 $ret .= $this->textwithpicto($langs->trans($text), $help);
157 } else {
158 $ret .= $langs->trans($text);
159 }
160 if ($fieldrequired) {
161 $ret .= '</span>';
162 }
163 if (!empty($notabletag)) {
164 $ret .= ' ';
165 }
166 if (empty($notabletag) && $perm) {
167 $ret .= '</td>';
168 }
169 if (empty($notabletag) && $perm) {
170 $ret .= '<td class="right">';
171 }
172 if ($htmlname && GETPOST('action', 'aZ09') != 'edit' . $htmlname && $perm) {
173 $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>';
174 }
175 if (!empty($notabletag) && $notabletag == 1) {
176 if ($text) {
177 $ret .= ' : ';
178 } else {
179 $ret .= ' ';
180 }
181 }
182 if (!empty($notabletag) && $notabletag == 3) {
183 $ret .= ' ';
184 }
185 if (empty($notabletag) && $perm) {
186 $ret .= '</td>';
187 }
188 if (empty($notabletag) && $perm) {
189 $ret .= '</tr></table>';
190 }
191 }
192
193 return $ret;
194 }
195
219 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 = '')
220 {
221 global $conf, $langs;
222
223 $ret = '';
224
225 // Check parameters
226 if (empty($typeofdata)) {
227 return 'ErrorBadParameter typeofdata is empty';
228 }
229 // Clean paramater $typeofdata
230 if ($typeofdata == 'datetime') {
231 $typeofdata = 'dayhour';
232 }
233 $reg = array();
234 if (preg_match('/^(\w+)\‍((\d+)\‍)$/', $typeofdata, $reg)) {
235 if ($reg[1] == 'varchar') {
236 $typeofdata = 'string';
237 } elseif ($reg[1] == 'int') {
238 $typeofdata = 'numeric';
239 } else {
240 return 'ErrorBadParameter ' . $typeofdata;
241 }
242 }
243
244 // When option to edit inline is activated
245 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;|day|datepicker|dayhour|datehourpicker/', $typeofdata)) { // TODO add jquery timepicker and support select
246 $ret .= $this->editInPlace($object, $value, $htmlname, $perm, $typeofdata, $editvalue, $extObject, $custommsg);
247 } else {
248 if ($editaction == '') {
249 $editaction = GETPOST('action', 'aZ09');
250 }
251 $editmode = ($editaction == 'edit' . $htmlname);
252 if ($editmode) { // edit mode
253 $ret .= "\n";
254 $ret .= '<form method="post" action="' . $_SERVER["PHP_SELF"] . ($moreparam ? '?' . $moreparam : '') . '">';
255 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
256 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
257 $ret .= '<input type="hidden" name="' . $paramid . '" value="' . $object->id . '">';
258 if (empty($notabletag)) {
259 $ret .= '<table class="nobordernopadding centpercent">';
260 }
261 if (empty($notabletag)) {
262 $ret .= '<tr><td>';
263 }
264 if (preg_match('/^(string|safehtmlstring|email|phone|url)/', $typeofdata)) {
265 $tmp = explode(':', $typeofdata);
266 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($editvalue ? $editvalue : $value) . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
267 } elseif (preg_match('/^(integer)/', $typeofdata)) {
268 $tmp = explode(':', $typeofdata);
269 $valuetoshow = price2num($editvalue ? $editvalue : $value, 0);
270 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . $valuetoshow . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
271 } elseif (preg_match('/^(numeric|amount)/', $typeofdata)) {
272 $tmp = explode(':', $typeofdata);
273 $valuetoshow = price2num($editvalue ? $editvalue : $value);
274 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($valuetoshow != '' ? price($valuetoshow) : '') . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
275 } elseif (preg_match('/^(checkbox)/', $typeofdata)) {
276 $tmp = explode(':', $typeofdata);
277 $ret .= '<input type="checkbox" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($value ? $value : 'on') . '"' . ($value ? ' checked' : '') . (empty($tmp[1]) ? '' : $tmp[1]) . '/>';
278 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) { // if wysiwyg is enabled $typeofdata = 'ckeditor'
279 $tmp = explode(':', $typeofdata);
280 $cols = (empty($tmp[2]) ? '' : $tmp[2]);
281 $morealt = '';
282 if (preg_match('/%/', $cols)) {
283 $morealt = ' style="width: ' . $cols . '"';
284 $cols = '';
285 }
286 $valuetoshow = ($editvalue ? $editvalue : $value);
287 $ret .= '<textarea id="' . $htmlname . '" name="' . $htmlname . '" wrap="soft" rows="' . (empty($tmp[1]) ? '20' : $tmp[1]) . '"' . ($cols ? ' cols="' . $cols . '"' : 'class="quatrevingtpercent"') . $morealt . '" autofocus>';
288 // textarea convert automatically entities chars into simple chars.
289 // 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 wysiwig is off.
290 $valuetoshow = str_replace('&', '&amp;', $valuetoshow);
291 $ret .= dol_htmlwithnojs(dol_string_neverthesehtmltags($valuetoshow, array('textarea')));
292 $ret .= '</textarea>';
293 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
294 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
295 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
296 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
297 $ret .= $this->selectDate($value, $htmlname, 0, 0, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
298 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
299 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
300 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
301 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
302 $ret .= $this->selectDate($value, $htmlname, 1, 1, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
303 } elseif (preg_match('/^select;/', $typeofdata)) {
304 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
305 $arraylist = array();
306 foreach ($arraydata as $val) {
307 $tmp = explode(':', $val);
308 $tmpkey = str_replace('|', ':', $tmp[0]);
309 $arraylist[$tmpkey] = $tmp[1];
310 }
311 $ret .= $this->selectarray($htmlname, $arraylist, $value);
312 } elseif (preg_match('/^link/', $typeofdata)) {
313 // TODO Not yet implemented. See code for extrafields
314 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
315 $tmp = explode(':', $typeofdata); // Example: ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols:uselocalbrowser
316 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
317 $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]));
318 $ret .= $doleditor->Create(1);
319 } elseif ($typeofdata == 'asis') {
320 $ret .= ($editvalue ? $editvalue : $value);
321 }
322 if (empty($notabletag)) {
323 $ret .= '</td>';
324 }
325
326 // Button save-cancel
327 if (empty($notabletag)) {
328 $ret .= '<td>';
329 }
330 //else $ret.='<div class="clearboth"></div>';
331 $ret .= '<input type="submit" class="smallpaddingimp button' . (empty($notabletag) ? '' : ' ') . '" name="modify" value="' . $langs->trans("Modify") . '">';
332 if (preg_match('/ckeditor|textarea/', $typeofdata) && empty($notabletag)) {
333 $ret .= '<br>' . "\n";
334 }
335 $ret .= '<input type="submit" class="smallpaddingimp button button-cancel' . (empty($notabletag) ? '' : ' ') . '" name="cancel" value="' . $langs->trans("Cancel") . '">';
336 if (empty($notabletag)) {
337 $ret .= '</td>';
338 }
339
340 if (empty($notabletag)) {
341 $ret .= '</tr></table>' . "\n";
342 }
343 $ret .= '</form>' . "\n";
344 } else { // view mode
345 if (preg_match('/^email/', $typeofdata)) {
346 $ret .= dol_print_email($value, 0, 0, 0, 0, 1);
347 } elseif (preg_match('/^phone/', $typeofdata)) {
348 $ret .= dol_print_phone($value, '_blank', 32, 1);
349 } elseif (preg_match('/^url/', $typeofdata)) {
350 $ret .= dol_print_url($value, '_blank', 32, 1);
351 } elseif (preg_match('/^(amount|numeric)/', $typeofdata)) {
352 $ret .= ($value != '' ? price($value, '', $langs, 0, -1, -1, $conf->currency) : '');
353 } elseif (preg_match('/^checkbox/', $typeofdata)) {
354 $tmp = explode(':', $typeofdata);
355 $ret .= '<input type="checkbox" disabled id="' . $htmlname . '" name="' . $htmlname . '" value="' . $value . '"' . ($value ? ' checked' : '') . ($tmp[1] ? $tmp[1] : '') . '/>';
356 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) {
358 } elseif (preg_match('/^(safehtmlstring|restricthtml)/', $typeofdata)) { // 'restricthtml' is not an allowed type for editfieldval. Value is 'safehtmlstring'
360 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
361 $ret .= '<span class="valuedate">' . dol_print_date($value, 'day', $gm) . '</span>';
362 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
363 $ret .= '<span class="valuedate">' . dol_print_date($value, 'dayhour', $gm) . '</span>';
364 } elseif (preg_match('/^select;/', $typeofdata)) {
365 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
366 $arraylist = array();
367 foreach ($arraydata as $val) {
368 $tmp = explode(':', $val);
369 $arraylist[$tmp[0]] = $tmp[1];
370 }
371 $ret .= $arraylist[$value];
372 if ($htmlname == 'fk_product_type') {
373 if ($value == 0) {
374 $ret = img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
375 } else {
376 $ret = img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
377 }
378 }
379 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
380 $tmpcontent = dol_htmlentitiesbr($value);
381 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
382 $firstline = preg_replace('/<br>.*/', '', $tmpcontent);
383 $firstline = preg_replace('/[\n\r].*/', '', $firstline);
384 $tmpcontent = $firstline . ((strlen($firstline) != strlen($tmpcontent)) ? '...' : '');
385 }
386 // We dont use dol_escape_htmltag to get the html formating active, but this need we must also
387 // clean data from some dangerous html
389 } else {
390 if (empty($moreoptions['valuealreadyhtmlescaped'])) {
391 $ret .= dol_escape_htmltag($value);
392 } else {
393 $ret .= $value; // $value must be already html escaped.
394 }
395 }
396
397 // Custom format if parameter $formatfunc has been provided
398 if ($formatfunc && method_exists($object, $formatfunc)) {
399 $ret = $object->$formatfunc($ret);
400 }
401 }
402 }
403 return $ret;
404 }
405
417 public function widgetForTranslation($fieldname, $object, $perm, $typeofdata = 'string', $check = '', $morecss = '')
418 {
419 global $conf, $langs, $extralanguages;
420
421 $result = '';
422
423 // List of extra languages
424 $arrayoflangcode = array();
425 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
426 $arrayoflangcode[] = $conf->global->PDF_USE_ALSO_LANGUAGE_CODE;
427 }
428
429 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
430 if (!is_object($extralanguages)) {
431 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
432 $extralanguages = new ExtraLanguages($this->db);
433 }
434 $extralanguages->fetch_name_extralanguages('societe');
435
436 if (!is_array($extralanguages->attributes[$object->element]) || empty($extralanguages->attributes[$object->element][$fieldname])) {
437 return ''; // No extralang field to show
438 }
439
440 $result .= '<!-- Widget for translation -->' . "\n";
441 $result .= '<div class="inline-block paddingleft image-' . $object->element . '-' . $fieldname . '">';
442 $s = img_picto($langs->trans("ShowOtherLanguages"), 'language', '', false, 0, 0, '', 'fa-15 editfieldlang');
443 $result .= $s;
444 $result .= '</div>';
445
446 $result .= '<div class="inline-block hidden field-' . $object->element . '-' . $fieldname . '">';
447
448 $resultforextrlang = '';
449 foreach ($arrayoflangcode as $langcode) {
450 $valuetoshow = GETPOSTISSET('field-' . $object->element . "-" . $fieldname . "-" . $langcode) ? GETPOST('field-' . $object->element . '-' . $fieldname . "-" . $langcode, $check) : '';
451 if (empty($valuetoshow)) {
452 $object->fetchValuesForExtraLanguages();
453 //var_dump($object->array_languages);
454 $valuetoshow = $object->array_languages[$fieldname][$langcode];
455 }
456
457 $s = picto_from_langcode($langcode, 'class="pictoforlang paddingright"');
458 $resultforextrlang .= $s;
459
460 // TODO Use the showInputField() method of ExtraLanguages object
461 if ($typeofdata == 'textarea') {
462 $resultforextrlang .= '<textarea name="field-' . $object->element . "-" . $fieldname . "-" . $langcode . '" id="' . $fieldname . "-" . $langcode . '" class="' . $morecss . '" rows="' . ROWS_2 . '" wrap="soft">';
463 $resultforextrlang .= $valuetoshow;
464 $resultforextrlang .= '</textarea>';
465 } else {
466 $resultforextrlang .= '<input type="text" class="inputfieldforlang ' . ($morecss ? ' ' . $morecss : '') . '" name="field-' . $object->element . '-' . $fieldname . '-' . $langcode . '" value="' . $valuetoshow . '">';
467 }
468 }
469 $result .= $resultforextrlang;
470
471 $result .= '</div>';
472 $result .= '<script nonce="' . getNonce() . '">$(".image-' . $object->element . '-' . $fieldname . '").click(function() { console.log("Toggle lang widget"); jQuery(".field-' . $object->element . '-' . $fieldname . '").toggle(); });</script>';
473 }
474
475 return $result;
476 }
477
491 protected function editInPlace($object, $value, $htmlname, $condition, $inputType = 'textarea', $editvalue = null, $extObject = null, $custommsg = null)
492 {
493 global $conf;
494
495 $out = '';
496
497 // Check parameters
498 if (preg_match('/^text/', $inputType)) {
499 $value = dol_nl2br($value);
500 } elseif (preg_match('/^numeric/', $inputType)) {
501 $value = price($value);
502 } elseif ($inputType == 'day' || $inputType == 'datepicker') {
503 $value = dol_print_date($value, 'day');
504 }
505
506 if ($condition) {
507 $element = false;
508 $table_element = false;
509 $fk_element = false;
510 $loadmethod = false;
511 $savemethod = false;
512 $ext_element = false;
513 $button_only = false;
514 $inputOption = '';
515 $rows = '';
516 $cols = '';
517
518 if (is_object($object)) {
519 $element = $object->element;
520 $table_element = $object->table_element;
521 $fk_element = $object->id;
522 }
523
524 if (is_object($extObject)) {
525 $ext_element = $extObject->element;
526 }
527
528 if (preg_match('/^(string|email|numeric)/', $inputType)) {
529 $tmp = explode(':', $inputType);
530 $inputType = $tmp[0];
531 if (!empty($tmp[1])) {
532 $inputOption = $tmp[1];
533 }
534 if (!empty($tmp[2])) {
535 $savemethod = $tmp[2];
536 }
537 $out .= '<input id="width_' . $htmlname . '" value="' . $inputOption . '" type="hidden"/>' . "\n";
538 } elseif ((preg_match('/^day$/', $inputType)) || (preg_match('/^datepicker/', $inputType)) || (preg_match('/^datehourpicker/', $inputType))) {
539 $tmp = explode(':', $inputType);
540 $inputType = $tmp[0];
541 if (!empty($tmp[1])) {
542 $inputOption = $tmp[1];
543 }
544 if (!empty($tmp[2])) {
545 $savemethod = $tmp[2];
546 }
547
548 $out .= '<input id="timestamp" type="hidden"/>' . "\n"; // Use for timestamp format
549 } elseif (preg_match('/^(select|autocomplete)/', $inputType)) {
550 $tmp = explode(':', $inputType);
551 $inputType = $tmp[0];
552 $loadmethod = $tmp[1];
553 if (!empty($tmp[2])) {
554 $savemethod = $tmp[2];
555 }
556 if (!empty($tmp[3])) {
557 $button_only = true;
558 }
559 } elseif (preg_match('/^textarea/', $inputType)) {
560 $tmp = explode(':', $inputType);
561 $inputType = $tmp[0];
562 $rows = (empty($tmp[1]) ? '8' : $tmp[1]);
563 $cols = (empty($tmp[2]) ? '80' : $tmp[2]);
564 } elseif (preg_match('/^ckeditor/', $inputType)) {
565 $tmp = explode(':', $inputType);
566 $inputType = $tmp[0];
567 $toolbar = $tmp[1];
568 if (!empty($tmp[2])) {
569 $width = $tmp[2];
570 }
571 if (!empty($tmp[3])) {
572 $heigth = $tmp[3];
573 }
574 if (!empty($tmp[4])) {
575 $savemethod = $tmp[4];
576 }
577
578 if (isModEnabled('fckeditor')) {
579 $out .= '<input id="ckeditor_toolbar" value="' . $toolbar . '" type="hidden"/>' . "\n";
580 } else {
581 $inputType = 'textarea';
582 }
583 }
584
585 $out .= '<input id="element_' . $htmlname . '" value="' . $element . '" type="hidden"/>' . "\n";
586 $out .= '<input id="table_element_' . $htmlname . '" value="' . $table_element . '" type="hidden"/>' . "\n";
587 $out .= '<input id="fk_element_' . $htmlname . '" value="' . $fk_element . '" type="hidden"/>' . "\n";
588 $out .= '<input id="loadmethod_' . $htmlname . '" value="' . $loadmethod . '" type="hidden"/>' . "\n";
589 if (!empty($savemethod)) {
590 $out .= '<input id="savemethod_' . $htmlname . '" value="' . $savemethod . '" type="hidden"/>' . "\n";
591 }
592 if (!empty($ext_element)) {
593 $out .= '<input id="ext_element_' . $htmlname . '" value="' . $ext_element . '" type="hidden"/>' . "\n";
594 }
595 if (!empty($custommsg)) {
596 if (is_array($custommsg)) {
597 if (!empty($custommsg['success'])) {
598 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg['success'] . '" type="hidden"/>' . "\n";
599 }
600 if (!empty($custommsg['error'])) {
601 $out .= '<input id="errormsg_' . $htmlname . '" value="' . $custommsg['error'] . '" type="hidden"/>' . "\n";
602 }
603 } else {
604 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg . '" type="hidden"/>' . "\n";
605 }
606 }
607 if ($inputType == 'textarea') {
608 $out .= '<input id="textarea_' . $htmlname . '_rows" value="' . $rows . '" type="hidden"/>' . "\n";
609 $out .= '<input id="textarea_' . $htmlname . '_cols" value="' . $cols . '" type="hidden"/>' . "\n";
610 }
611 $out .= '<span id="viewval_' . $htmlname . '" class="viewval_' . $inputType . ($button_only ? ' inactive' : ' active') . '">' . $value . '</span>' . "\n";
612 $out .= '<span id="editval_' . $htmlname . '" class="editval_' . $inputType . ($button_only ? ' inactive' : ' active') . ' hideobject">' . (!empty($editvalue) ? $editvalue : $value) . '</span>' . "\n";
613 } else {
614 $out = $value;
615 }
616
617 return $out;
618 }
619
638 public function textwithtooltip($text, $htmltext, $tooltipon = 1, $direction = 0, $img = '', $extracss = '', $notabs = 3, $incbefore = '', $noencodehtmltext = 0, $tooltiptrigger = '', $forcenowrap = 0)
639 {
640 if ($incbefore) {
641 $text = $incbefore . $text;
642 }
643 if (!$htmltext) {
644 return $text;
645 }
646 $direction = (int) $direction; // For backward compatibility when $direction was set to '' instead of 0
647
648 $tag = 'td';
649 if ($notabs == 2) {
650 $tag = 'div';
651 }
652 if ($notabs == 3) {
653 $tag = 'span';
654 }
655 // Sanitize tooltip
656 $htmltext = str_replace(array("\r", "\n"), '', $htmltext);
657
658 $extrastyle = '';
659 if ($direction < 0) {
660 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
661 $extrastyle = 'padding: 0px; padding-left: 3px;';
662 }
663 if ($direction > 0) {
664 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
665 $extrastyle = 'padding: 0px; padding-right: 3px;';
666 }
667
668 $classfortooltip = 'classfortooltip';
669
670 $s = '';
671 $textfordialog = '';
672
673 if ($tooltiptrigger == '') {
674 $htmltext = str_replace('"', '&quot;', $htmltext);
675 } else {
676 $classfortooltip = 'classfortooltiponclick';
677 $textfordialog .= '<div style="display: none;" id="idfortooltiponclick_' . $tooltiptrigger . '" class="classfortooltiponclicktext">' . $htmltext . '</div>';
678 }
679 if ($tooltipon == 2 || $tooltipon == 3) {
680 $paramfortooltipimg = ' class="' . $classfortooltip . ($notabs != 3 ? ' inline-block' : '') . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '"';
681 if ($tooltiptrigger == '') {
682 $paramfortooltipimg .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribut to put on img tag to store tooltip
683 } else {
684 $paramfortooltipimg .= ' dolid="' . $tooltiptrigger . '"';
685 }
686 } else {
687 $paramfortooltipimg = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribut to put on td text tag
688 }
689 if ($tooltipon == 1 || $tooltipon == 3) {
690 $paramfortooltiptd = ' class="' . ($tooltipon == 3 ? 'cursorpointer ' : '') . $classfortooltip . ' inline-block' . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '" ';
691 if ($tooltiptrigger == '') {
692 $paramfortooltiptd .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribut to put on td tag to store tooltip
693 } else {
694 $paramfortooltiptd .= ' dolid="' . $tooltiptrigger . '"';
695 }
696 } else {
697 $paramfortooltiptd = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribut to put on td text tag
698 }
699 if (empty($notabs)) {
700 $s .= '<table class="nobordernopadding"><tr style="height: auto;">';
701 } elseif ($notabs == 2) {
702 $s .= '<div class="inline-block' . ($forcenowrap ? ' nowrap' : '') . '">';
703 }
704 // Define value if value is before
705 if ($direction < 0) {
706 $s .= '<' . $tag . $paramfortooltipimg;
707 if ($tag == 'td') {
708 $s .= ' class="valigntop" width="14"';
709 }
710 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
711 }
712 // Use another method to help avoid having a space in value in order to use this value with jquery
713 // Define label
714 if ((string) $text != '') {
715 $s .= '<' . $tag . $paramfortooltiptd . '>' . $text . '</' . $tag . '>';
716 }
717 // Define value if value is after
718 if ($direction > 0) {
719 $s .= '<' . $tag . $paramfortooltipimg;
720 if ($tag == 'td') {
721 $s .= ' class="valignmiddle" width="14"';
722 }
723 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
724 }
725 if (empty($notabs)) {
726 $s .= '</tr></table>';
727 } elseif ($notabs == 2) {
728 $s .= '</div>';
729 }
730
731 return $s;
732 }
733
748 public function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 3, $tooltiptrigger = '', $forcenowrap = 0)
749 {
750 global $conf, $langs;
751
752 //For backwards compatibility
753 if ($type == '0') {
754 $type = 'info';
755 } elseif ($type == '1') {
756 $type = 'help';
757 }
758 // Clean parameters
759 $tooltiptrigger = preg_replace('/[^a-z0-9]/i', '', $tooltiptrigger);
760
761 if (preg_match('/onsmartphone$/', $tooltiptrigger) && empty($conf->dol_no_mouse_hover)) {
762 $tooltiptrigger = preg_replace('/^.*onsmartphone$/', '', $tooltiptrigger);
763 }
764 $alt = '';
765 if ($tooltiptrigger) {
766 $alt = $langs->transnoentitiesnoconv("ClickToShowHelp");
767 }
768
769 // If info or help with no javascript, show only text
770 if (empty($conf->use_javascript_ajax)) {
771 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
772 return $text;
773 } else {
774 $alt = $htmltext;
775 $htmltext = '';
776 }
777 }
778
779 // If info or help with smartphone, show only text (tooltip hover can't works)
780 if (!empty($conf->dol_no_mouse_hover) && empty($tooltiptrigger)) {
781 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
782 return $text;
783 }
784 }
785 // If info or help with smartphone, show only text (tooltip on click does not works with dialog on smaprtphone)
786 //if (!empty($conf->dol_no_mouse_hover) && !empty($tooltiptrigger))
787 //{
788 //if ($type == 'info' || $type == 'help') return '<a href="'..'">'.$text.'</a>';
789 //}
790
791 $img = '';
792 if ($type == 'info') {
793 $img = img_help(0, $alt);
794 } elseif ($type == 'help') {
795 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
796 } elseif ($type == 'helpclickable') {
797 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
798 } elseif ($type == 'superadmin') {
799 $img = img_picto($alt, 'redstar');
800 } elseif ($type == 'admin') {
801 $img = img_picto($alt, 'star');
802 } elseif ($type == 'warning') {
803 $img = img_warning($alt);
804 } elseif ($type != 'none') {
805 $img = img_picto($alt, $type); // $type can be an image path
806 }
807
808 return $this->textwithtooltip($text, $htmltext, ((($tooltiptrigger && !$img) || strpos($type, 'clickable')) ? 3 : 2), $direction, $img, $extracss, $notabs, '', $noencodehtmltext, $tooltiptrigger, $forcenowrap);
809 }
810
821 public function selectMassAction($selected, $arrayofaction, $alwaysvisible = 0, $name = 'massaction', $cssclass = 'checkforselect')
822 {
823 global $conf, $langs, $hookmanager;
824
825 $disabled = 0;
826 $ret = '<div class="centpercent center">';
827 $ret .= '<select class="flat' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'select valignmiddle alignstart" id="' . $name . '" name="' . $name . '"' . ($disabled ? ' disabled="disabled"' : '') . '>';
828
829 // 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.
830 $parameters = array();
831 $reshook = $hookmanager->executeHooks('addMoreMassActions', $parameters); // Note that $action and $object may have been modified by hook
832 // check if there is a mass action
833
834 if (is_array($arrayofaction) && count($arrayofaction) == 0 && empty($hookmanager->resPrint)) {
835 return;
836 }
837 if (empty($reshook)) {
838 $ret .= '<option value="0"' . ($disabled ? ' disabled="disabled"' : '') . '>-- ' . $langs->trans("SelectAction") . ' --</option>';
839 if (is_array($arrayofaction)) {
840 foreach ($arrayofaction as $code => $label) {
841 $ret .= '<option value="' . $code . '"' . ($disabled ? ' disabled="disabled"' : '') . ' data-html="' . dol_escape_htmltag($label) . '">' . $label . '</option>';
842 }
843 }
844 }
845 $ret .= $hookmanager->resPrint;
846
847 $ret .= '</select>';
848
849 if (empty($conf->dol_optimize_smallscreen)) {
850 $ret .= ajax_combobox('.' . $name . 'select');
851 }
852
853 // 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
854 $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.
855 $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")) . '">';
856 $ret .= '</div>';
857
858 if (!empty($conf->use_javascript_ajax)) {
859 $ret .= '<!-- JS CODE TO ENABLE mass action select -->
860 <script nonce="' . getNonce() . '">
861 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 */
862 {
863 atleastoneselected=0;
864 jQuery("."+cssclass).each(function( index ) {
865 /* console.log( index + ": " + $( this ).text() ); */
866 if ($(this).is(\':checked\')) atleastoneselected++;
867 });
868
869 console.log("initCheckForSelect mode="+mode+" name="+name+" cssclass="+cssclass+" atleastoneselected="+atleastoneselected);
870
871 if (atleastoneselected || ' . $alwaysvisible . ')
872 {
873 jQuery("."+name).show();
874 ' . ($selected ? 'if (atleastoneselected) { jQuery("."+name+"select").val("' . $selected . '").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', false); }' : '') . '
875 ' . ($selected ? 'if (! atleastoneselected) { jQuery("."+name+"select").val("0").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', true); } ' : '') . '
876 }
877 else
878 {
879 jQuery("."+name).hide();
880 jQuery("."+name+"other").hide();
881 }
882 }
883
884 jQuery(document).ready(function () {
885 initCheckForSelect(0, "' . $name . '", "' . $cssclass . '");
886 jQuery(".' . $cssclass . '").click(function() {
887 initCheckForSelect(1, "' . $name . '", "' . $cssclass . '");
888 });
889 jQuery(".' . $name . 'select").change(function() {
890 var massaction = $( this ).val();
891 var urlform = $( this ).closest("form").attr("action").replace("#show_files","");
892 if (massaction == "builddoc")
893 {
894 urlform = urlform + "#show_files";
895 }
896 $( this ).closest("form").attr("action", urlform);
897 console.log("we select a mass action name=' . $name . ' massaction="+massaction+" - "+urlform);
898 /* Warning: if you set submit button to disabled, post using Enter will no more work if there is no other button */
899 if ($(this).val() != \'0\')
900 {
901 jQuery(".' . $name . 'confirmed").prop(\'disabled\', false);
902 jQuery(".' . $name . 'other").hide(); /* To disable if another div was open */
903 jQuery(".' . $name . '"+massaction).show();
904 }
905 else
906 {
907 jQuery(".' . $name . 'confirmed").prop(\'disabled\', true);
908 jQuery(".' . $name . 'other").hide(); /* To disable any div open */
909 }
910 });
911 });
912 </script>
913 ';
914 }
915
916 return $ret;
917 }
918
919 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
920
937 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)
938 {
939 // phpcs:enable
940 global $conf, $langs, $mysoc;
941
942 $langs->load("dict");
943
944 $out = '';
945 $countryArray = array();
946 $favorite = array();
947 $label = array();
948 $atleastonefavorite = 0;
949
950 $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite, eec";
951 $sql .= " FROM " . $this->db->prefix() . "c_country";
952 $sql .= " WHERE active > 0";
953 //$sql.= " ORDER BY code ASC";
954
955 dol_syslog(get_class($this) . "::select_country", LOG_DEBUG);
956 $resql = $this->db->query($sql);
957 if ($resql) {
958 $out .= '<select id="select' . $htmlname . '" class="flat maxwidth200onsmartphone selectcountry' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" ' . $htmloption . '>';
959 $num = $this->db->num_rows($resql);
960 $i = 0;
961 if ($num) {
962 while ($i < $num) {
963 $obj = $this->db->fetch_object($resql);
964
965 $countryArray[$i]['rowid'] = $obj->rowid;
966 $countryArray[$i]['code_iso'] = $obj->code_iso;
967 $countryArray[$i]['code_iso3'] = $obj->code_iso3;
968 $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 : ''));
969 $countryArray[$i]['favorite'] = $obj->favorite;
970 $countryArray[$i]['eec'] = $obj->eec;
971 $favorite[$i] = $obj->favorite;
972 $label[$i] = dol_string_unaccent($countryArray[$i]['label']);
973 $i++;
974 }
975
976 if (empty($disablefavorites)) {
977 $array1_sort_order = SORT_DESC;
978 $array2_sort_order = SORT_ASC;
979 array_multisort($favorite, $array1_sort_order, $label, $array2_sort_order, $countryArray);
980 } else {
981 $countryArray = dol_sort_array($countryArray, 'label');
982 }
983
984 if ($showempty) {
985 if (is_numeric($showempty)) {
986 $out .= '<option value="">&nbsp;</option>' . "\n";
987 } else {
988 $out .= '<option value="-1">' . $langs->trans($showempty) . '</option>' . "\n";
989 }
990 }
991
992 if ($addspecialentries) { // Add dedicated entries for groups of countries
993 //if ($showempty) $out.= '<option value="" disabled class="selectoptiondisabledwhite">--------------</option>';
994 $out .= '<option value="special_allnotme"' . ($selected == 'special_allnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
995 $out .= '<option value="special_eec"' . ($selected == 'special_eec' ? ' selected' : '') . '>' . $langs->trans("CountriesInEEC") . '</option>';
996 if ($mysoc->isInEEC()) {
997 $out .= '<option value="special_eecnotme"' . ($selected == 'special_eecnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesInEECExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
998 }
999 $out .= '<option value="special_noteec"' . ($selected == 'special_noteec' ? ' selected' : '') . '>' . $langs->trans("CountriesNotInEEC") . '</option>';
1000 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1001 }
1002
1003 foreach ($countryArray as $row) {
1004 //if (empty($showempty) && empty($row['rowid'])) continue;
1005 if (empty($row['rowid'])) {
1006 continue;
1007 }
1008 if (is_array($exclude_country_code) && count($exclude_country_code) && in_array($row['code_iso'], $exclude_country_code)) {
1009 continue; // exclude some countries
1010 }
1011
1012 if (empty($disablefavorites) && $row['favorite'] && $row['code_iso']) {
1013 $atleastonefavorite++;
1014 }
1015 if (empty($row['favorite']) && $atleastonefavorite) {
1016 $atleastonefavorite = 0;
1017 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1018 }
1019
1020 $labeltoshow = '';
1021 if ($row['label']) {
1022 $labeltoshow .= dol_trunc($row['label'], $maxlength, 'middle');
1023 } else {
1024 $labeltoshow .= '&nbsp;';
1025 }
1026 if ($row['code_iso']) {
1027 $labeltoshow .= ' <span class="opacitymedium">(' . $row['code_iso'] . ')</span>';
1028 if (empty($hideflags)) {
1029 $tmpflag = picto_from_langcode($row['code_iso'], 'class="saturatemedium paddingrightonly"', 1);
1030 $labeltoshow = $tmpflag . ' ' . $labeltoshow;
1031 }
1032 }
1033
1034 if ($selected && $selected != '-1' && ($selected == $row['rowid'] || $selected == $row['code_iso'] || $selected == $row['code_iso3'] || $selected == $row['label'])) {
1035 $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']) . '">';
1036 } else {
1037 $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']) . '">';
1038 }
1039 $out .= $labeltoshow;
1040 $out .= '</option>' . "\n";
1041 }
1042 }
1043 $out .= '</select>';
1044 } else {
1045 dol_print_error($this->db);
1046 }
1047
1048 // Make select dynamic
1049 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1050 $out .= ajax_combobox('select' . $htmlname, array(), 0, 0, 'resolve');
1051
1052 return $out;
1053 }
1054
1055 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1056
1070 public function select_incoterms($selected = '', $location_incoterms = '', $page = '', $htmlname = 'incoterm_id', $htmloption = '', $forcecombo = 1, $events = array(), $disableautocomplete = 0)
1071 {
1072 // phpcs:enable
1073 global $conf, $langs;
1074
1075 $langs->load("dict");
1076
1077 $out = '';
1078 $moreattrib = '';
1079 $incotermArray = array();
1080
1081 $sql = "SELECT rowid, code";
1082 $sql .= " FROM " . $this->db->prefix() . "c_incoterms";
1083 $sql .= " WHERE active > 0";
1084 $sql .= " ORDER BY code ASC";
1085
1086 dol_syslog(get_class($this) . "::select_incoterm", LOG_DEBUG);
1087 $resql = $this->db->query($sql);
1088 if ($resql) {
1089 if ($conf->use_javascript_ajax && !$forcecombo) {
1090 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1091 $out .= ajax_combobox($htmlname, $events);
1092 }
1093
1094 if (!empty($page)) {
1095 $out .= '<form method="post" action="' . $page . '">';
1096 $out .= '<input type="hidden" name="action" value="set_incoterms">';
1097 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
1098 }
1099
1100 $out .= '<select id="' . $htmlname . '" class="flat selectincoterm width75" name="' . $htmlname . '" ' . $htmloption . '>';
1101 $out .= '<option value="0">&nbsp;</option>';
1102 $num = $this->db->num_rows($resql);
1103 $i = 0;
1104 if ($num) {
1105 while ($i < $num) {
1106 $obj = $this->db->fetch_object($resql);
1107 $incotermArray[$i]['rowid'] = $obj->rowid;
1108 $incotermArray[$i]['code'] = $obj->code;
1109 $i++;
1110 }
1111
1112 foreach ($incotermArray as $row) {
1113 if ($selected && ($selected == $row['rowid'] || $selected == $row['code'])) {
1114 $out .= '<option value="' . $row['rowid'] . '" selected>';
1115 } else {
1116 $out .= '<option value="' . $row['rowid'] . '">';
1117 }
1118
1119 if ($row['code']) {
1120 $out .= $row['code'];
1121 }
1122
1123 $out .= '</option>';
1124 }
1125 }
1126 $out .= '</select>';
1127
1128 if ($conf->use_javascript_ajax && empty($disableautocomplete)) {
1129 $out .= ajax_multiautocompleter('location_incoterms', array(), DOL_URL_ROOT . '/core/ajax/locationincoterms.php') . "\n";
1130 $moreattrib .= ' autocomplete="off"';
1131 }
1132 $out .= '<input id="location_incoterms" class="maxwidthonsmartphone type="text" name="location_incoterms" value="' . $location_incoterms . '">' . "\n";
1133
1134 if (!empty($page)) {
1135 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp nomargintop nomarginbottom" value="' . $langs->trans("Modify") . '"></form>';
1136 }
1137 } else {
1138 dol_print_error($this->db);
1139 }
1140
1141 return $out;
1142 }
1143
1144 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1145
1157 public function select_type_of_lines($selected = '', $htmlname = 'type', $showempty = 0, $hidetext = 0, $forceall = 0)
1158 {
1159 // phpcs:enable
1160 global $langs;
1161
1162 // If product & services are enabled or both disabled.
1163 if ($forceall == 1 || (empty($forceall) && isModEnabled("product") && isModEnabled("service"))
1164 || (empty($forceall) && !isModEnabled('product') && !isModEnabled('service'))) {
1165 if (empty($hidetext)) {
1166 print $langs->trans("Type") . ': ';
1167 }
1168 print '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
1169 if ($showempty) {
1170 print '<option value="-1"';
1171 if ($selected == -1) {
1172 print ' selected';
1173 }
1174 print '>&nbsp;</option>';
1175 }
1176
1177 print '<option value="0"';
1178 if (0 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'product')) {
1179 print ' selected';
1180 }
1181 print '>' . $langs->trans("Product");
1182
1183 print '<option value="1"';
1184 if (1 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'service')) {
1185 print ' selected';
1186 }
1187 print '>' . $langs->trans("Service");
1188
1189 print '</select>';
1190 print ajax_combobox('select_' . $htmlname);
1191 //if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1192 }
1193 if ((empty($forceall) && !isModEnabled('product') && isModEnabled("service")) || $forceall == 3) {
1194 print $langs->trans("Service");
1195 print '<input type="hidden" name="' . $htmlname . '" value="1">';
1196 }
1197 if ((empty($forceall) && isModEnabled("product") && !isModEnabled('service')) || $forceall == 2) {
1198 print $langs->trans("Product");
1199 print '<input type="hidden" name="' . $htmlname . '" value="0">';
1200 }
1201 if ($forceall < 0) { // This should happened only for contracts when both predefined product and service are disabled.
1202 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
1203 }
1204 }
1205
1206 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1207
1213 public function load_cache_types_fees()
1214 {
1215 // phpcs:enable
1216 global $langs;
1217
1218 $num = count($this->cache_types_fees);
1219 if ($num > 0) {
1220 return 0; // Cache already loaded
1221 }
1222
1223 dol_syslog(__METHOD__, LOG_DEBUG);
1224
1225 $langs->load("trips");
1226
1227 $sql = "SELECT c.code, c.label";
1228 $sql .= " FROM " . $this->db->prefix() . "c_type_fees as c";
1229 $sql .= " WHERE active > 0";
1230
1231 $resql = $this->db->query($sql);
1232 if ($resql) {
1233 $num = $this->db->num_rows($resql);
1234 $i = 0;
1235
1236 while ($i < $num) {
1237 $obj = $this->db->fetch_object($resql);
1238
1239 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
1240 $label = ($obj->code != $langs->trans($obj->code) ? $langs->trans($obj->code) : $langs->trans($obj->label));
1241 $this->cache_types_fees[$obj->code] = $label;
1242 $i++;
1243 }
1244
1245 asort($this->cache_types_fees);
1246
1247 return $num;
1248 } else {
1249 dol_print_error($this->db);
1250 return -1;
1251 }
1252 }
1253
1254 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1255
1264 public function select_type_fees($selected = '', $htmlname = 'type', $showempty = 0)
1265 {
1266 // phpcs:enable
1267 global $user, $langs;
1268
1269 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
1270
1271 $this->load_cache_types_fees();
1272
1273 print '<select id="select_' . $htmlname . '" class="flat" name="' . $htmlname . '">';
1274 if ($showempty) {
1275 print '<option value="-1"';
1276 if ($selected == -1) {
1277 print ' selected';
1278 }
1279 print '>&nbsp;</option>';
1280 }
1281
1282 foreach ($this->cache_types_fees as $key => $value) {
1283 print '<option value="' . $key . '"';
1284 if ($key == $selected) {
1285 print ' selected';
1286 }
1287 print '>';
1288 print $value;
1289 print '</option>';
1290 }
1291
1292 print '</select>';
1293 if ($user->admin) {
1294 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1295 }
1296 }
1297
1298
1299 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1300
1322 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)
1323 {
1324 // phpcs:enable
1325 global $conf, $user, $langs;
1326
1327 $out = '';
1328
1329 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT') && !$forcecombo) {
1330 if (is_null($ajaxoptions)) {
1331 $ajaxoptions = array();
1332 }
1333
1334 require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1335
1336 // No immediate load of all database
1337 $placeholder = '';
1338 if ($selected && empty($selected_input_value)) {
1339 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1340 $societetmp = new Societe($this->db);
1341 $societetmp->fetch($selected);
1342 $selected_input_value = $societetmp->name;
1343 unset($societetmp);
1344 }
1345
1346 // mode 1
1347 $urloption = 'htmlname=' . urlencode(str_replace('.', '_', $htmlname)) . '&outjson=1&filter=' . urlencode($filter) . (empty($excludeids) ? '' : '&excludeids=' . join(',', $excludeids)) . ($showtype ? '&showtype=' . urlencode($showtype) : '') . ($showcode ? '&showcode=' . urlencode($showcode) : '');
1348
1349 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
1350 if (empty($hidelabel)) {
1351 print $langs->trans("RefOrLabel") . ' : ';
1352 } elseif ($hidelabel > 1) {
1353 $placeholder = $langs->trans("RefOrLabel");
1354 if ($hidelabel == 2) {
1355 $out .= img_picto($langs->trans("Search"), 'search');
1356 }
1357 }
1358 $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' : '') . ' />';
1359 if ($hidelabel == 3) {
1360 $out .= img_picto($langs->trans("Search"), 'search');
1361 }
1362
1363 $out .= ajax_event($htmlname, $events);
1364
1365 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/societe/ajax/company.php', $urloption, $conf->global->COMPANY_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
1366 } else {
1367 // Immediate load of all database
1368 $out .= $this->select_thirdparty_list($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, '', 0, $limit, $morecss, $moreparam, $multiple, $excludeids, $showcode);
1369 }
1370
1371 return $out;
1372 }
1373
1374 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1375
1399 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)
1400 {
1401 // phpcs:enable
1402 global $conf, $user, $langs;
1403 global $hookmanager;
1404
1405 $out = '';
1406 $num = 0;
1407 $outarray = array();
1408
1409 if ($selected === '') {
1410 $selected = array();
1411 } elseif (!is_array($selected)) {
1412 $selected = array($selected);
1413 }
1414
1415 // Clean $filter that may contains sql conditions so sql code
1416 if (function_exists('testSqlAndScriptInject')) {
1417 if (testSqlAndScriptInject($filter, 3) > 0) {
1418 $filter = '';
1419 return 'SQLInjectionTryDetected';
1420 }
1421 }
1422
1423 if ($filter != '') { // If a filter was provided
1424 if (preg_match('/[\‍(\‍)]/', $filter)) {
1425 // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax.
1426 $errormsg = '';
1427 $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1);
1428
1429 // Redo clean $filter that may contains sql conditions so sql code
1430 if (function_exists('testSqlAndScriptInject')) {
1431 if (testSqlAndScriptInject($filter, 3) > 0) {
1432 $filter = '';
1433 return 'SQLInjectionTryDetected';
1434 }
1435 }
1436 } else {
1437 // If not, we do nothing. We already know that there is no parenthesis
1438 // TODO Disallow this case in a future.
1439 dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Syntax.", LOG_WARNING);
1440 }
1441 }
1442
1443 // We search companies
1444 $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.tva_intra, s.client, s.fournisseur, s.code_client, s.code_fournisseur";
1445 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1446 $sql .= ", s.address, s.zip, s.town";
1447 $sql .= ", dictp.code as country_code";
1448 }
1449 $sql .= " FROM " . $this->db->prefix() . "societe as s";
1450 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1451 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_country as dictp ON dictp.rowid = s.fk_pays";
1452 }
1453 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
1454 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
1455 }
1456 $sql .= " WHERE s.entity IN (" . getEntity('societe') . ")";
1457 if (!empty($user->socid)) {
1458 $sql .= " AND s.rowid = " . ((int) $user->socid);
1459 }
1460 if ($filter) {
1461 // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria()
1462 // if not, by testSqlAndScriptInject() only.
1463 $sql .= " AND (" . $filter . ")";
1464 }
1465 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
1466 $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
1467 }
1468 if (getDolGlobalString('COMPANY_HIDE_INACTIVE_IN_COMBOBOX')) {
1469 $sql .= " AND s.status <> 0";
1470 }
1471 if (!empty($excludeids)) {
1472 $sql .= " AND s.rowid NOT IN (" . $this->db->sanitize(join(',', $excludeids)) . ")";
1473 }
1474 // Add where from hooks
1475 $parameters = array();
1476 $reshook = $hookmanager->executeHooks('selectThirdpartyListWhere', $parameters); // Note that $action and $object may have been modified by hook
1477 $sql .= $hookmanager->resPrint;
1478 // Add criteria
1479 if ($filterkey && $filterkey != '') {
1480 $sql .= " AND (";
1481 $prefix = !getDolGlobalString('COMPANY_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if COMPANY_DONOTSEARCH_ANYWHERE is on
1482 // For natural search
1483 $scrit = explode(' ', $filterkey);
1484 $i = 0;
1485 if (count($scrit) > 1) {
1486 $sql .= "(";
1487 }
1488 foreach ($scrit as $crit) {
1489 if ($i > 0) {
1490 $sql .= " AND ";
1491 }
1492 $sql .= "(s.nom LIKE '" . $this->db->escape($prefix . $crit) . "%')";
1493 $i++;
1494 }
1495 if (count($scrit) > 1) {
1496 $sql .= ")";
1497 }
1498 if (isModEnabled('barcode')) {
1499 $sql .= " OR s.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1500 }
1501 $sql .= " OR s.code_client LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.code_fournisseur LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1502 $sql .= " OR s.name_alias LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.tva_intra LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1503 $sql .= ")";
1504 }
1505 $sql .= $this->db->order("nom", "ASC");
1506 $sql .= $this->db->plimit($limit, 0);
1507
1508 // Build output string
1509 dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
1510 $resql = $this->db->query($sql);
1511 if ($resql) {
1512 if (!$forcecombo) {
1513 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1514 $out .= ajax_combobox($htmlname, $events, getDolGlobalString("COMPANY_USE_SEARCH_TO_SELECT"));
1515 }
1516
1517 // Construct $out and $outarray
1518 $out .= '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($moreparam ? ' ' . $moreparam : '') . ' name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . '>' . "\n";
1519
1520 $textifempty = (($showempty && !is_numeric($showempty)) ? $langs->trans($showempty) : '');
1521 if (getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
1522 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
1523 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
1524 if ($showempty && !is_numeric($showempty)) {
1525 $textifempty = $langs->trans($showempty);
1526 } else {
1527 $textifempty .= $langs->trans("All");
1528 }
1529 }
1530 if ($showempty) {
1531 $out .= '<option value="-1" data-html="' . dol_escape_htmltag('<span class="opacitymedium">' . ($textifempty ? $textifempty : '&nbsp;') . '</span>') . '">' . $textifempty . '</option>' . "\n";
1532 }
1533
1534 $companytemp = new Societe($this->db);
1535
1536 $num = $this->db->num_rows($resql);
1537 $i = 0;
1538 if ($num) {
1539 while ($i < $num) {
1540 $obj = $this->db->fetch_object($resql);
1541 $label = '';
1542 if ($showcode || getDolGlobalString('SOCIETE_ADD_REF_IN_LIST')) {
1543 if (($obj->client) && (!empty($obj->code_client))) {
1544 $label = $obj->code_client . ' - ';
1545 }
1546 if (($obj->fournisseur) && (!empty($obj->code_fournisseur))) {
1547 $label .= $obj->code_fournisseur . ' - ';
1548 }
1549 $label .= ' ' . $obj->name;
1550 } else {
1551 $label = $obj->name;
1552 }
1553
1554 if (!empty($obj->name_alias)) {
1555 $label .= ' (' . $obj->name_alias . ')';
1556 }
1557
1558 if (getDolGlobalString('SOCIETE_SHOW_VAT_IN_LIST') && !empty($obj->tva_intra)) {
1559 $label .= ' - '.$obj->tva_intra;
1560 }
1561
1562 $labelhtml = $label;
1563
1564 if ($showtype) {
1565 $companytemp->id = $obj->rowid;
1566 $companytemp->client = $obj->client;
1567 $companytemp->fournisseur = $obj->fournisseur;
1568 $tmptype = $companytemp->getTypeUrl(1, '', 0, 'span');
1569 if ($tmptype) {
1570 $labelhtml .= ' ' . $tmptype;
1571 }
1572
1573 if ($obj->client || $obj->fournisseur) {
1574 $label .= ' (';
1575 }
1576 if ($obj->client == 1 || $obj->client == 3) {
1577 $label .= $langs->trans("Customer");
1578 }
1579 if ($obj->client == 2 || $obj->client == 3) {
1580 $label .= ($obj->client == 3 ? ', ' : '') . $langs->trans("Prospect");
1581 }
1582 if ($obj->fournisseur) {
1583 $label .= ($obj->client ? ', ' : '') . $langs->trans("Supplier");
1584 }
1585 if ($obj->client || $obj->fournisseur) {
1586 $label .= ')';
1587 }
1588 }
1589
1590 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1591 $s = ($obj->address ? ' - ' . $obj->address : '') . ($obj->zip ? ' - ' . $obj->zip : '') . ($obj->town ? ' ' . $obj->town : '');
1592 if (!empty($obj->country_code)) {
1593 $s .= ', ' . $langs->trans('Country' . $obj->country_code);
1594 }
1595 $label .= $s;
1596 $labelhtml .= $s;
1597 }
1598
1599 if (empty($outputmode)) {
1600 if (in_array($obj->rowid, $selected)) {
1601 $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>';
1602 } else {
1603 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1604 }
1605 } else {
1606 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label, 'labelhtml' => $labelhtml));
1607 }
1608
1609 $i++;
1610 if (($i % 10) == 0) {
1611 $out .= "\n";
1612 }
1613 }
1614 }
1615 $out .= '</select>' . "\n";
1616 } else {
1617 dol_print_error($this->db);
1618 }
1619
1620 $this->result = array('nbofthirdparties' => $num);
1621
1622 if ($outputmode) {
1623 return $outarray;
1624 }
1625 return $out;
1626 }
1627
1628
1629 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1630
1641 public function select_remises($selected, $htmlname, $filter, $socid, $maxvalue = 0)
1642 {
1643 // phpcs:enable
1644 global $langs, $conf;
1645
1646 // On recherche les remises
1647 $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
1648 $sql .= " re.description, re.fk_facture_source";
1649 $sql .= " FROM " . $this->db->prefix() . "societe_remise_except as re";
1650 $sql .= " WHERE re.fk_soc = " . (int) $socid;
1651 $sql .= " AND re.entity = " . $conf->entity;
1652 if ($filter) {
1653 $sql .= " AND " . $filter;
1654 }
1655 $sql .= " ORDER BY re.description ASC";
1656
1657 dol_syslog(get_class($this) . "::select_remises", LOG_DEBUG);
1658 $resql = $this->db->query($sql);
1659 if ($resql) {
1660 print '<select id="select_' . $htmlname . '" class="flat maxwidthonsmartphone" name="' . $htmlname . '">';
1661 $num = $this->db->num_rows($resql);
1662
1663 $qualifiedlines = $num;
1664
1665 $i = 0;
1666 if ($num) {
1667 print '<option value="0">&nbsp;</option>';
1668 while ($i < $num) {
1669 $obj = $this->db->fetch_object($resql);
1670 $desc = dol_trunc($obj->description, 40);
1671 if (preg_match('/\‍(CREDIT_NOTE\‍)/', $desc)) {
1672 $desc = preg_replace('/\‍(CREDIT_NOTE\‍)/', $langs->trans("CreditNote"), $desc);
1673 }
1674 if (preg_match('/\‍(DEPOSIT\‍)/', $desc)) {
1675 $desc = preg_replace('/\‍(DEPOSIT\‍)/', $langs->trans("Deposit"), $desc);
1676 }
1677 if (preg_match('/\‍(EXCESS RECEIVED\‍)/', $desc)) {
1678 $desc = preg_replace('/\‍(EXCESS RECEIVED\‍)/', $langs->trans("ExcessReceived"), $desc);
1679 }
1680 if (preg_match('/\‍(EXCESS PAID\‍)/', $desc)) {
1681 $desc = preg_replace('/\‍(EXCESS PAID\‍)/', $langs->trans("ExcessPaid"), $desc);
1682 }
1683
1684 $selectstring = '';
1685 if ($selected > 0 && $selected == $obj->rowid) {
1686 $selectstring = ' selected';
1687 }
1688
1689 $disabled = '';
1690 if ($maxvalue > 0 && $obj->amount_ttc > $maxvalue) {
1691 $qualifiedlines--;
1692 $disabled = ' disabled';
1693 }
1694
1695 if (getDolGlobalString('MAIN_SHOW_FACNUMBER_IN_DISCOUNT_LIST') && !empty($obj->fk_facture_source)) {
1696 $tmpfac = new Facture($this->db);
1697 if ($tmpfac->fetch($obj->fk_facture_source) > 0) {
1698 $desc = $desc . ' - ' . $tmpfac->ref;
1699 }
1700 }
1701
1702 print '<option value="' . $obj->rowid . '"' . $selectstring . $disabled . '>' . $desc . ' (' . price($obj->amount_ht) . ' ' . $langs->trans("HT") . ' - ' . price($obj->amount_ttc) . ' ' . $langs->trans("TTC") . ')</option>';
1703 $i++;
1704 }
1705 }
1706 print '</select>';
1707 print ajax_combobox('select_' . $htmlname);
1708
1709 return $qualifiedlines;
1710 } else {
1711 dol_print_error($this->db);
1712 return -1;
1713 }
1714 }
1715
1716 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1717
1738 public function select_contacts($socid, $selected = '', $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $showsoc = 0, $forcecombo = 0, $events = array(), $options_only = false, $moreparam = '', $htmlid = '')
1739 {
1740 // phpcs:enable
1741 print $this->selectcontacts($socid, $selected, $htmlname, $showempty, $exclude, $limitto, $showfunction, $morecss, $options_only, $showsoc, $forcecombo, $events, $moreparam, $htmlid);
1742 return $this->num;
1743 }
1744
1769 public function selectcontacts($socid, $selected = array(), $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $options_only = false, $showsoc = 0, $forcecombo = 0, $events = array(), $moreparam = '', $htmlid = '', $multiple = false, $disableifempty = 0)
1770 {
1771 global $conf, $langs, $hookmanager, $action;
1772
1773 $langs->load('companies');
1774
1775 if (empty($htmlid)) {
1776 $htmlid = $htmlname;
1777 }
1778 $num = 0;
1779
1780 if ($selected === '') {
1781 $selected = array();
1782 } elseif (!is_array($selected)) {
1783 $selected = array($selected);
1784 }
1785 $out = '';
1786
1787 if (!is_object($hookmanager)) {
1788 include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
1789 $hookmanager = new HookManager($this->db);
1790 }
1791
1792 // We search third parties
1793 $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";
1794 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1795 $sql .= ", s.nom as company, s.town AS company_town";
1796 }
1797 $sql .= " FROM " . $this->db->prefix() . "socpeople as sp";
1798 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1799 $sql .= " LEFT OUTER JOIN " . $this->db->prefix() . "societe as s ON s.rowid=sp.fk_soc";
1800 }
1801 $sql .= " WHERE sp.entity IN (" . getEntity('contact') . ")";
1802 if ($socid > 0 || $socid == -1) {
1803 $sql .= " AND sp.fk_soc = " . ((int) $socid);
1804 }
1805 if (getDolGlobalString('CONTACT_HIDE_INACTIVE_IN_COMBOBOX')) {
1806 $sql .= " AND sp.statut <> 0";
1807 }
1808 // Add where from hooks
1809 $parameters = array();
1810 $reshook = $hookmanager->executeHooks('selectContactListWhere', $parameters); // Note that $action and $object may have been modified by hook
1811 $sql .= $hookmanager->resPrint;
1812 $sql .= " ORDER BY sp.lastname ASC";
1813
1814 dol_syslog(get_class($this) . "::selectcontacts", LOG_DEBUG);
1815 $resql = $this->db->query($sql);
1816 if ($resql) {
1817 $num = $this->db->num_rows($resql);
1818
1819 if ($htmlname != 'none' && !$options_only) {
1820 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlid . '" name="' . $htmlname . (($num || empty($disableifempty)) ? '' : ' disabled') . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . (!empty($moreparam) ? $moreparam : '') . '>';
1821 }
1822
1823 if ($showempty && !is_numeric($showempty)) {
1824 $textforempty = $showempty;
1825 $out .= '<option class="optiongrey" value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>' . $textforempty . '</option>';
1826 } else {
1827 if (($showempty == 1 || ($showempty == 3 && $num > 1)) && !$multiple) {
1828 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>&nbsp;</option>';
1829 }
1830 if ($showempty == 2) {
1831 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>-- ' . $langs->trans("Internal") . ' --</option>';
1832 }
1833 }
1834
1835 $i = 0;
1836 if ($num) {
1837 include_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1838 $contactstatic = new Contact($this->db);
1839
1840 while ($i < $num) {
1841 $obj = $this->db->fetch_object($resql);
1842
1843 // Set email (or phones) and town extended infos
1844 $extendedInfos = '';
1845 if (getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1846 $extendedInfos = array();
1847 $email = trim($obj->email);
1848 if (!empty($email)) {
1849 $extendedInfos[] = $email;
1850 } else {
1851 $phone = trim($obj->phone);
1852 $phone_perso = trim($obj->phone_perso);
1853 $phone_mobile = trim($obj->phone_mobile);
1854 if (!empty($phone)) {
1855 $extendedInfos[] = $phone;
1856 }
1857 if (!empty($phone_perso)) {
1858 $extendedInfos[] = $phone_perso;
1859 }
1860 if (!empty($phone_mobile)) {
1861 $extendedInfos[] = $phone_mobile;
1862 }
1863 }
1864 $contact_town = trim($obj->contact_town);
1865 $company_town = trim($obj->company_town);
1866 if (!empty($contact_town)) {
1867 $extendedInfos[] = $contact_town;
1868 } elseif (!empty($company_town)) {
1869 $extendedInfos[] = $company_town;
1870 }
1871 $extendedInfos = implode(' - ', $extendedInfos);
1872 if (!empty($extendedInfos)) {
1873 $extendedInfos = ' - ' . $extendedInfos;
1874 }
1875 }
1876
1877 $contactstatic->id = $obj->rowid;
1878 $contactstatic->lastname = $obj->lastname;
1879 $contactstatic->firstname = $obj->firstname;
1880 if ($obj->statut == 1) {
1881 if ($htmlname != 'none') {
1882 $disabled = 0;
1883 if (is_array($exclude) && count($exclude) && in_array($obj->rowid, $exclude)) {
1884 $disabled = 1;
1885 }
1886 if (is_array($limitto) && count($limitto) && !in_array($obj->rowid, $limitto)) {
1887 $disabled = 1;
1888 }
1889 if (!empty($selected) && in_array($obj->rowid, $selected)) {
1890 $out .= '<option value="' . $obj->rowid . '"';
1891 if ($disabled) {
1892 $out .= ' disabled';
1893 }
1894 $out .= ' selected>';
1895 $out .= $contactstatic->getFullName($langs) . $extendedInfos;
1896 if ($showfunction && $obj->poste) {
1897 $out .= ' (' . $obj->poste . ')';
1898 }
1899 if (($showsoc > 0) && $obj->company) {
1900 $out .= ' - (' . $obj->company . ')';
1901 }
1902 $out .= '</option>';
1903 } else {
1904 $out .= '<option value="' . $obj->rowid . '"';
1905 if ($disabled) {
1906 $out .= ' disabled';
1907 }
1908 $out .= '>';
1909 $out .= $contactstatic->getFullName($langs) . $extendedInfos;
1910 if ($showfunction && $obj->poste) {
1911 $out .= ' (' . $obj->poste . ')';
1912 }
1913 if (($showsoc > 0) && $obj->company) {
1914 $out .= ' - (' . $obj->company . ')';
1915 }
1916 $out .= '</option>';
1917 }
1918 } else {
1919 if (in_array($obj->rowid, $selected)) {
1920 $out .= $contactstatic->getFullName($langs) . $extendedInfos;
1921 if ($showfunction && $obj->poste) {
1922 $out .= ' (' . $obj->poste . ')';
1923 }
1924 if (($showsoc > 0) && $obj->company) {
1925 $out .= ' - (' . $obj->company . ')';
1926 }
1927 }
1928 }
1929 }
1930 $i++;
1931 }
1932 } else {
1933 $labeltoshow = ($socid != -1) ? ($langs->trans($socid ? "NoContactDefinedForThirdParty" : "NoContactDefined")) : $langs->trans('SelectAThirdPartyFirst');
1934 $out .= '<option class="disabled" value="-1"' . (($showempty == 2 || $multiple) ? '' : ' selected') . ' disabled="disabled">';
1935 $out .= $labeltoshow;
1936 $out .= '</option>';
1937 }
1938
1939 $parameters = array(
1940 'socid' => $socid,
1941 'htmlname' => $htmlname,
1942 'resql' => $resql,
1943 'out' => &$out,
1944 'showfunction' => $showfunction,
1945 'showsoc' => $showsoc,
1946 );
1947
1948 $reshook = $hookmanager->executeHooks('afterSelectContactOptions', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1949
1950 if ($htmlname != 'none' && !$options_only) {
1951 $out .= '</select>';
1952 }
1953
1954 if ($conf->use_javascript_ajax && !$forcecombo && !$options_only) {
1955 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1956 $out .= ajax_combobox($htmlid, $events, getDolGlobalString("CONTACT_USE_SEARCH_TO_SELECT"));
1957 }
1958
1959 $this->num = $num;
1960 return $out;
1961 } else {
1962 dol_print_error($this->db);
1963 return -1;
1964 }
1965 }
1966
1967 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1968
1984 public function select_users($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0')
1985 {
1986 // phpcs:enable
1987 print $this->select_dolusers($selected, $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity);
1988 }
1989
1990 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1991
2016 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)
2017 {
2018 // phpcs:enable
2019 global $conf, $user, $langs, $hookmanager;
2020 global $action;
2021
2022 // If no preselected user defined, we take current user
2023 if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) {
2024 $selected = $user->id;
2025 }
2026
2027 if ($selected === '') {
2028 $selected = array();
2029 } elseif (!is_array($selected)) {
2030 $selected = array($selected);
2031 }
2032
2033 $excludeUsers = null;
2034 $includeUsers = null;
2035
2036 // Exclude some users
2037 if (is_array($exclude)) {
2038 $excludeUsers = implode(",", $exclude);
2039 }
2040 // Include some uses
2041 if (is_array($include)) {
2042 $includeUsers = implode(",", $include);
2043 } elseif ($include == 'hierarchy') {
2044 // Build list includeUsers to have only hierarchy
2045 $includeUsers = implode(",", $user->getAllChildIds(0));
2046 } elseif ($include == 'hierarchyme') {
2047 // Build list includeUsers to have only hierarchy and current user
2048 $includeUsers = implode(",", $user->getAllChildIds(1));
2049 }
2050
2051 $out = '';
2052 $outarray = array();
2053 $outarray2 = array();
2054
2055 // Forge request to select users
2056 $sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut as status, u.login, u.admin, u.entity, u.photo";
2057 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
2058 $sql .= ", e.label";
2059 }
2060 $sql .= " FROM " . $this->db->prefix() . "user as u";
2061 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
2062 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid = u.entity";
2063 if (!empty($force_entity)) {
2064 $sql .= " WHERE u.entity IN (0, " . $this->db->sanitize($force_entity) . ")";
2065 } else {
2066 $sql .= " WHERE u.entity IS NOT NULL";
2067 }
2068 } else {
2069 if (isModEnabled('multicompany') && getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE')) {
2070 $sql .= " WHERE u.rowid IN (SELECT ug.fk_user FROM ".$this->db->prefix()."usergroup_user as ug WHERE ug.entity IN (".getEntity('usergroup')."))";
2071 } else {
2072 $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
2073 }
2074 }
2075 if (!empty($user->socid)) {
2076 $sql .= " AND u.fk_soc = " . ((int) $user->socid);
2077 }
2078 if (is_array($exclude) && $excludeUsers) {
2079 $sql .= " AND u.rowid NOT IN (" . $this->db->sanitize($excludeUsers) . ")";
2080 }
2081 if ($includeUsers) {
2082 $sql .= " AND u.rowid IN (" . $this->db->sanitize($includeUsers) . ")";
2083 }
2084 if (getDolGlobalString('USER_HIDE_INACTIVE_IN_COMBOBOX') || $notdisabled) {
2085 $sql .= " AND u.statut <> 0";
2086 }
2087 if (!empty($morefilter)) {
2088 $sql .= " " . $morefilter;
2089 }
2090
2091 //Add hook to filter on user (for exemple on usergroup define in custom modules)
2092 $reshook = $hookmanager->executeHooks('addSQLWhereFilterOnSelectUsers', array(), $this, $action);
2093 if (!empty($reshook)) {
2094 $sql .= $hookmanager->resPrint;
2095 }
2096
2097 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) { // MAIN_FIRSTNAME_NAME_POSITION is 0 means firstname+lastname
2098 $sql .= " ORDER BY u.statut DESC, u.firstname ASC, u.lastname ASC";
2099 } else {
2100 $sql .= " ORDER BY u.statut DESC, u.lastname ASC, u.firstname ASC";
2101 }
2102
2103 dol_syslog(get_class($this) . "::select_dolusers", LOG_DEBUG);
2104
2105 $resql = $this->db->query($sql);
2106 if ($resql) {
2107 $num = $this->db->num_rows($resql);
2108 $i = 0;
2109 if ($num) {
2110 // do not use maxwidthonsmartphone by default. Set it by caller so auto size to 100% will work when not defined
2111 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : ' minwidth200') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
2112 if ($show_empty && !$multiple) {
2113 $textforempty = ' ';
2114 if (!empty($conf->use_javascript_ajax)) {
2115 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
2116 }
2117 if (!is_numeric($show_empty)) {
2118 $textforempty = $show_empty;
2119 }
2120 $out .= '<option class="optiongrey" value="' . ($show_empty < 0 ? $show_empty : -1) . '"' . ((empty($selected) || in_array(-1, $selected)) ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
2121 }
2122 if ($show_every) {
2123 $out .= '<option value="-2"' . ((in_array(-2, $selected)) ? ' selected' : '') . '>-- ' . $langs->trans("Everybody") . ' --</option>' . "\n";
2124 }
2125
2126 $userstatic = new User($this->db);
2127
2128 while ($i < $num) {
2129 $obj = $this->db->fetch_object($resql);
2130
2131 $userstatic->id = $obj->rowid;
2132 $userstatic->lastname = $obj->lastname;
2133 $userstatic->firstname = $obj->firstname;
2134 $userstatic->photo = $obj->photo;
2135 $userstatic->statut = $obj->status;
2136 $userstatic->entity = $obj->entity;
2137 $userstatic->admin = $obj->admin;
2138
2139 $disableline = '';
2140 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
2141 $disableline = ($enableonlytext ? $enableonlytext : '1');
2142 }
2143
2144 $labeltoshow = '';
2145 $labeltoshowhtml = '';
2146
2147 // $fullNameMode is 0=Lastname+Firstname (MAIN_FIRSTNAME_NAME_POSITION=1), 1=Firstname+Lastname (MAIN_FIRSTNAME_NAME_POSITION=0)
2148 $fullNameMode = 0;
2149 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) {
2150 $fullNameMode = 1; //Firstname+lastname
2151 }
2152 $labeltoshow .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2153 $labeltoshowhtml .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2154 if (empty($obj->firstname) && empty($obj->lastname)) {
2155 $labeltoshow .= $obj->login;
2156 $labeltoshowhtml .= $obj->login;
2157 }
2158
2159 // Complete name with a more info string like: ' (info1 - info2 - ...)'
2160 $moreinfo = '';
2161 $moreinfohtml = '';
2162 if (getDolGlobalString('MAIN_SHOW_LOGIN')) {
2163 $moreinfo .= ($moreinfo ? ' - ' : ' (');
2164 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(');
2165 $moreinfo .= $obj->login;
2166 $moreinfohtml .= $obj->login;
2167 }
2168 if ($showstatus >= 0) {
2169 if ($obj->status == 1 && $showstatus == 1) {
2170 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Enabled');
2171 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Enabled');
2172 }
2173 if ($obj->status == 0 && $showstatus == 1) {
2174 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Disabled');
2175 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Disabled');
2176 }
2177 }
2178 if (isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1 && !empty($user->admin) && empty($user->entity)) {
2179 if (empty($obj->entity)) {
2180 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans("AllEntities");
2181 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans("AllEntities");
2182 } else {
2183 if ($obj->entity != $conf->entity) {
2184 $moreinfo .= ($moreinfo ? ' - ' : ' (') . ($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2185 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . ($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2186 }
2187 }
2188 }
2189 $moreinfo .= (!empty($moreinfo) ? ')' : '');
2190 $moreinfohtml .= (!empty($moreinfohtml) ? ')</span>' : '');
2191 if (!empty($disableline) && $disableline != '1') {
2192 // Add text from $enableonlytext parameter
2193 $moreinfo .= ' - ' . $disableline;
2194 $moreinfohtml .= ' - ' . $disableline;
2195 }
2196 $labeltoshow .= $moreinfo;
2197 $labeltoshowhtml .= $moreinfohtml;
2198
2199 $out .= '<option value="' . $obj->rowid . '"';
2200 if (!empty($disableline)) {
2201 $out .= ' disabled';
2202 }
2203 if ((is_object($selected) && $selected->id == $obj->rowid) || (!is_object($selected) && in_array($obj->rowid, $selected))) {
2204 $out .= ' selected';
2205 }
2206 $out .= ' data-html="';
2207 $outhtml = $userstatic->getNomUrl(-3, '', 0, 1, 24, 1, 'login', '', 1) . ' ';
2208 if ($showstatus >= 0 && $obj->status == 0) {
2209 $outhtml .= '<strike class="opacitymediumxxx">';
2210 }
2211 $outhtml .= $labeltoshowhtml;
2212 if ($showstatus >= 0 && $obj->status == 0) {
2213 $outhtml .= '</strike>';
2214 }
2215 $out .= dol_escape_htmltag($outhtml);
2216 $out .= '">';
2217 $out .= $labeltoshow;
2218 $out .= '</option>';
2219
2220 $outarray[$userstatic->id] = $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength) . $moreinfo;
2221 $outarray2[$userstatic->id] = array(
2222 'id'=>$userstatic->id,
2223 'label'=>$labeltoshow,
2224 'labelhtml'=>$labeltoshowhtml,
2225 'color'=>'',
2226 'picto'=>''
2227 );
2228
2229 $i++;
2230 }
2231 } else {
2232 $out .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '" disabled>';
2233 $out .= '<option value="">' . $langs->trans("None") . '</option>';
2234 }
2235 $out .= '</select>';
2236
2237 if ($num && !$forcecombo) {
2238 // Enhance with select2
2239 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2240 $out .= ajax_combobox($htmlname);
2241 }
2242 } else {
2243 dol_print_error($this->db);
2244 }
2245
2246 if ($outputmode == 2) {
2247 return $outarray2;
2248 } elseif ($outputmode) {
2249 return $outarray;
2250 }
2251
2252 return $out;
2253 }
2254
2255
2256 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2279 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())
2280 {
2281 // phpcs:enable
2282 global $langs;
2283
2284 $userstatic = new User($this->db);
2285 $out = '';
2286
2287 $assignedtouser = array();
2288 if (!empty($_SESSION['assignedtouser'])) {
2289 $assignedtouser = json_decode($_SESSION['assignedtouser'], true);
2290 }
2291 $nbassignetouser = count($assignedtouser);
2292
2293 //if ($nbassignetouser && $action != 'view') $out .= '<br>';
2294 if ($nbassignetouser) {
2295 $out .= '<ul class="attendees">';
2296 }
2297 $i = 0;
2298 $ownerid = 0;
2299 foreach ($assignedtouser as $key => $value) {
2300 if ($value['id'] == $ownerid) {
2301 continue;
2302 }
2303
2304 $out .= '<li>';
2305 $userstatic->fetch($value['id']);
2306 $out .= $userstatic->getNomUrl(-1);
2307 if ($i == 0) {
2308 $ownerid = $value['id'];
2309 $out .= ' (' . $langs->trans("Owner") . ')';
2310 }
2311 if ($nbassignetouser > 1 && $action != 'view') {
2312 $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 . '">';
2313 }
2314 // Show my availability
2315 if ($showproperties) {
2316 if ($ownerid == $value['id'] && is_array($listofuserid) && count($listofuserid) && in_array($ownerid, array_keys($listofuserid))) {
2317 $out .= '<div class="myavailability inline-block">';
2318 $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>';
2319 $out .= '</div>';
2320 }
2321 }
2322 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2323 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2324
2325 $out .= '</li>';
2326 $i++;
2327 }
2328 if ($nbassignetouser) {
2329 $out .= '</ul>';
2330 }
2331
2332 // Method with no ajax
2333 if ($action != 'view') {
2334 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassigned" value="">';
2335 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2336 $out .= 'jQuery(".removedassigned").click(function() { jQuery(".removedassignedhidden").val(jQuery(this).val()); });';
2337 $out .= 'jQuery(".assignedtouser").change(function() { console.log(jQuery(".assignedtouser option:selected").val());';
2338 $out .= ' if (jQuery(".assignedtouser option:selected").val() > 0) { jQuery("#' . $action . 'assignedtouser").attr("disabled", false); }';
2339 $out .= ' else { jQuery("#' . $action . 'assignedtouser").attr("disabled", true); }';
2340 $out .= '});';
2341 $out .= '})</script>';
2342 $out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2343 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtouser" name="' . $action . 'assignedtouser" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2344 $out .= '<br>';
2345 }
2346
2347 return $out;
2348 }
2349
2350 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2370 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())
2371 {
2372 // phpcs:enable
2373 global $langs;
2374
2375 require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php';
2376 require_once DOL_DOCUMENT_ROOT.'/resource/class/dolresource.class.php';
2377 $formresources = new FormResource($this->db);
2378 $resourcestatic = new Dolresource($this->db);
2379
2380 $out = '';
2381 $assignedtoresource = array();
2382 if (!empty($_SESSION['assignedtoresource'])) {
2383 $assignedtoresource = json_decode($_SESSION['assignedtoresource'], true);
2384 }
2385 $nbassignetoresource = count($assignedtoresource);
2386
2387 //if ($nbassignetoresource && $action != 'view') $out .= '<br>';
2388 if ($nbassignetoresource) {
2389 $out .= '<ul class="attendees">';
2390 }
2391 $i = 0;
2392
2393 foreach ($assignedtoresource as $key => $value) {
2394 $out .= '<li>';
2395 $resourcestatic->fetch($value['id']);
2396 $out .= $resourcestatic->getNomUrl(-1);
2397 if ($nbassignetoresource > 1 && $action != 'view') {
2398 $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 . '">';
2399 }
2400 // Show my availability
2401 if ($showproperties) {
2402 if (is_array($listofresourceid) && count($listofresourceid)) {
2403 $out .= '<div class="myavailability inline-block">';
2404 $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>';
2405 $out .= '</div>';
2406 }
2407 }
2408 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2409 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2410
2411 $out .= '</li>';
2412 $i++;
2413 }
2414 if ($nbassignetoresource) {
2415 $out .= '</ul>';
2416 }
2417
2418 // Method with no ajax
2419 if ($action != 'view') {
2420 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassignedresource" value="">';
2421 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2422 $out .= 'jQuery(".removedassignedresource").click(function() { jQuery(".removedassignedresourcehidden").val(jQuery(this).val()); });';
2423 $out .= 'jQuery(".assignedtoresource").change(function() { console.log(jQuery(".assignedtoresource option:selected").val());';
2424 $out .= ' if (jQuery(".assignedtoresource option:selected").val() > 0) { jQuery("#' . $action . 'assignedtoresource").attr("disabled", false); }';
2425 $out .= ' else { jQuery("#' . $action . 'assignedtoresource").attr("disabled", true); }';
2426 $out .= '});';
2427 $out .= '})</script>';
2428
2429 $events = array();
2430 $out .= img_picto('', 'resource', 'class="pictofixedwidth"');
2431 $out .= $formresources->select_resource_list('', $htmlname, '', 1, 1, 0, $events, '', 2, null);
2432 //$out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2433 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtoresource" name="' . $action . 'assignedtoresource" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2434 $out .= '<br>';
2435 }
2436
2437 return $out;
2438 }
2439
2440 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2441
2469 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)
2470 {
2471 // phpcs:enable
2472 global $langs, $conf;
2473
2474 $out = '';
2475
2476 // check parameters
2477 $price_level = (!empty($price_level) ? $price_level : 0);
2478 if (is_null($ajaxoptions)) {
2479 $ajaxoptions = array();
2480 }
2481
2482 if (strval($filtertype) === '' && (isModEnabled("product") || isModEnabled("service"))) {
2483 if (isModEnabled("product") && !isModEnabled('service')) {
2484 $filtertype = '0';
2485 } elseif (!isModEnabled('product') && isModEnabled("service")) {
2486 $filtertype = '1';
2487 }
2488 }
2489
2490 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
2491 $placeholder = '';
2492
2493 if ($selected && empty($selected_input_value)) {
2494 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2495 $producttmpselect = new Product($this->db);
2496 $producttmpselect->fetch($selected);
2497 $selected_input_value = $producttmpselect->ref;
2498 unset($producttmpselect);
2499 }
2500 // handle case where product or service module is disabled + no filter specified
2501 if ($filtertype == '') {
2502 if (!isModEnabled('product')) { // when product module is disabled, show services only
2503 $filtertype = 1;
2504 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
2505 $filtertype = 0;
2506 }
2507 }
2508 // mode=1 means customers products
2509 $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;
2510 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
2511
2512 if (isModEnabled('variants') && is_array($selected_combinations)) {
2513 // Code to automatically insert with javascript the select of attributes under the select of product
2514 // when a parent of variant has been selected.
2515 $out .= '
2516 <!-- script to auto show attributes select tags if a variant was selected -->
2517 <script nonce="' . getNonce() . '">
2518 // auto show attributes fields
2519 selected = ' . json_encode($selected_combinations) . ';
2520 combvalues = {};
2521
2522 jQuery(document).ready(function () {
2523
2524 jQuery("input[name=\'prod_entry_mode\']").change(function () {
2525 if (jQuery(this).val() == \'free\') {
2526 jQuery(\'div#attributes_box\').empty();
2527 }
2528 });
2529
2530 jQuery("input#' . $htmlname . '").change(function () {
2531
2532 if (!jQuery(this).val()) {
2533 jQuery(\'div#attributes_box\').empty();
2534 return;
2535 }
2536
2537 console.log("A change has started. We get variants fields to inject html select");
2538
2539 jQuery.getJSON("' . DOL_URL_ROOT . '/variants/ajax/getCombinations.php", {
2540 id: jQuery(this).val()
2541 }, function (data) {
2542 jQuery(\'div#attributes_box\').empty();
2543
2544 jQuery.each(data, function (key, val) {
2545
2546 combvalues[val.id] = val.values;
2547
2548 var span = jQuery(document.createElement(\'div\')).css({
2549 \'display\': \'table-row\'
2550 });
2551
2552 span.append(
2553 jQuery(document.createElement(\'div\')).text(val.label).css({
2554 \'font-weight\': \'bold\',
2555 \'display\': \'table-cell\'
2556 })
2557 );
2558
2559 var html = jQuery(document.createElement(\'select\')).attr(\'name\', \'combinations[\' + val.id + \']\').css({
2560 \'margin-left\': \'15px\',
2561 \'white-space\': \'pre\'
2562 }).append(
2563 jQuery(document.createElement(\'option\')).val(\'\')
2564 );
2565
2566 jQuery.each(combvalues[val.id], function (key, val) {
2567 var tag = jQuery(document.createElement(\'option\')).val(val.id).html(val.value);
2568
2569 if (selected[val.fk_product_attribute] == val.id) {
2570 tag.attr(\'selected\', \'selected\');
2571 }
2572
2573 html.append(tag);
2574 });
2575
2576 span.append(html);
2577 jQuery(\'div#attributes_box\').append(span);
2578 });
2579 })
2580 });
2581
2582 ' . ($selected ? 'jQuery("input#' . $htmlname . '").change();' : '') . '
2583 });
2584 </script>
2585 ';
2586 }
2587
2588 if (empty($hidelabel)) {
2589 $out .= $langs->trans("RefOrLabel") . ' : ';
2590 } elseif ($hidelabel > 1) {
2591 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
2592 if ($hidelabel == 2) {
2593 $out .= img_picto($langs->trans("Search"), 'search');
2594 }
2595 }
2596 $out .= '<input type="text" class="minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
2597 if ($hidelabel == 3) {
2598 $out .= img_picto($langs->trans("Search"), 'search');
2599 }
2600 } else {
2601 $out .= $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus, $status_purchase);
2602 }
2603
2604 if (empty($nooutput)) {
2605 print $out;
2606 } else {
2607 return $out;
2608 }
2609 }
2610
2611 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2612
2628 public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 0, $showempty = '1', $morecss = '', $nooutput = '', $forcecombo = 0, $TProducts = [])
2629 {
2630 // phpcs:enable
2631 global $conf, $user, $langs, $db;
2632
2633 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2634
2635 $error = 0;
2636 $out = '';
2637
2638 if (!$forcecombo) {
2639 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2640 $events = array();
2641 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
2642 }
2643
2644 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
2645
2646 $sql = 'SELECT b.rowid, b.ref, b.label, b.fk_product';
2647 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'bom_bom as b';
2648 $sql .= ' WHERE b.entity IN (' . getEntity('bom') . ')';
2649 if (!empty($status)) {
2650 $sql .= ' AND status = ' . (int) $status;
2651 }
2652 if (!empty($type)) {
2653 $sql .= ' AND bomtype = ' . (int) $type;
2654 }
2655 if (!empty($TProducts)) {
2656 $sql .= ' AND fk_product IN (' . $this->db->sanitize(implode(',', $TProducts)) . ')';
2657 }
2658 if (!empty($limit)) {
2659 $sql .= ' LIMIT ' . (int) $limit;
2660 }
2661 $resql = $db->query($sql);
2662 if ($resql) {
2663 if ($showempty) {
2664 $out .= '<option value="-1"';
2665 if (empty($selected)) {
2666 $out .= ' selected';
2667 }
2668 $out .= '>&nbsp;</option>';
2669 }
2670 while ($obj = $db->fetch_object($resql)) {
2671 $product = new Product($db);
2672 $res = $product->fetch($obj->fk_product);
2673 $out .= '<option value="' . $obj->rowid . '"';
2674 if ($obj->rowid == $selected) {
2675 $out .= 'selected';
2676 }
2677 $out .= '>' . $obj->ref . ' - ' . $product->label . ' - ' . $obj->label . '</option>';
2678 }
2679 } else {
2680 $error++;
2681 dol_print_error($db);
2682 }
2683 $out .= '</select>';
2684 if (empty($nooutput)) {
2685 print $out;
2686 } else {
2687 return $out;
2688 }
2689 }
2690
2691 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2692
2718 public function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $status_purchase = -1)
2719 {
2720 // phpcs:enable
2721 global $langs, $conf;
2722 global $hookmanager;
2723
2724 $out = '';
2725 $outarray = array();
2726
2727 // Units
2728 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2729 $langs->load('other');
2730 }
2731
2732 $warehouseStatusArray = array();
2733 if (!empty($warehouseStatus)) {
2734 require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
2735 if (preg_match('/warehouseclosed/', $warehouseStatus)) {
2736 $warehouseStatusArray[] = Entrepot::STATUS_CLOSED;
2737 }
2738 if (preg_match('/warehouseopen/', $warehouseStatus)) {
2739 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL;
2740 }
2741 if (preg_match('/warehouseinternal/', $warehouseStatus)) {
2742 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL;
2743 }
2744 }
2745
2746 $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";
2747 if (count($warehouseStatusArray)) {
2748 $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
2749 } else {
2750 $selectFieldsGrouped = ", " . $this->db->ifsql("p.stock IS NULL", 0, "p.stock") . " AS stock";
2751 }
2752
2753 $sql = "SELECT ";
2754
2755 // Add select from hooks
2756 $parameters = array();
2757 $reshook = $hookmanager->executeHooks('selectProductsListSelect', $parameters); // Note that $action and $object may have been modified by hook
2758 if (empty($reshook)) {
2759 $sql .= $selectFields.$selectFieldsGrouped.$hookmanager->resPrint;
2760 } else {
2761 $sql .= $hookmanager->resPrint;
2762 }
2763
2764 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
2765 //Product category
2766 $sql .= ", (SELECT " . $this->db->prefix() . "categorie_product.fk_categorie
2767 FROM " . $this->db->prefix() . "categorie_product
2768 WHERE " . $this->db->prefix() . "categorie_product.fk_product=p.rowid
2769 LIMIT 1
2770 ) AS categorie_product_id ";
2771 }
2772
2773 //Price by customer
2774 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2775 $sql .= ', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
2776 $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';
2777 $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custdefault_vat_code, custref";
2778 }
2779 // Units
2780 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2781 $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";
2782 $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';
2783 }
2784
2785 // Multilang : we add translation
2786 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2787 $sql .= ", pl.label as label_translated";
2788 $sql .= ", pl.description as description_translated";
2789 $selectFields .= ", label_translated";
2790 $selectFields .= ", description_translated";
2791 }
2792 // Price by quantity
2793 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2794 $sql .= ", (SELECT pp.rowid FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid";
2795 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2796 $sql .= " AND price_level = " . ((int) $price_level);
2797 }
2798 $sql .= " ORDER BY date_price";
2799 $sql .= " DESC LIMIT 1) as price_rowid";
2800 $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
2801 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2802 $sql .= " AND price_level = " . ((int) $price_level);
2803 }
2804 $sql .= " ORDER BY date_price";
2805 $sql .= " DESC LIMIT 1) as price_by_qty";
2806 $selectFields .= ", price_rowid, price_by_qty";
2807 }
2808
2809 $sql .= " FROM ".$this->db->prefix()."product as p";
2810 // Add from (left join) from hooks
2811 $parameters = array();
2812 $reshook = $hookmanager->executeHooks('selectProductsListFrom', $parameters); // Note that $action and $object may have been modified by hook
2813 $sql .= $hookmanager->resPrint;
2814
2815 if (count($warehouseStatusArray)) {
2816 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_stock as ps on ps.fk_product = p.rowid";
2817 $sql .= " LEFT JOIN " . $this->db->prefix() . "entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (" . getEntity('stock') . ")";
2818 $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.
2819 }
2820
2821 // include search in supplier ref
2822 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
2823 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
2824 }
2825
2826 //Price by customer
2827 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2828 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_customer_price as pcp ON pcp.fk_soc=" . ((int) $socid) . " AND pcp.fk_product=p.rowid";
2829 }
2830 // Units
2831 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2832 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
2833 }
2834 // Multilang : we add translation
2835 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2836 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_lang as pl ON pl.fk_product = p.rowid ";
2837 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE') && !empty($socid)) {
2838 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
2839 $soc = new Societe($this->db);
2840 $result = $soc->fetch($socid);
2841 if ($result > 0 && !empty($soc->default_lang)) {
2842 $sql .= " AND pl.lang = '" . $this->db->escape($soc->default_lang) . "'";
2843 } else {
2844 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
2845 }
2846 } else {
2847 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
2848 }
2849 }
2850
2851 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
2852 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_attribute_combination pac ON pac.fk_product_child = p.rowid";
2853 }
2854
2855 $sql .= ' WHERE p.entity IN (' . getEntity('product') . ')';
2856
2857 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
2858 $sql .= " AND pac.rowid IS NULL";
2859 }
2860
2861 if ($finished == 0) {
2862 $sql .= " AND p.finished = " . ((int) $finished);
2863 } elseif ($finished == 1) {
2864 $sql .= " AND p.finished = ".((int) $finished);
2865 }
2866 if ($status >= 0) {
2867 $sql .= " AND p.tosell = ".((int) $status);
2868 }
2869 if ($status_purchase >= 0) {
2870 $sql .= " AND p.tobuy = " . ((int) $status_purchase);
2871 }
2872 // Filter by product type
2873 if (strval($filtertype) != '') {
2874 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
2875 } elseif (!isModEnabled('product')) { // when product module is disabled, show services only
2876 $sql .= " AND p.fk_product_type = 1";
2877 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
2878 $sql .= " AND p.fk_product_type = 0";
2879 }
2880 // Add where from hooks
2881 $parameters = array();
2882 $reshook = $hookmanager->executeHooks('selectProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
2883 $sql .= $hookmanager->resPrint;
2884 // Add criteria on ref/label
2885 if ($filterkey != '') {
2886 $sql .= ' AND (';
2887 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
2888 // For natural search
2889 $scrit = explode(' ', $filterkey);
2890 $i = 0;
2891 if (count($scrit) > 1) {
2892 $sql .= "(";
2893 }
2894 foreach ($scrit as $crit) {
2895 if ($i > 0) {
2896 $sql .= " AND ";
2897 }
2898 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2899 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2900 $sql .= " OR pl.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2901 }
2902 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2903 $sql .= " OR pcp.ref_customer LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2904 }
2905 if (getDolGlobalString('PRODUCT_AJAX_SEARCH_ON_DESCRIPTION')) {
2906 $sql .= " OR p.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2907 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2908 $sql .= " OR pl.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2909 }
2910 }
2911 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
2912 $sql .= " OR pfp.ref_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2913 }
2914 $sql .= ")";
2915 $i++;
2916 }
2917 if (count($scrit) > 1) {
2918 $sql .= ")";
2919 }
2920 if (isModEnabled('barcode')) {
2921 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
2922 }
2923 $sql .= ')';
2924 }
2925 if (count($warehouseStatusArray)) {
2926 $sql .= " GROUP BY " . $selectFields;
2927 }
2928
2929 //Sort by category
2930 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
2931 $sql .= " ORDER BY categorie_product_id ";
2932 //ASC OR DESC order
2933 (getDolGlobalInt('PRODUCT_SORT_BY_CATEGORY') == 1) ? $sql .= "ASC" : $sql .= "DESC";
2934 } else {
2935 $sql .= $this->db->order("p.ref");
2936 }
2937
2938 $sql .= $this->db->plimit($limit, 0);
2939
2940 // Build output string
2941 dol_syslog(get_class($this) . "::select_produits_list search products", LOG_DEBUG);
2942 $result = $this->db->query($sql);
2943 if ($result) {
2944 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2945 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
2946 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
2947
2948 $num = $this->db->num_rows($result);
2949
2950 $events = null;
2951
2952 if (!$forcecombo) {
2953 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2954 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
2955 }
2956
2957 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
2958
2959 $textifempty = '';
2960 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
2961 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
2962 if (getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
2963 if ($showempty && !is_numeric($showempty)) {
2964 $textifempty = $langs->trans($showempty);
2965 } else {
2966 $textifempty .= $langs->trans("All");
2967 }
2968 } else {
2969 if ($showempty && !is_numeric($showempty)) {
2970 $textifempty = $langs->trans($showempty);
2971 }
2972 }
2973 if ($showempty) {
2974 $out .= '<option value="-1" selected>' . ($textifempty ? $textifempty : '&nbsp;') . '</option>';
2975 }
2976
2977 $i = 0;
2978 while ($num && $i < $num) {
2979 $opt = '';
2980 $optJson = array();
2981 $objp = $this->db->fetch_object($result);
2982
2983 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
2984 $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type";
2985 $sql .= " FROM " . $this->db->prefix() . "product_price_by_qty";
2986 $sql .= " WHERE fk_product_price = " . ((int) $objp->price_rowid);
2987 $sql .= " ORDER BY quantity ASC";
2988
2989 dol_syslog(get_class($this) . "::select_produits_list search prices by qty", LOG_DEBUG);
2990 $result2 = $this->db->query($sql);
2991 if ($result2) {
2992 $nb_prices = $this->db->num_rows($result2);
2993 $j = 0;
2994 while ($nb_prices && $j < $nb_prices) {
2995 $objp2 = $this->db->fetch_object($result2);
2996
2997 $objp->price_by_qty_rowid = $objp2->rowid;
2998 $objp->price_by_qty_price_base_type = $objp2->price_base_type;
2999 $objp->price_by_qty_quantity = $objp2->quantity;
3000 $objp->price_by_qty_unitprice = $objp2->unitprice;
3001 $objp->price_by_qty_remise_percent = $objp2->remise_percent;
3002 // For backward compatibility
3003 $objp->quantity = $objp2->quantity;
3004 $objp->price = $objp2->price;
3005 $objp->unitprice = $objp2->unitprice;
3006 $objp->remise_percent = $objp2->remise_percent;
3007
3008 //$objp->tva_tx is not overwritten by $objp2 value
3009 //$objp->default_vat_code is not overwritten by $objp2 value
3010
3011 $this->constructProductListOption($objp, $opt, $optJson, 0, $selected, $hidepriceinlabel, $filterkey);
3012
3013 $j++;
3014
3015 // Add new entry
3016 // "key" value of json key array is used by jQuery automatically as selected value
3017 // "label" value of json key array is used by jQuery automatically as text for combo box
3018 $out .= $opt;
3019 array_push($outarray, $optJson);
3020 }
3021 }
3022 } else {
3023 if (isModEnabled('dynamicprices') && !empty($objp->fk_price_expression)) {
3024 $price_product = new Product($this->db);
3025 $price_product->fetch($objp->rowid, '', '', 1);
3026
3027 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3028 $priceparser = new PriceParser($this->db);
3029 $price_result = $priceparser->parseProduct($price_product);
3030 if ($price_result >= 0) {
3031 $objp->price = $price_result;
3032 $objp->unitprice = $price_result;
3033 //Calculate the VAT
3034 $objp->price_ttc = price2num($objp->price) * (1 + ($objp->tva_tx / 100));
3035 $objp->price_ttc = price2num($objp->price_ttc, 'MU');
3036 }
3037 }
3038
3039 $this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected, $hidepriceinlabel, $filterkey);
3040 // Add new entry
3041 // "key" value of json key array is used by jQuery automatically as selected value
3042 // "label" value of json key array is used by jQuery automatically as text for combo box
3043 $out .= $opt;
3044 array_push($outarray, $optJson);
3045 }
3046
3047 $i++;
3048 }
3049
3050 $out .= '</select>';
3051
3052 $this->db->free($result);
3053
3054 if (empty($outputmode)) {
3055 return $out;
3056 }
3057
3058 return $outarray;
3059 } else {
3060 dol_print_error($this->db);
3061 }
3062
3063 return '';
3064 }
3065
3081 protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0)
3082 {
3083 global $langs, $conf, $user;
3084 global $hookmanager;
3085
3086 $outkey = '';
3087 $outval = '';
3088 $outref = '';
3089 $outlabel = '';
3090 $outlabel_translated = '';
3091 $outdesc = '';
3092 $outdesc_translated = '';
3093 $outbarcode = '';
3094 $outorigin = '';
3095 $outtype = '';
3096 $outprice_ht = '';
3097 $outprice_ttc = '';
3098 $outpricebasetype = '';
3099 $outtva_tx = '';
3100 $outdefault_vat_code = '';
3101 $outqty = 1;
3102 $outdiscount = 0;
3103
3104 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3105
3106 $label = $objp->label;
3107 if (!empty($objp->label_translated)) {
3108 $label = $objp->label_translated;
3109 }
3110 if (!empty($filterkey) && $filterkey != '') {
3111 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3112 }
3113
3114 $outkey = $objp->rowid;
3115 $outref = $objp->ref;
3116 $outrefcust = empty($objp->custref) ? '' : $objp->custref;
3117 $outlabel = $objp->label;
3118 $outdesc = $objp->description;
3119 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3120 $outlabel_translated = $objp->label_translated;
3121 $outdesc_translated = $objp->description_translated;
3122 }
3123 $outbarcode = $objp->barcode;
3124 $outorigin = $objp->fk_country;
3125 $outpbq = empty($objp->price_by_qty_rowid) ? '' : $objp->price_by_qty_rowid;
3126
3127 $outtype = $objp->fk_product_type;
3128 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3129 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3130
3131 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3132 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
3133 }
3134
3135 // Units
3136 $outvalUnits = '';
3137 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3138 if (!empty($objp->unit_short)) {
3139 $outvalUnits .= ' - ' . $objp->unit_short;
3140 }
3141 }
3142 if (getDolGlobalString('PRODUCT_SHOW_DIMENSIONS_IN_COMBO')) {
3143 if (!empty($objp->weight) && $objp->weight_units !== null) {
3144 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3145 $outvalUnits .= ' - ' . $unitToShow;
3146 }
3147 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3148 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3149 $outvalUnits .= ' - ' . $unitToShow;
3150 }
3151 if (!empty($objp->surface) && $objp->surface_units !== null) {
3152 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3153 $outvalUnits .= ' - ' . $unitToShow;
3154 }
3155 if (!empty($objp->volume) && $objp->volume_units !== null) {
3156 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3157 $outvalUnits .= ' - ' . $unitToShow;
3158 }
3159 }
3160 if ($outdurationvalue && $outdurationunit) {
3161 $da = array(
3162 'h' => $langs->trans('Hour'),
3163 'd' => $langs->trans('Day'),
3164 'w' => $langs->trans('Week'),
3165 'm' => $langs->trans('Month'),
3166 'y' => $langs->trans('Year')
3167 );
3168 if (isset($da[$outdurationunit])) {
3169 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3170 }
3171 }
3172
3173 $opt = '<option value="' . $objp->rowid . '"';
3174 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
3175 if (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0) {
3176 $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 . '"';
3177 }
3178 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3179 if ($user->hasRight('stock', 'lire')) {
3180 if ($objp->stock > 0) {
3181 $opt .= ' class="product_line_stock_ok"';
3182 } elseif ($objp->stock <= 0) {
3183 $opt .= ' class="product_line_stock_too_low"';
3184 }
3185 }
3186 }
3187 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
3188 $opt .= ' data-labeltrans="' . $outlabel_translated . '"';
3189 $opt .= ' data-desctrans="' . dol_escape_htmltag($outdesc_translated) . '"';
3190 }
3191 $opt .= '>';
3192 $opt .= $objp->ref;
3193 if (!empty($objp->custref)) {
3194 $opt .= ' (' . $objp->custref . ')';
3195 }
3196 if ($outbarcode) {
3197 $opt .= ' (' . $outbarcode . ')';
3198 }
3199 $opt .= ' - ' . dol_trunc($label, $maxlengtharticle);
3200 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3201 $opt .= ' (' . getCountry($outorigin, 1) . ')';
3202 }
3203
3204 $objRef = $objp->ref;
3205 if (!empty($objp->custref)) {
3206 $objRef .= ' (' . $objp->custref . ')';
3207 }
3208 if (!empty($filterkey) && $filterkey != '') {
3209 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3210 }
3211 $outval .= $objRef;
3212 if ($outbarcode) {
3213 $outval .= ' (' . $outbarcode . ')';
3214 }
3215 $outval .= ' - ' . dol_trunc($label, $maxlengtharticle);
3216 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3217 $outval .= ' (' . getCountry($outorigin, 1) . ')';
3218 }
3219
3220 // Units
3221 $opt .= $outvalUnits;
3222 $outval .= $outvalUnits;
3223
3224 $found = 0;
3225
3226 // Multiprice
3227 // If we need a particular price level (from 1 to n)
3228 if (empty($hidepriceinlabel) && $price_level >= 1 && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3229 $sql = "SELECT price, price_ttc, price_base_type, tva_tx, default_vat_code";
3230 $sql .= " FROM " . $this->db->prefix() . "product_price";
3231 $sql .= " WHERE fk_product = " . ((int) $objp->rowid);
3232 $sql .= " AND entity IN (" . getEntity('productprice') . ")";
3233 $sql .= " AND price_level = " . ((int) $price_level);
3234 $sql .= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid.
3235 $sql .= " LIMIT 1";
3236
3237 dol_syslog(get_class($this) . '::constructProductListOption search price for product ' . $objp->rowid . ' AND level ' . $price_level, LOG_DEBUG);
3238 $result2 = $this->db->query($sql);
3239 if ($result2) {
3240 $objp2 = $this->db->fetch_object($result2);
3241 if ($objp2) {
3242 $found = 1;
3243 if ($objp2->price_base_type == 'HT') {
3244 $opt .= ' - ' . price($objp2->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3245 $outval .= ' - ' . price($objp2->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3246 } else {
3247 $opt .= ' - ' . price($objp2->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3248 $outval .= ' - ' . price($objp2->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3249 }
3250 $outprice_ht = price($objp2->price);
3251 $outprice_ttc = price($objp2->price_ttc);
3252 $outpricebasetype = $objp2->price_base_type;
3253 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
3254 $outtva_tx = $objp2->tva_tx; // We use the vat rate on line of multiprice
3255 $outdefault_vat_code = $objp2->default_vat_code; // We use the vat code on line of multiprice
3256 } else {
3257 $outtva_tx = $objp->tva_tx; // We use the vat rate of product, not the one on line of multiprice
3258 $outdefault_vat_code = $objp->default_vat_code; // We use the vat code or product, not the one on line of multiprice
3259 }
3260 }
3261 } else {
3262 dol_print_error($this->db);
3263 }
3264 }
3265
3266 // Price by quantity
3267 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1 && (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3268 $found = 1;
3269 $outqty = $objp->quantity;
3270 $outdiscount = $objp->remise_percent;
3271 if ($objp->quantity == 1) {
3272 $opt .= ' - ' . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/";
3273 $outval .= ' - ' . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/";
3274 $opt .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3275 $outval .= $langs->transnoentities("Unit");
3276 } else {
3277 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3278 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3279 $opt .= $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3280 $outval .= $langs->transnoentities("Units");
3281 }
3282
3283 $outprice_ht = price($objp->unitprice);
3284 $outprice_ttc = price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
3285 $outpricebasetype = $objp->price_base_type;
3286 $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
3287 $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
3288 }
3289 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1) {
3290 $opt .= " (" . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3291 $outval .= " (" . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3292 }
3293 if (empty($hidepriceinlabel) && !empty($objp->remise_percent) && $objp->remise_percent >= 1) {
3294 $opt .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3295 $outval .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3296 }
3297
3298 // Price by customer
3299 if (empty($hidepriceinlabel) && getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
3300 if (!empty($objp->idprodcustprice)) {
3301 $found = 1;
3302
3303 if ($objp->custprice_base_type == 'HT') {
3304 $opt .= ' - ' . price($objp->custprice, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3305 $outval .= ' - ' . price($objp->custprice, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3306 } else {
3307 $opt .= ' - ' . price($objp->custprice_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3308 $outval .= ' - ' . price($objp->custprice_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3309 }
3310
3311 $outprice_ht = price($objp->custprice);
3312 $outprice_ttc = price($objp->custprice_ttc);
3313 $outpricebasetype = $objp->custprice_base_type;
3314 $outtva_tx = $objp->custtva_tx;
3315 $outdefault_vat_code = $objp->custdefault_vat_code;
3316 }
3317 }
3318
3319 // If level no defined or multiprice not found, we used the default price
3320 if (empty($hidepriceinlabel) && !$found) {
3321 if ($objp->price_base_type == 'HT') {
3322 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3323 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3324 } else {
3325 $opt .= ' - ' . price($objp->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3326 $outval .= ' - ' . price($objp->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3327 }
3328 $outprice_ht = price($objp->price);
3329 $outprice_ttc = price($objp->price_ttc);
3330 $outpricebasetype = $objp->price_base_type;
3331 $outtva_tx = $objp->tva_tx;
3332 $outdefault_vat_code = $objp->default_vat_code;
3333 }
3334
3335 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3336 if ($user->hasRight('stock', 'lire')) {
3337 $opt .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'), 0, $langs, 0, 0);
3338
3339 if ($objp->stock > 0) {
3340 $outval .= ' - <span class="product_line_stock_ok">';
3341 } elseif ($objp->stock <= 0) {
3342 $outval .= ' - <span class="product_line_stock_too_low">';
3343 }
3344 $outval .= $langs->transnoentities("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3345 $outval .= '</span>';
3346 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3347 $langs->load("stocks");
3348
3349 $tmpproduct = new Product($this->db);
3350 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3351 $tmpproduct->load_virtual_stock();
3352 $virtualstock = $tmpproduct->stock_theorique;
3353
3354 $opt .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3355
3356 $outval .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3357 if ($virtualstock > 0) {
3358 $outval .= '<span class="product_line_stock_ok">';
3359 } elseif ($virtualstock <= 0) {
3360 $outval .= '<span class="product_line_stock_too_low">';
3361 }
3362 $outval .= $virtualstock;
3363 $outval .= '</span>';
3364
3365 unset($tmpproduct);
3366 }
3367 }
3368 }
3369
3370 $parameters = array('objp'=>$objp);
3371 $reshook = $hookmanager->executeHooks('constructProductListOption', $parameters); // Note that $action and $object may have been modified by hook
3372 if (empty($reshook)) {
3373 $opt .= $hookmanager->resPrint;
3374 } else {
3375 $opt = $hookmanager->resPrint;
3376 }
3377
3378 $opt .= "</option>\n";
3379 $optJson = array(
3380 'key' => $outkey,
3381 'value' => $outref,
3382 'label' => $outval,
3383 'label2' => $outlabel,
3384 'desc' => $outdesc,
3385 'type' => $outtype,
3386 'price_ht' => price2num($outprice_ht),
3387 'price_ttc' => price2num($outprice_ttc),
3388 'price_ht_locale' => price(price2num($outprice_ht)),
3389 'price_ttc_locale' => price(price2num($outprice_ttc)),
3390 'pricebasetype' => $outpricebasetype,
3391 'tva_tx' => $outtva_tx,
3392 'default_vat_code' => $outdefault_vat_code,
3393 'qty' => $outqty,
3394 'discount' => $outdiscount,
3395 'duration_value' => $outdurationvalue,
3396 'duration_unit' => $outdurationunit,
3397 'pbq' => $outpbq,
3398 'labeltrans' => $outlabel_translated,
3399 'desctrans' => $outdesc_translated,
3400 'ref_customer' => $outrefcust
3401 );
3402 }
3403
3404 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3405
3421 public function select_produits_fournisseurs($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $ajaxoptions = array(), $hidelabel = 0, $alsoproductwithnosupplierprice = 0, $morecss = '', $placeholder = '')
3422 {
3423 // phpcs:enable
3424 global $langs, $conf;
3425 global $price_level, $status, $finished;
3426
3427 if (!isset($status)) {
3428 $status = 1;
3429 }
3430
3431 $selected_input_value = '';
3432 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3433 if ($selected > 0) {
3434 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3435 $producttmpselect = new Product($this->db);
3436 $producttmpselect->fetch($selected);
3437 $selected_input_value = $producttmpselect->ref;
3438 unset($producttmpselect);
3439 }
3440
3441 // mode=2 means suppliers products
3442 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=2&status=' . $status . '&finished=' . $finished . '&alsoproductwithnosupplierprice=' . $alsoproductwithnosupplierprice;
3443 print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
3444
3445 print($hidelabel ? '' : $langs->trans("RefOrLabel") . ' : ') . '<input type="text" class="minwidth300" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . $placeholder . '"' : '') . '>';
3446 } else {
3447 print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', $status, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder);
3448 }
3449 }
3450
3451 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3452
3471 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 = '')
3472 {
3473 // phpcs:enable
3474 global $langs, $conf, $user;
3475 global $hookmanager;
3476
3477 $out = '';
3478 $outarray = array();
3479
3480 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3481
3482 $langs->load('stocks');
3483 // Units
3484 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3485 $langs->load('other');
3486 }
3487
3488 $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,";
3489 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice";
3490 $sql .= ", pfp.multicurrency_code, pfp.multicurrency_unitprice";
3491 $sql .= ", pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.default_vat_code, pfp.fk_soc, s.nom as name";
3492 $sql .= ", pfp.supplier_reputation";
3493 // if we use supplier description of the products
3494 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3495 $sql .= ", pfp.desc_fourn as description";
3496 } else {
3497 $sql .= ", p.description";
3498 }
3499 // Units
3500 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3501 $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";
3502 }
3503 if (isModEnabled('barcode')) {
3504 $sql .= ", pfp.barcode";
3505 }
3506 $sql .= " FROM " . $this->db->prefix() . "product as p";
3507 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (" . getEntity('product') . ") )";
3508 if ($socid > 0) {
3509 $sql .= " AND pfp.fk_soc = " . ((int) $socid);
3510 }
3511 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3512 // Units
3513 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3514 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3515 }
3516 $sql .= " WHERE p.entity IN (" . getEntity('product') . ")";
3517 if ($statut != -1) {
3518 $sql .= " AND p.tobuy = " . ((int) $statut);
3519 }
3520 if (strval($filtertype) != '') {
3521 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3522 }
3523 if (!empty($filtre)) {
3524 $sql .= " " . $filtre;
3525 }
3526 // Add where from hooks
3527 $parameters = array();
3528 $reshook = $hookmanager->executeHooks('selectSuppliersProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3529 $sql .= $hookmanager->resPrint;
3530 // Add criteria on ref/label
3531 if ($filterkey != '') {
3532 $sql .= ' AND (';
3533 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3534 // For natural search
3535 $scrit = explode(' ', $filterkey);
3536 $i = 0;
3537 if (count($scrit) > 1) {
3538 $sql .= "(";
3539 }
3540 foreach ($scrit as $crit) {
3541 if ($i > 0) {
3542 $sql .= " AND ";
3543 }
3544 $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) . "%'";
3545 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3546 $sql .= " OR pfp.desc_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3547 }
3548 $sql .= ")";
3549 $i++;
3550 }
3551 if (count($scrit) > 1) {
3552 $sql .= ")";
3553 }
3554 if (isModEnabled('barcode')) {
3555 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3556 $sql .= " OR pfp.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3557 }
3558 $sql .= ')';
3559 }
3560 $sql .= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC";
3561 $sql .= $this->db->plimit($limit, 0);
3562
3563 // Build output string
3564
3565 dol_syslog(get_class($this) . "::select_produits_fournisseurs_list", LOG_DEBUG);
3566 $result = $this->db->query($sql);
3567 if ($result) {
3568 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3569 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3570
3571 $num = $this->db->num_rows($result);
3572
3573 //$out.='<select class="flat" id="select'.$htmlname.'" name="'.$htmlname.'">'; // remove select to have id same with combo and ajax
3574 $out .= '<select class="flat ' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '">';
3575 if (!$selected) {
3576 $out .= '<option value="-1" selected>' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3577 } else {
3578 $out .= '<option value="-1">' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3579 }
3580
3581 $i = 0;
3582 while ($i < $num) {
3583 $objp = $this->db->fetch_object($result);
3584
3585 if (is_null($objp->idprodfournprice)) {
3586 // There is no supplier price found, we will use the vat rate for sale
3587 $objp->tva_tx = $objp->tva_tx_sale;
3588 $objp->default_vat_code = $objp->default_vat_code_sale;
3589 }
3590
3591 $outkey = $objp->idprodfournprice; // id in table of price
3592 if (!$outkey && $alsoproductwithnosupplierprice) {
3593 $outkey = 'idprod_' . $objp->rowid; // id of product
3594 }
3595
3596 $outref = $objp->ref;
3597 $outbarcode = $objp->barcode;
3598 $outqty = 1;
3599 $outdiscount = 0;
3600 $outtype = $objp->fk_product_type;
3601 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3602 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3603
3604 // Units
3605 $outvalUnits = '';
3606 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3607 if (!empty($objp->unit_short)) {
3608 $outvalUnits .= ' - ' . $objp->unit_short;
3609 }
3610 if (!empty($objp->weight) && $objp->weight_units !== null) {
3611 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3612 $outvalUnits .= ' - ' . $unitToShow;
3613 }
3614 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3615 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3616 $outvalUnits .= ' - ' . $unitToShow;
3617 }
3618 if (!empty($objp->surface) && $objp->surface_units !== null) {
3619 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3620 $outvalUnits .= ' - ' . $unitToShow;
3621 }
3622 if (!empty($objp->volume) && $objp->volume_units !== null) {
3623 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3624 $outvalUnits .= ' - ' . $unitToShow;
3625 }
3626 if ($outdurationvalue && $outdurationunit) {
3627 $da = array(
3628 'h' => $langs->trans('Hour'),
3629 'd' => $langs->trans('Day'),
3630 'w' => $langs->trans('Week'),
3631 'm' => $langs->trans('Month'),
3632 'y' => $langs->trans('Year')
3633 );
3634 if (isset($da[$outdurationunit])) {
3635 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3636 }
3637 }
3638 }
3639
3640 $objRef = $objp->ref;
3641 if ($filterkey && $filterkey != '') {
3642 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3643 }
3644 $objRefFourn = $objp->ref_fourn;
3645 if ($filterkey && $filterkey != '') {
3646 $objRefFourn = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRefFourn, 1);
3647 }
3648 $label = $objp->label;
3649 if ($filterkey && $filterkey != '') {
3650 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3651 }
3652
3653 switch ($objp->fk_product_type) {
3655 $picto = 'product';
3656 break;
3658 $picto = 'service';
3659 break;
3660 default:
3661 $picto = '';
3662 break;
3663 }
3664
3665 if (empty($picto)) {
3666 $optlabel = '';
3667 } else {
3668 $optlabel = img_object('', $picto, 'class="paddingright classfortooltip"', 0, 0, 1);
3669 }
3670
3671 $optlabel .= $objp->ref;
3672 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3673 $optlabel .= ' <span class="opacitymedium">(' . $objp->ref_fourn . ')</span>';
3674 }
3675 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3676 $optlabel .= ' (' . $outbarcode . ')';
3677 }
3678 $optlabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3679
3680 $outvallabel = $objRef;
3681 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3682 $outvallabel .= ' (' . $objRefFourn . ')';
3683 }
3684 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3685 $outvallabel .= ' (' . $outbarcode . ')';
3686 }
3687 $outvallabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3688
3689 // Units
3690 $optlabel .= $outvalUnits;
3691 $outvallabel .= $outvalUnits;
3692
3693 if (!empty($objp->idprodfournprice)) {
3694 $outqty = $objp->quantity;
3695 $outdiscount = $objp->remise_percent;
3696 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3697 $prod_supplier = new ProductFournisseur($this->db);
3698 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3699 $prod_supplier->id = $objp->fk_product;
3700 $prod_supplier->fourn_qty = $objp->quantity;
3701 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3702 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3703
3704 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3705 $priceparser = new PriceParser($this->db);
3706 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3707 if ($price_result >= 0) {
3708 $objp->fprice = $price_result;
3709 if ($objp->quantity >= 1) {
3710 $objp->unitprice = $objp->fprice / $objp->quantity; // Replace dynamically unitprice
3711 }
3712 }
3713 }
3714 if ($objp->quantity == 1) {
3715 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3716 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/";
3717 $optlabel .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3718 $outvallabel .= $langs->transnoentities("Unit");
3719 } else {
3720 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3721 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3722 $optlabel .= ' ' . $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3723 $outvallabel .= ' ' . $langs->transnoentities("Units");
3724 }
3725
3726 if ($objp->quantity > 1) {
3727 $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
3728 $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
3729 }
3730 if ($objp->remise_percent >= 1) {
3731 $optlabel .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3732 $outvallabel .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3733 }
3734 if ($objp->duration) {
3735 $optlabel .= " - " . $objp->duration;
3736 $outvallabel .= " - " . $objp->duration;
3737 }
3738 if (!$socid) {
3739 $optlabel .= " - " . dol_trunc($objp->name, 8);
3740 $outvallabel .= " - " . dol_trunc($objp->name, 8);
3741 }
3742 if ($objp->supplier_reputation) {
3743 //TODO dictionary
3744 $reputations = array('' => $langs->trans('Standard'), 'FAVORITE' => $langs->trans('Favorite'), 'NOTTHGOOD' => $langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER' => $langs->trans('DoNotOrderThisProductToThisSupplier'));
3745
3746 $optlabel .= " - " . $reputations[$objp->supplier_reputation];
3747 $outvallabel .= " - " . $reputations[$objp->supplier_reputation];
3748 }
3749 } else {
3750 if (empty($alsoproductwithnosupplierprice)) { // No supplier price defined for couple product/supplier
3751 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3752 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3753 } else { // No supplier price defined for product, even on other suppliers
3754 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3755 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3756 }
3757 }
3758
3759 if (isModEnabled('stock') && $showstockinlist && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3760 $novirtualstock = ($showstockinlist == 2);
3761
3762 if ($user->hasRight('stock', 'lire')) {
3763 $outvallabel .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3764
3765 if ($objp->stock > 0) {
3766 $optlabel .= ' - <span class="product_line_stock_ok">';
3767 } elseif ($objp->stock <= 0) {
3768 $optlabel .= ' - <span class="product_line_stock_too_low">';
3769 }
3770 $optlabel .= $langs->transnoentities("Stock") . ':' . price(price2num($objp->stock, 'MS'));
3771 $optlabel .= '</span>';
3772 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3773 $langs->load("stocks");
3774
3775 $tmpproduct = new Product($this->db);
3776 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3777 $tmpproduct->load_virtual_stock();
3778 $virtualstock = $tmpproduct->stock_theorique;
3779
3780 $outvallabel .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3781
3782 $optlabel .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3783 if ($virtualstock > 0) {
3784 $optlabel .= '<span class="product_line_stock_ok">';
3785 } elseif ($virtualstock <= 0) {
3786 $optlabel .= '<span class="product_line_stock_too_low">';
3787 }
3788 $optlabel .= $virtualstock;
3789 $optlabel .= '</span>';
3790
3791 unset($tmpproduct);
3792 }
3793 }
3794 }
3795
3796 $optstart = '<option value="' . $outkey . '"';
3797 if ($selected && $selected == $objp->idprodfournprice) {
3798 $optstart .= ' selected';
3799 }
3800 if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) {
3801 $optstart .= ' disabled';
3802 }
3803
3804 if (!empty($objp->idprodfournprice) && $objp->idprodfournprice > 0) {
3805 $optstart .= ' data-product-id="' . dol_escape_htmltag($objp->rowid) . '"';
3806 $optstart .= ' data-price-id="' . dol_escape_htmltag($objp->idprodfournprice) . '"';
3807 $optstart .= ' data-qty="' . dol_escape_htmltag($objp->quantity) . '"';
3808 $optstart .= ' data-up="' . dol_escape_htmltag(price2num($objp->unitprice)) . '"';
3809 $optstart .= ' data-up-locale="' . dol_escape_htmltag(price($objp->unitprice)) . '"';
3810 $optstart .= ' data-discount="' . dol_escape_htmltag($outdiscount) . '"';
3811 $optstart .= ' data-tvatx="' . dol_escape_htmltag(price2num($objp->tva_tx)) . '"';
3812 $optstart .= ' data-tvatx-formated="' . dol_escape_htmltag(price($objp->tva_tx, 0, $langs, 1, -1, 2)) . '"';
3813 $optstart .= ' data-default-vat-code="' . dol_escape_htmltag($objp->default_vat_code) . '"';
3814 $optstart .= ' data-supplier-ref="' . dol_escape_htmltag($objp->ref_fourn) . '"';
3815 if (isModEnabled('multicurrency')) {
3816 $optstart .= ' data-multicurrency-code="' . dol_escape_htmltag($objp->multicurrency_code) . '"';
3817 $optstart .= ' data-multicurrency-up="' . dol_escape_htmltag($objp->multicurrency_unitprice) . '"';
3818 }
3819 }
3820 $optstart .= ' data-description="' . dol_escape_htmltag($objp->description, 0, 1) . '"';
3821
3822 $outarrayentry = array(
3823 'key' => $outkey,
3824 'value' => $outref,
3825 'label' => $outvallabel,
3826 'qty' => $outqty,
3827 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
3828 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
3829 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
3830 'tva_tx_formated' => price($objp->tva_tx, 0, $langs, 1, -1, 2),
3831 'tva_tx' => price2num($objp->tva_tx),
3832 'default_vat_code' => $objp->default_vat_code,
3833 'discount' => $outdiscount,
3834 'type' => $outtype,
3835 'duration_value' => $outdurationvalue,
3836 'duration_unit' => $outdurationunit,
3837 'disabled' => (empty($objp->idprodfournprice) ? true : false),
3838 'description' => $objp->description
3839 );
3840 if (isModEnabled('multicurrency')) {
3841 $outarrayentry['multicurrency_code'] = $objp->multicurrency_code;
3842 $outarrayentry['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
3843 }
3844
3845 $parameters = array(
3846 'objp' => &$objp,
3847 'optstart' => &$optstart,
3848 'optlabel' => &$optlabel,
3849 'outvallabel' => &$outvallabel,
3850 'outarrayentry' => &$outarrayentry
3851 );
3852 $reshook = $hookmanager->executeHooks('selectProduitsFournisseurListOption', $parameters, $this);
3853
3854
3855 // Add new entry
3856 // "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
3857 // "label" value of json key array is used by jQuery automatically as text for combo box
3858 $out .= $optstart . ' data-html="' . dol_escape_htmltag($optlabel) . '">' . $optlabel . "</option>\n";
3859 $outarraypush = array(
3860 'key' => $outkey,
3861 'value' => $outref,
3862 'label' => $outvallabel,
3863 'qty' => $outqty,
3864 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
3865 'price_qty_ht_locale' => price($objp->fprice),
3866 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
3867 'price_unit_ht_locale' => price($objp->unitprice),
3868 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
3869 'tva_tx_formated' => price($objp->tva_tx),
3870 'tva_tx' => price2num($objp->tva_tx),
3871 'default_vat_code' => $objp->default_vat_code,
3872 'discount' => $outdiscount,
3873 'type' => $outtype,
3874 'duration_value' => $outdurationvalue,
3875 'duration_unit' => $outdurationunit,
3876 'disabled' => (empty($objp->idprodfournprice) ? true : false),
3877 'description' => $objp->description
3878 );
3879 if (isModEnabled('multicurrency')) {
3880 $outarraypush['multicurrency_code'] = $objp->multicurrency_code;
3881 $outarraypush['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
3882 }
3883 array_push($outarray, $outarraypush);
3884
3885 // Example of var_dump $outarray
3886 // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
3887 // ["label"]=>string(76) "ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
3888 // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false)
3889 //}
3890 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
3891 //$outval=array('label'=>'ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)');
3892 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
3893
3894 $i++;
3895 }
3896 $out .= '</select>';
3897
3898 $this->db->free($result);
3899
3900 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
3901 $out .= ajax_combobox($htmlname);
3902 } else {
3903 dol_print_error($this->db);
3904 }
3905
3906 if (empty($outputmode)) {
3907 return $out;
3908 }
3909 return $outarray;
3910 }
3911
3912 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3913
3922 public function select_product_fourn_price($productid, $htmlname = 'productfournpriceid', $selected_supplier = 0)
3923 {
3924 // phpcs:enable
3925 global $langs, $conf;
3926
3927 $langs->load('stocks');
3928
3929 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, pfp.fk_soc,";
3930 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,";
3931 $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name";
3932 $sql .= " FROM " . $this->db->prefix() . "product as p";
3933 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
3934 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3935 $sql .= " WHERE pfp.entity IN (" . getEntity('productsupplierprice') . ")";
3936 $sql .= " AND p.tobuy = 1";
3937 $sql .= " AND s.fournisseur = 1";
3938 $sql .= " AND p.rowid = " . ((int) $productid);
3939 if (!getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED')) {
3940 $sql .= " ORDER BY s.nom, pfp.ref_fourn DESC";
3941 } else {
3942 $sql .= " ORDER BY pfp.unitprice ASC";
3943 }
3944
3945 dol_syslog(get_class($this) . "::select_product_fourn_price", LOG_DEBUG);
3946 $result = $this->db->query($sql);
3947
3948 if ($result) {
3949 $num = $this->db->num_rows($result);
3950
3951 $form = '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
3952
3953 if (!$num) {
3954 $form .= '<option value="0">-- ' . $langs->trans("NoSupplierPriceDefinedForThisProduct") . ' --</option>';
3955 } else {
3956 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3957 $form .= '<option value="0">&nbsp;</option>';
3958
3959 $i = 0;
3960 while ($i < $num) {
3961 $objp = $this->db->fetch_object($result);
3962
3963 $opt = '<option value="' . $objp->idprodfournprice . '"';
3964 //if there is only one supplier, preselect it
3965 if ($num == 1 || ($selected_supplier > 0 && $objp->fk_soc == $selected_supplier) || ($i == 0 && getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED'))) {
3966 $opt .= ' selected';
3967 }
3968 $opt .= '>' . $objp->name . ' - ' . $objp->ref_fourn . ' - ';
3969
3970 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3971 $prod_supplier = new ProductFournisseur($this->db);
3972 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3973 $prod_supplier->id = $productid;
3974 $prod_supplier->fourn_qty = $objp->quantity;
3975 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3976 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3977
3978 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3979 $priceparser = new PriceParser($this->db);
3980 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3981 if ($price_result >= 0) {
3982 $objp->fprice = $price_result;
3983 if ($objp->quantity >= 1) {
3984 $objp->unitprice = $objp->fprice / $objp->quantity;
3985 }
3986 }
3987 }
3988 if ($objp->quantity == 1) {
3989 $opt .= price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3990 }
3991
3992 $opt .= $objp->quantity . ' ';
3993
3994 if ($objp->quantity == 1) {
3995 $opt .= $langs->trans("Unit");
3996 } else {
3997 $opt .= $langs->trans("Units");
3998 }
3999 if ($objp->quantity > 1) {
4000 $opt .= " - ";
4001 $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");
4002 }
4003 if ($objp->duration) {
4004 $opt .= " - " . $objp->duration;
4005 }
4006 $opt .= "</option>\n";
4007
4008 $form .= $opt;
4009 $i++;
4010 }
4011 }
4012
4013 $form .= '</select>';
4014 $this->db->free($result);
4015 return $form;
4016 } else {
4017 dol_print_error($this->db);
4018 return '';
4019 }
4020 }
4021
4022
4023 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4030 {
4031 // phpcs:enable
4032 global $langs;
4033
4034 $num = count($this->cache_conditions_paiements);
4035 if ($num > 0) {
4036 return 0; // Cache already loaded
4037 }
4038
4039 dol_syslog(__METHOD__, LOG_DEBUG);
4040
4041 $sql = "SELECT rowid, code, libelle as label, deposit_percent";
4042 $sql .= " FROM " . $this->db->prefix() . 'c_payment_term';
4043 $sql .= " WHERE entity IN (" . getEntity('c_payment_term') . ")";
4044 $sql .= " AND active > 0";
4045 $sql .= " ORDER BY sortorder";
4046
4047 $resql = $this->db->query($sql);
4048 if ($resql) {
4049 $num = $this->db->num_rows($resql);
4050 $i = 0;
4051 while ($i < $num) {
4052 $obj = $this->db->fetch_object($resql);
4053
4054 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4055 $label = ($langs->trans("PaymentConditionShort" . $obj->code) != "PaymentConditionShort" . $obj->code ? $langs->trans("PaymentConditionShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4056 $this->cache_conditions_paiements[$obj->rowid]['code'] = $obj->code;
4057 $this->cache_conditions_paiements[$obj->rowid]['label'] = $label;
4058 $this->cache_conditions_paiements[$obj->rowid]['deposit_percent'] = $obj->deposit_percent;
4059 $i++;
4060 }
4061
4062 //$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1); // We use the field sortorder of table
4063
4064 return $num;
4065 } else {
4066 dol_print_error($this->db);
4067 return -1;
4068 }
4069 }
4070
4071 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4072
4078 public function load_cache_availability()
4079 {
4080 // phpcs:enable
4081 global $langs;
4082
4083 $num = count($this->cache_availability); // TODO Use $conf->cache['availability'] instead of $this->cache_availability
4084 if ($num > 0) {
4085 return 0; // Cache already loaded
4086 }
4087
4088 dol_syslog(__METHOD__, LOG_DEBUG);
4089
4090 $langs->load('propal');
4091
4092 $sql = "SELECT rowid, code, label, position";
4093 $sql .= " FROM " . $this->db->prefix() . 'c_availability';
4094 $sql .= " WHERE active > 0";
4095
4096 $resql = $this->db->query($sql);
4097 if ($resql) {
4098 $num = $this->db->num_rows($resql);
4099 $i = 0;
4100 while ($i < $num) {
4101 $obj = $this->db->fetch_object($resql);
4102
4103 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4104 $label = ($langs->trans("AvailabilityType" . $obj->code) != "AvailabilityType" . $obj->code ? $langs->trans("AvailabilityType" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4105 $this->cache_availability[$obj->rowid]['code'] = $obj->code;
4106 $this->cache_availability[$obj->rowid]['label'] = $label;
4107 $this->cache_availability[$obj->rowid]['position'] = $obj->position;
4108 $i++;
4109 }
4110
4111 $this->cache_availability = dol_sort_array($this->cache_availability, 'position', 'asc', 0, 0, 1);
4112
4113 return $num;
4114 } else {
4115 dol_print_error($this->db);
4116 return -1;
4117 }
4118 }
4119
4130 public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0, $morecss = '')
4131 {
4132 global $langs, $user;
4133
4134 $this->load_cache_availability();
4135
4136 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4137
4138 print '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4139 if ($addempty) {
4140 print '<option value="0">&nbsp;</option>';
4141 }
4142 foreach ($this->cache_availability as $id => $arrayavailability) {
4143 if ($selected == $id) {
4144 print '<option value="' . $id . '" selected>';
4145 } else {
4146 print '<option value="' . $id . '">';
4147 }
4148 print dol_escape_htmltag($arrayavailability['label']);
4149 print '</option>';
4150 }
4151 print '</select>';
4152 if ($user->admin) {
4153 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4154 }
4155 print ajax_combobox($htmlname);
4156 }
4157
4163 public function loadCacheInputReason()
4164 {
4165 global $langs;
4166
4167 $num = count($this->cache_demand_reason); // TODO Use $conf->cache['input_reason'] instead of $this->cache_demand_reason
4168 if ($num > 0) {
4169 return 0; // Cache already loaded
4170 }
4171
4172 $sql = "SELECT rowid, code, label";
4173 $sql .= " FROM " . $this->db->prefix() . 'c_input_reason';
4174 $sql .= " WHERE active > 0";
4175
4176 $resql = $this->db->query($sql);
4177 if ($resql) {
4178 $num = $this->db->num_rows($resql);
4179 $i = 0;
4180 $tmparray = array();
4181 while ($i < $num) {
4182 $obj = $this->db->fetch_object($resql);
4183
4184 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4185 $label = ($obj->label != '-' ? $obj->label : '');
4186 if ($langs->trans("DemandReasonType" . $obj->code) != "DemandReasonType" . $obj->code) {
4187 $label = $langs->trans("DemandReasonType" . $obj->code); // So translation key DemandReasonTypeSRC_XXX will work
4188 }
4189 if ($langs->trans($obj->code) != $obj->code) {
4190 $label = $langs->trans($obj->code); // So translation key SRC_XXX will work
4191 }
4192
4193 $tmparray[$obj->rowid]['id'] = $obj->rowid;
4194 $tmparray[$obj->rowid]['code'] = $obj->code;
4195 $tmparray[$obj->rowid]['label'] = $label;
4196 $i++;
4197 }
4198
4199 $this->cache_demand_reason = dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1);
4200
4201 unset($tmparray);
4202 return $num;
4203 } else {
4204 dol_print_error($this->db);
4205 return -1;
4206 }
4207 }
4208
4221 public function selectInputReason($selected = '', $htmlname = 'demandreasonid', $exclude = '', $addempty = 0, $morecss = '', $notooltip = 0)
4222 {
4223 global $langs, $user;
4224
4225 $this->loadCacheInputReason();
4226
4227 print '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4228 if ($addempty) {
4229 print '<option value="0"' . (empty($selected) ? ' selected' : '') . '>&nbsp;</option>';
4230 }
4231 foreach ($this->cache_demand_reason as $id => $arraydemandreason) {
4232 if ($arraydemandreason['code'] == $exclude) {
4233 continue;
4234 }
4235
4236 if ($selected && ($selected == $arraydemandreason['id'] || $selected == $arraydemandreason['code'])) {
4237 print '<option value="' . $arraydemandreason['id'] . '" selected>';
4238 } else {
4239 print '<option value="' . $arraydemandreason['id'] . '">';
4240 }
4241 $label = $arraydemandreason['label']; // Translation of label was already done into the ->loadCacheInputReason
4242 print $langs->trans($label);
4243 print '</option>';
4244 }
4245 print '</select>';
4246 if ($user->admin && empty($notooltip)) {
4247 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4248 }
4249 print ajax_combobox('select_' . $htmlname);
4250 }
4251
4252 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4253
4260 {
4261 // phpcs:enable
4262 global $langs;
4263
4264 $num = count($this->cache_types_paiements); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_types_paiements
4265 if ($num > 0) {
4266 return $num; // Cache already loaded
4267 }
4268
4269 dol_syslog(__METHOD__, LOG_DEBUG);
4270
4271 $this->cache_types_paiements = array();
4272
4273 $sql = "SELECT id, code, libelle as label, type, active";
4274 $sql .= " FROM " . $this->db->prefix() . "c_paiement";
4275 $sql .= " WHERE entity IN (" . getEntity('c_paiement') . ")";
4276
4277 $resql = $this->db->query($sql);
4278 if ($resql) {
4279 $num = $this->db->num_rows($resql);
4280 $i = 0;
4281 while ($i < $num) {
4282 $obj = $this->db->fetch_object($resql);
4283
4284 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4285 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4286 $this->cache_types_paiements[$obj->id]['id'] = $obj->id;
4287 $this->cache_types_paiements[$obj->id]['code'] = $obj->code;
4288 $this->cache_types_paiements[$obj->id]['label'] = $label;
4289 $this->cache_types_paiements[$obj->id]['type'] = $obj->type;
4290 $this->cache_types_paiements[$obj->id]['active'] = $obj->active;
4291 $i++;
4292 }
4293
4294 $this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1);
4295
4296 return $num;
4297 } else {
4298 dol_print_error($this->db);
4299 return -1;
4300 }
4301 }
4302
4303
4304 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4305
4323 public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4324 {
4325 // phpcs:enable
4326 print $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, $noinfoadmin, $morecss, $deposit_percent);
4327 }
4328
4329
4346 public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4347 {
4348 global $langs, $user, $conf;
4349
4350 $out = '';
4351 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4352
4354
4355 // Set default value if not already set by caller
4356 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID')) {
4357 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TERM_ID", LOG_NOTICE);
4358 $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID;
4359 }
4360
4361 $out .= '<select id="' . $htmlname . '" class="flat selectpaymentterms' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4362 if ($addempty) {
4363 $out .= '<option value="0">&nbsp;</option>';
4364 }
4365
4366 $selectedDepositPercent = null;
4367
4368 foreach ($this->cache_conditions_paiements as $id => $arrayconditions) {
4369 if ($filtertype <= 0 && !empty($arrayconditions['deposit_percent'])) {
4370 continue;
4371 }
4372
4373 if ($selected == $id) {
4374 $selectedDepositPercent = $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'];
4375 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '" selected>';
4376 } else {
4377 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '">';
4378 }
4379 $label = $arrayconditions['label'];
4380
4381 if (!empty($arrayconditions['deposit_percent'])) {
4382 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'], $label);
4383 }
4384
4385 $out .= $label;
4386 $out .= '</option>';
4387 }
4388 $out .= '</select>';
4389 if ($user->admin && empty($noinfoadmin)) {
4390 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4391 }
4392 $out .= ajax_combobox($htmlname);
4393
4394 if ($deposit_percent >= 0) {
4395 $out .= ' <span id="' . $htmlname . '_deposit_percent_container"' . (empty($selectedDepositPercent) ? ' style="display: none"' : '') . '>';
4396 $out .= $langs->trans('DepositPercent') . ' : ';
4397 $out .= '<input id="' . $htmlname . '_deposit_percent" name="' . $htmlname . '_deposit_percent" class="maxwidth50" value="' . $deposit_percent . '" />';
4398 $out .= '</span>';
4399 $out .= '
4400 <script nonce="' . getNonce() . '">
4401 $(document).ready(function () {
4402 $("#' . $htmlname . '").change(function () {
4403 let $selected = $(this).find("option:selected");
4404 let depositPercent = $selected.attr("data-deposit_percent");
4405
4406 if (depositPercent.length > 0) {
4407 $("#' . $htmlname . '_deposit_percent_container").show().find("#' . $htmlname . '_deposit_percent").val(depositPercent);
4408 } else {
4409 $("#' . $htmlname . '_deposit_percent_container").hide();
4410 }
4411
4412 return true;
4413 });
4414 });
4415 </script>';
4416 }
4417
4418 return $out;
4419 }
4420
4421
4422 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4423
4440 public function select_types_paiements($selected = '', $htmlname = 'paiementtype', $filtertype = '', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '', $nooutput = 0)
4441 {
4442 // phpcs:enable
4443 global $langs, $user, $conf;
4444
4445 $out = '';
4446
4447 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
4448
4449 $filterarray = array();
4450 if ($filtertype == 'CRDT') {
4451 $filterarray = array(0, 2, 3);
4452 } elseif ($filtertype == 'DBIT') {
4453 $filterarray = array(1, 2, 3);
4454 } elseif ($filtertype != '' && $filtertype != '-1') {
4455 $filterarray = explode(',', $filtertype);
4456 }
4457
4459
4460 // Set default value if not already set by caller
4461 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID')) {
4462 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TYPE_ID", LOG_NOTICE);
4463 $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TYPE_ID;
4464 }
4465
4466 $out .= '<select id="select' . $htmlname . '" class="flat selectpaymenttypes' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4467 if ($empty) {
4468 $out .= '<option value="">&nbsp;</option>';
4469 }
4470 foreach ($this->cache_types_paiements as $id => $arraytypes) {
4471 // If not good status
4472 if ($active >= 0 && $arraytypes['active'] != $active) {
4473 continue;
4474 }
4475
4476 // On passe si on a demande de filtrer sur des modes de paiments particuliers
4477 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
4478 continue;
4479 }
4480
4481 // We discard empty line if showempty is on because an empty line has already been output.
4482 if ($empty && empty($arraytypes['code'])) {
4483 continue;
4484 }
4485
4486 if ($format == 0) {
4487 $out .= '<option value="' . $id . '"';
4488 } elseif ($format == 1) {
4489 $out .= '<option value="' . $arraytypes['code'] . '"';
4490 } elseif ($format == 2) {
4491 $out .= '<option value="' . $arraytypes['code'] . '"';
4492 } elseif ($format == 3) {
4493 $out .= '<option value="' . $id . '"';
4494 }
4495 // Print attribute selected or not
4496 if ($format == 1 || $format == 2) {
4497 if ($selected == $arraytypes['code']) {
4498 $out .= ' selected';
4499 }
4500 } else {
4501 if ($selected == $id) {
4502 $out .= ' selected';
4503 }
4504 }
4505 $out .= '>';
4506 $value = '';
4507 if ($format == 0) {
4508 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4509 } elseif ($format == 1) {
4510 $value = $arraytypes['code'];
4511 } elseif ($format == 2) {
4512 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4513 } elseif ($format == 3) {
4514 $value = $arraytypes['code'];
4515 }
4516 $out .= $value ? $value : '&nbsp;';
4517 $out .= '</option>';
4518 }
4519 $out .= '</select>';
4520 if ($user->admin && !$noadmininfo) {
4521 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4522 }
4523 $out .= ajax_combobox('select' . $htmlname);
4524
4525 if (empty($nooutput)) {
4526 print $out;
4527 } else {
4528 return $out;
4529 }
4530 }
4531
4532
4541 public function selectPriceBaseType($selected = '', $htmlname = 'price_base_type', $addjscombo = 0)
4542 {
4543 global $langs;
4544
4545 $return = '<select class="flat maxwidth100" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4546 $options = array(
4547 'HT' => $langs->trans("HT"),
4548 'TTC' => $langs->trans("TTC")
4549 );
4550 foreach ($options as $id => $value) {
4551 if ($selected == $id) {
4552 $return .= '<option value="' . $id . '" selected>' . $value;
4553 } else {
4554 $return .= '<option value="' . $id . '">' . $value;
4555 }
4556 $return .= '</option>';
4557 }
4558 $return .= '</select>';
4559 if ($addjscombo) {
4560 $return .= ajax_combobox('select_' . $htmlname);
4561 }
4562
4563 return $return;
4564 }
4565
4566 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4567
4574 {
4575 // phpcs:enable
4576 global $langs;
4577
4578 $num = count($this->cache_transport_mode); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_transport_mode
4579 if ($num > 0) {
4580 return $num; // Cache already loaded
4581 }
4582
4583 dol_syslog(__METHOD__, LOG_DEBUG);
4584
4585 $this->cache_transport_mode = array();
4586
4587 $sql = "SELECT rowid, code, label, active";
4588 $sql .= " FROM " . $this->db->prefix() . "c_transport_mode";
4589 $sql .= " WHERE entity IN (" . getEntity('c_transport_mode') . ")";
4590
4591 $resql = $this->db->query($sql);
4592 if ($resql) {
4593 $num = $this->db->num_rows($resql);
4594 $i = 0;
4595 while ($i < $num) {
4596 $obj = $this->db->fetch_object($resql);
4597
4598 // If traduction exist, we use it else we take the default label
4599 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4600 $this->cache_transport_mode[$obj->rowid]['rowid'] = $obj->rowid;
4601 $this->cache_transport_mode[$obj->rowid]['code'] = $obj->code;
4602 $this->cache_transport_mode[$obj->rowid]['label'] = $label;
4603 $this->cache_transport_mode[$obj->rowid]['active'] = $obj->active;
4604 $i++;
4605 }
4606
4607 $this->cache_transport_mode = dol_sort_array($this->cache_transport_mode, 'label', 'asc', 0, 0, 1);
4608
4609 return $num;
4610 } else {
4611 dol_print_error($this->db);
4612 return -1;
4613 }
4614 }
4615
4629 public function selectTransportMode($selected = '', $htmlname = 'transportmode', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '')
4630 {
4631 global $langs, $user;
4632
4633 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $format, LOG_DEBUG);
4634
4636
4637 print '<select id="select' . $htmlname . '" class="flat selectmodetransport' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4638 if ($empty) {
4639 print '<option value="">&nbsp;</option>';
4640 }
4641 foreach ($this->cache_transport_mode as $id => $arraytypes) {
4642 // If not good status
4643 if ($active >= 0 && $arraytypes['active'] != $active) {
4644 continue;
4645 }
4646
4647 // We discard empty line if showempty is on because an empty line has already been output.
4648 if ($empty && empty($arraytypes['code'])) {
4649 continue;
4650 }
4651
4652 if ($format == 0) {
4653 print '<option value="' . $id . '"';
4654 } elseif ($format == 1) {
4655 print '<option value="' . $arraytypes['code'] . '"';
4656 } elseif ($format == 2) {
4657 print '<option value="' . $arraytypes['code'] . '"';
4658 } elseif ($format == 3) {
4659 print '<option value="' . $id . '"';
4660 }
4661 // If text is selected, we compare with code, else with id
4662 if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) {
4663 print ' selected';
4664 } elseif ($selected == $id) {
4665 print ' selected';
4666 }
4667 print '>';
4668 $value = '';
4669 if ($format == 0) {
4670 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4671 } elseif ($format == 1) {
4672 $value = $arraytypes['code'];
4673 } elseif ($format == 2) {
4674 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4675 } elseif ($format == 3) {
4676 $value = $arraytypes['code'];
4677 }
4678 print $value ? $value : '&nbsp;';
4679 print '</option>';
4680 }
4681 print '</select>';
4682 if ($user->admin && !$noadmininfo) {
4683 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4684 }
4685 }
4686
4699 public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '', $noinfoadmin = 0, $morecss = '')
4700 {
4701 global $langs, $user;
4702
4703 $langs->load("admin");
4704 $langs->load("deliveries");
4705
4706 $sql = "SELECT rowid, code, libelle as label";
4707 $sql .= " FROM " . $this->db->prefix() . "c_shipment_mode";
4708 $sql .= " WHERE active > 0";
4709 if ($filtre) {
4710 $sql .= " AND " . $filtre;
4711 }
4712 $sql .= " ORDER BY libelle ASC";
4713
4714 dol_syslog(get_class($this) . "::selectShippingMode", LOG_DEBUG);
4715 $result = $this->db->query($sql);
4716 if ($result) {
4717 $num = $this->db->num_rows($result);
4718 $i = 0;
4719 if ($num) {
4720 print '<select id="select' . $htmlname . '" class="flat selectshippingmethod' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4721 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4722 print '<option value="-1">&nbsp;</option>';
4723 }
4724 while ($i < $num) {
4725 $obj = $this->db->fetch_object($result);
4726 if ($selected == $obj->rowid) {
4727 print '<option value="' . $obj->rowid . '" selected>';
4728 } else {
4729 print '<option value="' . $obj->rowid . '">';
4730 }
4731 print ($langs->trans("SendingMethod" . strtoupper($obj->code)) != "SendingMethod" . strtoupper($obj->code)) ? $langs->trans("SendingMethod" . strtoupper($obj->code)) : $obj->label;
4732 print '</option>';
4733 $i++;
4734 }
4735 print "</select>";
4736 if ($user->admin && empty($noinfoadmin)) {
4737 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4738 }
4739
4740 print ajax_combobox('select' . $htmlname);
4741 } else {
4742 print $langs->trans("NoShippingMethodDefined");
4743 }
4744 } else {
4745 dol_print_error($this->db);
4746 }
4747 }
4748
4758 public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0)
4759 {
4760 global $langs;
4761
4762 $langs->load("deliveries");
4763
4764 if ($htmlname != "none") {
4765 print '<form method="POST" action="' . $page . '">';
4766 print '<input type="hidden" name="action" value="setshippingmethod">';
4767 print '<input type="hidden" name="token" value="' . newToken() . '">';
4768 $this->selectShippingMethod($selected, $htmlname, '', $addempty);
4769 print '<input type="submit" class="button valignmiddle" value="' . $langs->trans("Modify") . '">';
4770 print '</form>';
4771 } else {
4772 if ($selected) {
4773 $code = $langs->getLabelFromKey($this->db, $selected, 'c_shipment_mode', 'rowid', 'code');
4774 print $langs->trans("SendingMethod" . strtoupper($code));
4775 } else {
4776 print "&nbsp;";
4777 }
4778 }
4779 }
4780
4789 public function selectSituationInvoices($selected = '', $socid = 0)
4790 {
4791 global $langs;
4792
4793 $langs->load('bills');
4794
4795 $opt = '<option value="" selected></option>';
4796 $sql = "SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc";
4797 $sql .= ' FROM ' . $this->db->prefix() . 'facture';
4798 $sql .= ' WHERE entity IN (' . getEntity('invoice') . ')';
4799 $sql .= ' AND situation_counter >= 1';
4800 $sql .= ' AND fk_soc = ' . (int) $socid;
4801 $sql .= ' AND type <> 2';
4802 $sql .= ' ORDER by situation_cycle_ref, situation_counter desc';
4803 $resql = $this->db->query($sql);
4804
4805 if ($resql && $this->db->num_rows($resql) > 0) {
4806 // Last seen cycle
4807 $ref = 0;
4808 while ($obj = $this->db->fetch_object($resql)) {
4809 //Same cycle ?
4810 if ($obj->situation_cycle_ref != $ref) {
4811 // Just seen this cycle
4812 $ref = $obj->situation_cycle_ref;
4813 //not final ?
4814 if ($obj->situation_final != 1) {
4815 //Not prov?
4816 if (substr($obj->ref, 1, 4) != 'PROV') {
4817 if ($selected == $obj->rowid) {
4818 $opt .= '<option value="' . $obj->rowid . '" selected>' . $obj->ref . '</option>';
4819 } else {
4820 $opt .= '<option value="' . $obj->rowid . '">' . $obj->ref . '</option>';
4821 }
4822 }
4823 }
4824 }
4825 }
4826 } else {
4827 dol_syslog("Error sql=" . $sql . ", error=" . $this->error, LOG_ERR);
4828 }
4829 if ($opt == '<option value ="" selected></option>') {
4830 $opt = '<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>';
4831 }
4832 return $opt;
4833 }
4834
4844 public function selectUnits($selected = '', $htmlname = 'units', $showempty = 0, $unit_type = '')
4845 {
4846 global $langs;
4847
4848 $langs->load('products');
4849
4850 $return = '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
4851
4852 $sql = "SELECT rowid, label, code FROM " . $this->db->prefix() . "c_units";
4853 $sql .= ' WHERE active > 0';
4854 if (!empty($unit_type)) {
4855 $sql .= " AND unit_type = '" . $this->db->escape($unit_type) . "'";
4856 }
4857 $sql .= " ORDER BY sortorder";
4858
4859 $resql = $this->db->query($sql);
4860 if ($resql && $this->db->num_rows($resql) > 0) {
4861 if ($showempty) {
4862 $return .= '<option value="none"></option>';
4863 }
4864
4865 while ($res = $this->db->fetch_object($resql)) {
4866 $unitLabel = $res->label;
4867 if (!empty($langs->tab_translate['unit' . $res->code])) { // check if Translation is available before
4868 $unitLabel = $langs->trans('unit' . $res->code) != $res->label ? $langs->trans('unit' . $res->code) : $res->label;
4869 }
4870
4871 if ($selected == $res->rowid) {
4872 $return .= '<option value="' . $res->rowid . '" selected>' . $unitLabel . '</option>';
4873 } else {
4874 $return .= '<option value="' . $res->rowid . '">' . $unitLabel . '</option>';
4875 }
4876 }
4877 $return .= '</select>';
4878 }
4879 return $return;
4880 }
4881
4882 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4883
4898 public function select_comptes($selected = '', $htmlname = 'accountid', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '', $showcurrency = 0, $morecss = '', $nooutput = 0)
4899 {
4900 // phpcs:enable
4901 global $langs, $conf;
4902
4903 $out = '';
4904
4905 $langs->load("admin");
4906 $num = 0;
4907
4908 $sql = "SELECT rowid, label, bank, clos as status, currency_code";
4909 $sql .= " FROM " . $this->db->prefix() . "bank_account";
4910 $sql .= " WHERE entity IN (" . getEntity('bank_account') . ")";
4911 if ($status != 2) {
4912 $sql .= " AND clos = " . (int) $status;
4913 }
4914 if ($filtre) {
4915 $sql .= " AND " . $filtre;
4916 }
4917 $sql .= " ORDER BY label";
4918
4919 dol_syslog(get_class($this) . "::select_comptes", LOG_DEBUG);
4920 $result = $this->db->query($sql);
4921 if ($result) {
4922 $num = $this->db->num_rows($result);
4923 $i = 0;
4924 if ($num) {
4925 $out .= '<select id="select' . $htmlname . '" class="flat selectbankaccount' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4926 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4927 $out .= '<option value="-1">&nbsp;</option>';
4928 }
4929
4930 while ($i < $num) {
4931 $obj = $this->db->fetch_object($result);
4932 if ($selected == $obj->rowid || ($useempty == 2 && $num == 1 && empty($selected))) {
4933 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '" selected>';
4934 } else {
4935 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '">';
4936 }
4937 $out .= trim($obj->label);
4938 if ($showcurrency) {
4939 $out .= ' (' . $obj->currency_code . ')';
4940 }
4941 if ($status == 2 && $obj->status == 1) {
4942 $out .= ' (' . $langs->trans("Closed") . ')';
4943 }
4944 $out .= '</option>';
4945 $i++;
4946 }
4947 $out .= "</select>";
4948 $out .= ajax_combobox('select' . $htmlname);
4949 } else {
4950 if ($status == 0) {
4951 $out .= '<span class="opacitymedium">' . $langs->trans("NoActiveBankAccountDefined") . '</span>';
4952 } else {
4953 $out .= '<span class="opacitymedium">' . $langs->trans("NoBankAccountFound") . '</span>';
4954 }
4955 }
4956 } else {
4957 dol_print_error($this->db);
4958 }
4959
4960 // Output or return
4961 if (empty($nooutput)) {
4962 print $out;
4963 } else {
4964 return $out;
4965 }
4966
4967 return $num;
4968 }
4969
4981 public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '')
4982 {
4983 global $langs, $conf;
4984
4985 $langs->load("admin");
4986 $num = 0;
4987
4988 $sql = "SELECT rowid, name, fk_country, status, entity";
4989 $sql .= " FROM " . $this->db->prefix() . "establishment";
4990 $sql .= " WHERE 1=1";
4991 if ($status != 2) {
4992 $sql .= " AND status = " . (int) $status;
4993 }
4994 if ($filtre) {
4995 $sql .= " AND " . $filtre;
4996 }
4997 $sql .= " ORDER BY name";
4998
4999 dol_syslog(get_class($this) . "::select_establishment", LOG_DEBUG);
5000 $result = $this->db->query($sql);
5001 if ($result) {
5002 $num = $this->db->num_rows($result);
5003 $i = 0;
5004 if ($num) {
5005 print '<select id="select' . $htmlname . '" class="flat selectestablishment" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5006 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5007 print '<option value="-1">&nbsp;</option>';
5008 }
5009
5010 while ($i < $num) {
5011 $obj = $this->db->fetch_object($result);
5012 if ($selected == $obj->rowid) {
5013 print '<option value="' . $obj->rowid . '" selected>';
5014 } else {
5015 print '<option value="' . $obj->rowid . '">';
5016 }
5017 print trim($obj->name);
5018 if ($status == 2 && $obj->status == 1) {
5019 print ' (' . $langs->trans("Closed") . ')';
5020 }
5021 print '</option>';
5022 $i++;
5023 }
5024 print "</select>";
5025 } else {
5026 if ($status == 0) {
5027 print '<span class="opacitymedium">' . $langs->trans("NoActiveEstablishmentDefined") . '</span>';
5028 } else {
5029 print '<span class="opacitymedium">' . $langs->trans("NoEstablishmentFound") . '</span>';
5030 }
5031 }
5032
5033 return $num;
5034 } else {
5035 dol_print_error($this->db);
5036 return -1;
5037 }
5038 }
5039
5049 public function formSelectAccount($page, $selected = '', $htmlname = 'fk_account', $addempty = 0)
5050 {
5051 global $langs;
5052 if ($htmlname != "none") {
5053 print '<form method="POST" action="' . $page . '">';
5054 print '<input type="hidden" name="action" value="setbankaccount">';
5055 print '<input type="hidden" name="token" value="' . newToken() . '">';
5056 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
5057 $nbaccountfound = $this->select_comptes($selected, $htmlname, 0, '', $addempty);
5058 if ($nbaccountfound > 0) {
5059 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5060 }
5061 print '</form>';
5062 } else {
5063 $langs->load('banks');
5064
5065 if ($selected) {
5066 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
5067 $bankstatic = new Account($this->db);
5068 $result = $bankstatic->fetch($selected);
5069 if ($result) {
5070 print $bankstatic->getNomUrl(1);
5071 }
5072 } else {
5073 print "&nbsp;";
5074 }
5075 }
5076 }
5077
5078 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5079
5098 public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $markafterid = 0, $outputmode = 0, $include = 0, $morecss = '')
5099 {
5100 // phpcs:enable
5101 global $conf, $langs;
5102 $langs->load("categories");
5103
5104 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
5105
5106 // For backward compatibility
5107 if (is_numeric($type)) {
5108 dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING);
5109 }
5110
5111 if ($type === Categorie::TYPE_BANK_LINE) {
5112 // TODO Move this into common category feature
5113 $cate_arbo = array();
5114 $sql = "SELECT c.label, c.rowid";
5115 $sql .= " FROM " . $this->db->prefix() . "bank_categ as c";
5116 $sql .= " WHERE entity = " . $conf->entity;
5117 $sql .= " ORDER BY c.label";
5118 $result = $this->db->query($sql);
5119 if ($result) {
5120 $num = $this->db->num_rows($result);
5121 $i = 0;
5122 while ($i < $num) {
5123 $objp = $this->db->fetch_object($result);
5124 if ($objp) {
5125 $cate_arbo[$objp->rowid] = array('id' => $objp->rowid, 'fulllabel' => $objp->label, 'color' => '', 'picto' => 'category');
5126 }
5127 $i++;
5128 }
5129 $this->db->free($result);
5130 } else {
5131 dol_print_error($this->db);
5132 }
5133 } else {
5134 $cat = new Categorie($this->db);
5135 $cate_arbo = $cat->get_full_arbo($type, $markafterid, $include);
5136 }
5137
5138 $outarray = array();
5139 $outarrayrichhtml = array();
5140
5141 $output = '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
5142 if (is_array($cate_arbo)) {
5143 if (!count($cate_arbo)) {
5144 $output .= '<option value="-1" disabled>' . $langs->trans("NoCategoriesDefined") . '</option>';
5145 } else {
5146 $output .= '<option value="-1">&nbsp;</option>';
5147 foreach ($cate_arbo as $key => $value) {
5148 if ($cate_arbo[$key]['id'] == $selected || ($selected === 'auto' && count($cate_arbo) == 1)) {
5149 $add = 'selected ';
5150 } else {
5151 $add = '';
5152 }
5153
5154 $labeltoshow = img_picto('', 'category', 'class="pictofixedwidth" style="color: #' . $cate_arbo[$key]['color'] . '"');
5155 $labeltoshow .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5156
5157 $outarray[$cate_arbo[$key]['id']] = $cate_arbo[$key]['fulllabel'];
5158
5159 $outarrayrichhtml[$cate_arbo[$key]['id']] = $labeltoshow;
5160
5161 $output .= '<option ' . $add . 'value="' . $cate_arbo[$key]['id'] . '"';
5162 $output .= ' data-html="' . dol_escape_htmltag($labeltoshow) . '"';
5163 $output .= '>';
5164 $output .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5165 $output .= '</option>';
5166 }
5167 }
5168 }
5169 $output .= '</select>';
5170 $output .= "\n";
5171
5172 if ($outputmode == 2) {
5173 return $cate_arbo;
5174 } elseif ($outputmode == 1) {
5175 return $outarray;
5176 } elseif ($outputmode == 3) {
5177 return $outarrayrichhtml;
5178 }
5179 return $output;
5180 }
5181
5182 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5183
5200 public function form_confirm($page, $title, $question, $action, $formquestion = array(), $selectedchoice = "", $useajax = 0, $height = 170, $width = 500)
5201 {
5202 // phpcs:enable
5203 dol_syslog(__METHOD__ . ': using form_confirm is deprecated. Use formconfim instead.', LOG_WARNING);
5204 print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width);
5205 }
5206
5234 public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No')
5235 {
5236 global $langs, $conf;
5237
5238 $more = '<!-- formconfirm - before call, page=' . dol_escape_htmltag($page) . ' -->';
5239 $formconfirm = '';
5240 $inputok = array();
5241 $inputko = array();
5242
5243 // Clean parameters
5244 $newselectedchoice = empty($selectedchoice) ? "no" : $selectedchoice;
5245 if ($conf->browser->layout == 'phone') {
5246 $width = '95%';
5247 }
5248
5249 // Set height automatically if not defined
5250 if (empty($height)) {
5251 $height = 220;
5252 if (is_array($formquestion) && count($formquestion) > 2) {
5253 $height += ((count($formquestion) - 2) * 24);
5254 }
5255 }
5256
5257 if (is_array($formquestion) && !empty($formquestion)) {
5258 // First add hidden fields and value
5259 foreach ($formquestion as $key => $input) {
5260 if (is_array($input) && !empty($input)) {
5261 if ($input['type'] == 'hidden') {
5262 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5263 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5264
5265 $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";
5266 }
5267 }
5268 }
5269
5270 // Now add questions
5271 $moreonecolumn = '';
5272 $more .= '<div class="tagtable paddingtopbottomonly centpercent noborderspacing">' . "\n";
5273 foreach ($formquestion as $key => $input) {
5274 if (is_array($input) && !empty($input)) {
5275 $size = (!empty($input['size']) ? ' size="' . $input['size'] . '"' : ''); // deprecated. Use morecss instead.
5276 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5277 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5278
5279 if ($input['type'] == 'text') {
5280 $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";
5281 } elseif ($input['type'] == 'password') {
5282 $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";
5283 } elseif ($input['type'] == 'textarea') {
5284 /*$more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">'.$input['label'].'</div><div class="tagtd">';
5285 $more .= '<textarea name="'.$input['name'].'" class="'.$morecss.'"'.$moreattr.'>';
5286 $more .= $input['value'];
5287 $more .= '</textarea>';
5288 $more .= '</div></div>'."\n";*/
5289 $moreonecolumn .= '<div class="margintoponly">';
5290 $moreonecolumn .= $input['label'] . '<br>';
5291 $moreonecolumn .= '<textarea name="' . dol_escape_htmltag($input['name']) . '" id="' . dol_escape_htmltag($input['name']) . '" class="' . $morecss . '"' . $moreattr . '>';
5292 $moreonecolumn .= $input['value'];
5293 $moreonecolumn .= '</textarea>';
5294 $moreonecolumn .= '</div>';
5295 } elseif (in_array($input['type'], ['select', 'multiselect'])) {
5296 if (empty($morecss)) {
5297 $morecss = 'minwidth100';
5298 }
5299
5300 $show_empty = isset($input['select_show_empty']) ? $input['select_show_empty'] : 1;
5301 $key_in_label = isset($input['select_key_in_label']) ? $input['select_key_in_label'] : 0;
5302 $value_as_key = isset($input['select_value_as_key']) ? $input['select_value_as_key'] : 0;
5303 $translate = isset($input['select_translate']) ? $input['select_translate'] : 0;
5304 $maxlen = isset($input['select_maxlen']) ? $input['select_maxlen'] : 0;
5305 $disabled = isset($input['select_disabled']) ? $input['select_disabled'] : 0;
5306 $sort = isset($input['select_sort']) ? $input['select_sort'] : '';
5307
5308 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">';
5309 if (!empty($input['label'])) {
5310 $more .= $input['label'] . '</div><div class="tagtd left">';
5311 }
5312 if ($input['type'] == 'select') {
5313 $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);
5314 } else {
5315 $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);
5316 }
5317 $more .= '</div></div>' . "\n";
5318 } elseif ($input['type'] == 'checkbox') {
5319 $more .= '<div class="tagtr">';
5320 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '"><label for="' . dol_escape_htmltag($input['name']) . '">' . $input['label'] . '</label></div><div class="tagtd">';
5321 $more .= '<input type="checkbox" class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $moreattr;
5322 if (!is_bool($input['value']) && $input['value'] != 'false' && $input['value'] != '0' && $input['value'] != '') {
5323 $more .= ' checked';
5324 }
5325 if (is_bool($input['value']) && $input['value']) {
5326 $more .= ' checked';
5327 }
5328 if (isset($input['disabled'])) {
5329 $more .= ' disabled';
5330 }
5331 $more .= ' /></div>';
5332 $more .= '</div>' . "\n";
5333 } elseif ($input['type'] == 'radio') {
5334 $i = 0;
5335 foreach ($input['values'] as $selkey => $selval) {
5336 $more .= '<div class="tagtr">';
5337 if (isset($input['label'])) {
5338 if ($i == 0) {
5339 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? ' tdtop' : (' tdtop ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5340 } else {
5341 $more .= '<div clas="tagtd' . (empty($input['tdclass']) ? '' : (' "' . $input['tdclass'])) . '">&nbsp;</div>';
5342 }
5343 }
5344 $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;
5345 if (!empty($input['disabled'])) {
5346 $more .= ' disabled';
5347 }
5348 if (isset($input['default']) && $input['default'] === $selkey) {
5349 $more .= ' checked="checked"';
5350 }
5351 $more .= ' /> ';
5352 $more .= '<label for="' . dol_escape_htmltag($input['name'] . $selkey) . '" class="valignmiddle">' . $selval . '</label>';
5353 $more .= '</div></div>' . "\n";
5354 $i++;
5355 }
5356 } elseif ($input['type'] == 'date' || $input['type'] == 'datetime') {
5357 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5358 $more .= '<div class="tagtd">';
5359 $addnowlink = (empty($input['datenow']) ? 0 : 1);
5360 $h = $m = 0;
5361 if ($input['type'] == 'datetime') {
5362 $h = isset($input['hours']) ? $input['hours'] : 1;
5363 $m = isset($input['minutes']) ? $input['minutes'] : 1;
5364 }
5365 $more .= $this->selectDate($input['value'], $input['name'], $h, $m, 0, '', 1, $addnowlink);
5366 $more .= '</div></div>'."\n";
5367 $formquestion[] = array('name'=>$input['name'].'day');
5368 $formquestion[] = array('name'=>$input['name'].'month');
5369 $formquestion[] = array('name'=>$input['name'].'year');
5370 $formquestion[] = array('name'=>$input['name'].'hour');
5371 $formquestion[] = array('name'=>$input['name'].'min');
5372 } elseif ($input['type'] == 'other') { // can be 1 column or 2 depending if label is set or not
5373 $more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">';
5374 if (!empty($input['label'])) {
5375 $more .= $input['label'] . '</div><div class="tagtd">';
5376 }
5377 $more .= $input['value'];
5378 $more .= '</div></div>' . "\n";
5379 } elseif ($input['type'] == 'onecolumn') {
5380 $moreonecolumn .= '<div class="margintoponly">';
5381 $moreonecolumn .= $input['value'];
5382 $moreonecolumn .= '</div>' . "\n";
5383 } elseif ($input['type'] == 'hidden') {
5384 // Do nothing more, already added by a previous loop
5385 } elseif ($input['type'] == 'separator') {
5386 $more .= '<br>';
5387 } else {
5388 $more .= 'Error type ' . $input['type'] . ' for the confirm box is not a supported type';
5389 }
5390 }
5391 }
5392 $more .= '</div>' . "\n";
5393 $more .= $moreonecolumn;
5394 }
5395
5396 // JQUERY method dialog is broken with smartphone, we use standard HTML.
5397 // 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
5398 // See page product/card.php for example
5399 if (!empty($conf->dol_use_jmobile)) {
5400 $useajax = 0;
5401 }
5402 if (empty($conf->use_javascript_ajax)) {
5403 $useajax = 0;
5404 }
5405
5406 if ($useajax) {
5407 $autoOpen = true;
5408 $dialogconfirm = 'dialog-confirm';
5409 $button = '';
5410 if (!is_numeric($useajax)) {
5411 $button = $useajax;
5412 $useajax = 1;
5413 $autoOpen = false;
5414 $dialogconfirm .= '-' . $button;
5415 }
5416 $pageyes = $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=yes';
5417 $pageno = ($useajax == 2 ? $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=no' : '');
5418
5419 // Add input fields into list of fields to read during submit (inputok and inputko)
5420 if (is_array($formquestion)) {
5421 foreach ($formquestion as $key => $input) {
5422 //print "xx ".$key." rr ".is_array($input)."<br>\n";
5423 // Add name of fields to propagate with the GET when submitting the form with button OK.
5424 if (is_array($input) && isset($input['name'])) {
5425 if (strpos($input['name'], ',') > 0) {
5426 $inputok = array_merge($inputok, explode(',', $input['name']));
5427 } else {
5428 array_push($inputok, $input['name']);
5429 }
5430 }
5431 // Add name of fields to propagate with the GET when submitting the form with button KO.
5432 if (isset($input['inputko']) && $input['inputko'] == 1) {
5433 array_push($inputko, $input['name']);
5434 }
5435 }
5436 }
5437
5438 // Show JQuery confirm box.
5439 $formconfirm .= '<div id="' . $dialogconfirm . '" title="' . dol_escape_htmltag($title) . '" style="display: none;">';
5440 if (is_array($formquestion) && !empty($formquestion['text'])) {
5441 $formconfirm .= '<div class="confirmtext">' . $formquestion['text'] . '</div>' . "\n";
5442 }
5443 if (!empty($more)) {
5444 $formconfirm .= '<div class="confirmquestions">' . $more . '</div>' . "\n";
5445 }
5446 $formconfirm .= ($question ? '<div class="confirmmessage">' . img_help('', '') . ' ' . $question . '</div>' : '');
5447 $formconfirm .= '</div>' . "\n";
5448
5449 $formconfirm .= "\n<!-- begin code of popup for formconfirm page=" . $page . " -->\n";
5450 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5451 $formconfirm .= "/* Code for the jQuery('#dialogforpopup').dialog() */\n";
5452 $formconfirm .= 'jQuery(document).ready(function() {
5453 $(function() {
5454 $( "#' . $dialogconfirm . '" ).dialog(
5455 {
5456 autoOpen: ' . ($autoOpen ? "true" : "false") . ',';
5457 if ($newselectedchoice == 'no') {
5458 $formconfirm .= '
5459 open: function() {
5460 $(this).parent().find("button.ui-button:eq(2)").focus();
5461 },';
5462 }
5463
5464 $jsforcursor = '';
5465 if ($useajax == 1) {
5466 $jsforcursor = '// The call to urljump can be slow, so we set the wait cursor' . "\n";
5467 $jsforcursor .= 'jQuery("html,body,#id-container").addClass("cursorwait");' . "\n";
5468 }
5469
5470 $postconfirmas = 'GET';
5471
5472 $formconfirm .= '
5473 resizable: false,
5474 height: "' . $height . '",
5475 width: "' . $width . '",
5476 modal: true,
5477 closeOnEscape: false,
5478 buttons: {
5479 "' . dol_escape_js($langs->transnoentities($labelbuttonyes)) . '": function() {
5480 var options = "token=' . urlencode(newToken()) . '";
5481 var inputok = ' . json_encode($inputok) . '; /* List of fields into form */
5482 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5483 var pageyes = "' . dol_escape_js(!empty($pageyes) ? $pageyes : '') . '";
5484
5485 if (inputok.length > 0) {
5486 $.each(inputok, function(i, inputname) {
5487 var more = "";
5488 var inputvalue;
5489 if ($("input[name=\'" + inputname + "\']").attr("type") == "radio") {
5490 inputvalue = $("input[name=\'" + inputname + "\']:checked").val();
5491 } else {
5492 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5493 inputvalue = $("#" + inputname + more).val();
5494 }
5495 if (typeof inputvalue == "undefined") { inputvalue=""; }
5496 console.log("formconfirm check inputname="+inputname+" inputvalue="+inputvalue);
5497 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5498 });
5499 }
5500 var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "&") + options;
5501 if (pageyes.length > 0) {';
5502 if ($postconfirmas == 'GET') {
5503 $formconfirm .= 'location.href = urljump;';
5504 } else {
5505 $formconfirm .= $jsforcursor;
5506 $formconfirm .= 'var post = $.post(
5507 pageyes,
5508 options,
5509 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5510 );';
5511 }
5512 $formconfirm .= '
5513 console.log("after post ok");
5514 }
5515 $(this).dialog("close");
5516 },
5517 "' . dol_escape_js($langs->transnoentities($labelbuttonno)) . '": function() {
5518 var options = "token=' . urlencode(newToken()) . '";
5519 var inputko = ' . json_encode($inputko) . '; /* List of fields into form */
5520 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5521 var pageno="' . dol_escape_js(!empty($pageno) ? $pageno : '') . '";
5522 if (inputko.length > 0) {
5523 $.each(inputko, function(i, inputname) {
5524 var more = "";
5525 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5526 var inputvalue = $("#" + inputname + more).val();
5527 if (typeof inputvalue == "undefined") { inputvalue=""; }
5528 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5529 });
5530 }
5531 var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "&") + options;
5532 //alert(urljump);
5533 if (pageno.length > 0) {';
5534 if ($postconfirmas == 'GET') {
5535 $formconfirm .= 'location.href = urljump;';
5536 } else {
5537 $formconfirm .= $jsforcursor;
5538 $formconfirm .= 'var post = $.post(
5539 pageno,
5540 options,
5541 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5542 );';
5543 }
5544 $formconfirm .= '
5545 console.log("after post ko");
5546 }
5547 $(this).dialog("close");
5548 }
5549 }
5550 }
5551 );
5552
5553 var button = "' . $button . '";
5554 if (button.length > 0) {
5555 $( "#" + button ).click(function() {
5556 $("#' . $dialogconfirm . '").dialog("open");
5557 });
5558 }
5559 });
5560 });
5561 </script>';
5562 $formconfirm .= "<!-- end ajax formconfirm -->\n";
5563 } else {
5564 $formconfirm .= "\n<!-- begin formconfirm page=" . dol_escape_htmltag($page) . " -->\n";
5565
5566 if (empty($disableformtag)) {
5567 $formconfirm .= '<form method="POST" action="' . $page . '" class="notoptoleftroright">' . "\n";
5568 }
5569
5570 $formconfirm .= '<input type="hidden" name="action" value="' . $action . '">' . "\n";
5571 $formconfirm .= '<input type="hidden" name="token" value="' . newToken() . '">' . "\n";
5572
5573 $formconfirm .= '<table class="valid centpercent">' . "\n";
5574
5575 // Line title
5576 $formconfirm .= '<tr class="validtitre"><td class="validtitre" colspan="2">';
5577 $formconfirm .= img_picto('', 'pictoconfirm') . ' ' . $title;
5578 $formconfirm .= '</td></tr>' . "\n";
5579
5580 // Line text
5581 if (is_array($formquestion) && !empty($formquestion['text'])) {
5582 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . $formquestion['text'] . '</td></tr>' . "\n";
5583 }
5584
5585 // Line form fields
5586 if ($more) {
5587 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . "\n";
5588 $formconfirm .= $more;
5589 $formconfirm .= '</td></tr>' . "\n";
5590 }
5591
5592 // Line with question
5593 $formconfirm .= '<tr class="valid">';
5594 $formconfirm .= '<td class="valid">' . $question . '</td>';
5595 $formconfirm .= '<td class="valid center">';
5596 $formconfirm .= $this->selectyesno("confirm", $newselectedchoice, 0, false, 0, 0, 'marginleftonly marginrightonly', $labelbuttonyes, $labelbuttonno);
5597 $formconfirm .= '<input class="button valignmiddle confirmvalidatebutton small" type="submit" value="' . $langs->trans("Validate") . '">';
5598 $formconfirm .= '</td>';
5599 $formconfirm .= '</tr>' . "\n";
5600
5601 $formconfirm .= '</table>' . "\n";
5602
5603 if (empty($disableformtag)) {
5604 $formconfirm .= "</form>\n";
5605 }
5606 $formconfirm .= '<br>';
5607
5608 if (!empty($conf->use_javascript_ajax)) {
5609 $formconfirm .= '<!-- code to disable button to avoid double clic -->';
5610 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5611 $formconfirm .= '
5612 $(document).ready(function () {
5613 $(".confirmvalidatebutton").on("click", function() {
5614 console.log("We click on button confirmvalidatebutton");
5615 $(this).attr("disabled", "disabled");
5616 setTimeout(\'$(".confirmvalidatebutton").removeAttr("disabled")\', 3000);
5617 //console.log($(this).closest("form"));
5618 $(this).closest("form").submit();
5619 });
5620 });
5621 ';
5622 $formconfirm .= '</script>' . "\n";
5623 }
5624
5625 $formconfirm .= "<!-- end formconfirm -->\n";
5626 }
5627
5628 return $formconfirm;
5629 }
5630
5631
5632 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5633
5649 public function form_project($page, $socid, $selected = '', $htmlname = 'projectid', $discard_closed = 0, $maxlength = 20, $forcefocus = 0, $nooutput = 0, $textifnoproject = '', $morecss = '')
5650 {
5651 // phpcs:enable
5652 global $langs;
5653
5654 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
5655 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
5656
5657 $out = '';
5658
5659 $formproject = new FormProjets($this->db);
5660
5661 $langs->load("project");
5662 if ($htmlname != "none") {
5663 $out .= '<form method="post" action="' . $page . '">';
5664 $out .= '<input type="hidden" name="action" value="classin">';
5665 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5666 $out .= $formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1, 0, $morecss);
5667 $out .= '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5668 $out .= '</form>';
5669 } else {
5670 $out .= '<span class="project_head_block">';
5671 if ($selected) {
5672 $projet = new Project($this->db);
5673 $projet->fetch($selected);
5674 $out .= $projet->getNomUrl(0, '', 1);
5675 } else {
5676 $out .= '<span class="opacitymedium">' . $textifnoproject . '</span>';
5677 }
5678 $out .= '</span>';
5679 }
5680
5681 if (empty($nooutput)) {
5682 print $out;
5683 return '';
5684 }
5685 return $out;
5686 }
5687
5688 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5689
5705 public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0, $type = '', $filtertype = -1, $deposit_percent = -1, $nooutput = 0)
5706 {
5707 // phpcs:enable
5708 global $langs;
5709
5710 $out = '';
5711
5712 if ($htmlname != "none") {
5713 $out .= '<form method="POST" action="' . $page . '">';
5714 $out .= '<input type="hidden" name="action" value="setconditions">';
5715 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5716 if ($type) {
5717 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5718 }
5719 $out .= $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, 0, '', $deposit_percent);
5720 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5721 $out .= '</form>';
5722 } else {
5723 if ($selected) {
5725 if (isset($this->cache_conditions_paiements[$selected])) {
5726 $label = $this->cache_conditions_paiements[$selected]['label'];
5727
5728 if (!empty($this->cache_conditions_paiements[$selected]['deposit_percent'])) {
5729 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $this->cache_conditions_paiements[$selected]['deposit_percent'], $label);
5730 }
5731
5732 $out .= $label;
5733 } else {
5734 $langs->load('errors');
5735 $out .= $langs->trans('ErrorNotInDictionaryPaymentConditions');
5736 }
5737 } else {
5738 $out .= '&nbsp;';
5739 }
5740 }
5741
5742 if (empty($nooutput)) {
5743 print $out;
5744 return '';
5745 }
5746 return $out;
5747 }
5748
5749 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5750
5760 public function form_availability($page, $selected = '', $htmlname = 'availability', $addempty = 0)
5761 {
5762 // phpcs:enable
5763 global $langs;
5764 if ($htmlname != "none") {
5765 print '<form method="post" action="' . $page . '">';
5766 print '<input type="hidden" name="action" value="setavailability">';
5767 print '<input type="hidden" name="token" value="' . newToken() . '">';
5768 $this->selectAvailabilityDelay($selected, $htmlname, -1, $addempty);
5769 print '<input type="submit" name="modify" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5770 print '<input type="submit" name="cancel" class="button smallpaddingimp" value="' . $langs->trans("Cancel") . '">';
5771 print '</form>';
5772 } else {
5773 if ($selected) {
5774 $this->load_cache_availability();
5775 print $this->cache_availability[$selected]['label'];
5776 } else {
5777 print "&nbsp;";
5778 }
5779 }
5780 }
5781
5792 public function formInputReason($page, $selected = '', $htmlname = 'demandreason', $addempty = 0)
5793 {
5794 global $langs;
5795 if ($htmlname != "none") {
5796 print '<form method="post" action="' . $page . '">';
5797 print '<input type="hidden" name="action" value="setdemandreason">';
5798 print '<input type="hidden" name="token" value="' . newToken() . '">';
5799 $this->selectInputReason($selected, $htmlname, -1, $addempty);
5800 print '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5801 print '</form>';
5802 } else {
5803 if ($selected) {
5804 $this->loadCacheInputReason();
5805 foreach ($this->cache_demand_reason as $key => $val) {
5806 if ($val['id'] == $selected) {
5807 print $val['label'];
5808 break;
5809 }
5810 }
5811 } else {
5812 print "&nbsp;";
5813 }
5814 }
5815 }
5816
5817 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5818
5832 public function form_date($page, $selected, $htmlname, $displayhour = 0, $displaymin = 0, $nooutput = 0, $type = '')
5833 {
5834 // phpcs:enable
5835 global $langs;
5836
5837 $ret = '';
5838
5839 if ($htmlname != "none") {
5840 $ret .= '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
5841 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
5842 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
5843 if ($type) {
5844 $ret .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5845 }
5846 $ret .= '<table class="nobordernopadding">';
5847 $ret .= '<tr><td>';
5848 $ret .= $this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form' . $htmlname, 1, 0);
5849 $ret .= '</td>';
5850 $ret .= '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
5851 $ret .= '</tr></table></form>';
5852 } else {
5853 if ($displayhour) {
5854 $ret .= dol_print_date($selected, 'dayhour');
5855 } else {
5856 $ret .= dol_print_date($selected, 'day');
5857 }
5858 }
5859
5860 if (empty($nooutput)) {
5861 print $ret;
5862 }
5863 return $ret;
5864 }
5865
5866
5867 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5868
5879 public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = array(), $include = array())
5880 {
5881 // phpcs:enable
5882 global $langs;
5883
5884 if ($htmlname != "none") {
5885 print '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
5886 print '<input type="hidden" name="action" value="set' . $htmlname . '">';
5887 print '<input type="hidden" name="token" value="' . newToken() . '">';
5888 print $this->select_dolusers($selected, $htmlname, 1, $exclude, 0, $include);
5889 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5890 print '</form>';
5891 } else {
5892 if ($selected) {
5893 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
5894 $theuser = new User($this->db);
5895 $theuser->fetch($selected);
5896 print $theuser->getNomUrl(1);
5897 } else {
5898 print "&nbsp;";
5899 }
5900 }
5901 }
5902
5903
5904 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5905
5919 public function form_modes_reglement($page, $selected = '', $htmlname = 'mode_reglement_id', $filtertype = '', $active = 1, $addempty = 0, $type = '', $nooutput = 0)
5920 {
5921 // phpcs:enable
5922 global $langs;
5923
5924 $out = '';
5925 if ($htmlname != "none") {
5926 $out .= '<form method="POST" action="' . $page . '">';
5927 $out .= '<input type="hidden" name="action" value="setmode">';
5928 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5929 if ($type) {
5930 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5931 }
5932 $out .= $this->select_types_paiements($selected, $htmlname, $filtertype, 0, $addempty, 0, 0, $active, '', 1);
5933 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5934 $out .= '</form>';
5935 } else {
5936 if ($selected) {
5938 $out .= $this->cache_types_paiements[$selected]['label'];
5939 } else {
5940 $out .= "&nbsp;";
5941 }
5942 }
5943
5944 if ($nooutput) {
5945 return $out;
5946 } else {
5947 print $out;
5948 }
5949 return '';
5950 }
5951
5962 public function formSelectTransportMode($page, $selected = '', $htmlname = 'transport_mode_id', $active = 1, $addempty = 0)
5963 {
5964 global $langs;
5965 if ($htmlname != "none") {
5966 print '<form method="POST" action="' . $page . '">';
5967 print '<input type="hidden" name="action" value="settransportmode">';
5968 print '<input type="hidden" name="token" value="' . newToken() . '">';
5969 $this->selectTransportMode($selected, $htmlname, 0, $addempty, 0, 0, $active);
5970 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5971 print '</form>';
5972 } else {
5973 if ($selected) {
5975 print $this->cache_transport_mode[$selected]['label'];
5976 } else {
5977 print "&nbsp;";
5978 }
5979 }
5980 }
5981
5982 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5983
5992 public function form_multicurrency_code($page, $selected = '', $htmlname = 'multicurrency_code')
5993 {
5994 // phpcs:enable
5995 global $langs;
5996 if ($htmlname != "none") {
5997 print '<form method="POST" action="' . $page . '">';
5998 print '<input type="hidden" name="action" value="setmulticurrencycode">';
5999 print '<input type="hidden" name="token" value="' . newToken() . '">';
6000 print $this->selectMultiCurrency($selected, $htmlname, 0);
6001 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6002 print '</form>';
6003 } else {
6004 dol_include_once('/core/lib/company.lib.php');
6005 print !empty($selected) ? currency_name($selected, 1) : '&nbsp;';
6006 }
6007 }
6008
6009 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6010
6020 public function form_multicurrency_rate($page, $rate = 0.0, $htmlname = 'multicurrency_tx', $currency = '')
6021 {
6022 // phpcs:enable
6023 global $langs, $mysoc, $conf;
6024
6025 if ($htmlname != "none") {
6026 print '<form method="POST" action="' . $page . '">';
6027 print '<input type="hidden" name="action" value="setmulticurrencyrate">';
6028 print '<input type="hidden" name="token" value="' . newToken() . '">';
6029 print '<input type="text" class="maxwidth100" name="' . $htmlname . '" value="' . (!empty($rate) ? price(price2num($rate, 'CU')) : 1) . '" /> ';
6030 print '<select name="calculation_mode">';
6031 print '<option value="1">Change ' . $langs->trans("PriceUHT") . ' of lines</option>';
6032 print '<option value="2">Change ' . $langs->trans("PriceUHTCurrency") . ' of lines</option>';
6033 print '</select> ';
6034 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6035 print '</form>';
6036 } else {
6037 if (!empty($rate)) {
6038 print price($rate, 1, $langs, 0, 0);
6039 if ($currency && $rate != 1) {
6040 print ' &nbsp; (' . price($rate, 1, $langs, 0, 0) . ' ' . $currency . ' = 1 ' . $conf->currency . ')';
6041 }
6042 } else {
6043 print 1;
6044 }
6045 }
6046 }
6047
6048
6049 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6050
6066 public function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter = '', $maxvalue = 0, $more = '', $hidelist = 0, $discount_type = 0)
6067 {
6068 // phpcs:enable
6069 global $conf, $langs;
6070 if ($htmlname != "none") {
6071 print '<form method="post" action="' . $page . '">';
6072 print '<input type="hidden" name="action" value="setabsolutediscount">';
6073 print '<input type="hidden" name="token" value="' . newToken() . '">';
6074 print '<div class="inline-block">';
6075 if (!empty($discount_type)) {
6076 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
6077 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL") {
6078 $translationKey = 'HasAbsoluteDiscountFromSupplier'; // If we want deposit to be substracted to payments only and not to total of final invoice
6079 } else {
6080 $translationKey = 'HasCreditNoteFromSupplier';
6081 }
6082 } else {
6083 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6084 $translationKey = 'HasAbsoluteDiscountFromSupplier';
6085 } else {
6086 $translationKey = 'HasCreditNoteFromSupplier';
6087 }
6088 }
6089 } else {
6090 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
6091 if (!$filter || $filter == "fk_facture_source IS NULL") {
6092 $translationKey = 'CompanyHasAbsoluteDiscount'; // If we want deposit to be substracted to payments only and not to total of final invoice
6093 } else {
6094 $translationKey = 'CompanyHasCreditNote';
6095 }
6096 } else {
6097 if (!$filter || $filter == "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6098 $translationKey = 'CompanyHasAbsoluteDiscount';
6099 } else {
6100 $translationKey = 'CompanyHasCreditNote';
6101 }
6102 }
6103 }
6104 print $langs->trans($translationKey, price($amount, 0, $langs, 0, 0, -1, $conf->currency));
6105 if (empty($hidelist)) {
6106 print ' ';
6107 }
6108 print '</div>';
6109 if (empty($hidelist)) {
6110 print '<div class="inline-block" style="padding-right: 10px">';
6111 $newfilter = 'discount_type=' . intval($discount_type);
6112 if (!empty($discount_type)) {
6113 $newfilter .= ' AND fk_invoice_supplier IS NULL AND fk_invoice_supplier_line IS NULL'; // Supplier discounts available
6114 } else {
6115 $newfilter .= ' AND fk_facture IS NULL AND fk_facture_line IS NULL'; // Customer discounts available
6116 }
6117 if ($filter) {
6118 $newfilter .= ' AND (' . $filter . ')';
6119 }
6120 // output the combo of discounts
6121 $nbqualifiedlines = $this->select_remises($selected, $htmlname, $newfilter, $socid, $maxvalue);
6122 if ($nbqualifiedlines > 0) {
6123 print ' &nbsp; <input type="submit" class="button smallpaddingimp" value="' . dol_escape_htmltag($langs->trans("UseLine")) . '"';
6124 if (!empty($discount_type) && $filter && $filter != "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6125 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6126 }
6127 if (empty($discount_type) && $filter && $filter != "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6128 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6129 }
6130
6131 print '>';
6132 }
6133 print '</div>';
6134 }
6135 if ($more) {
6136 print '<div class="inline-block">';
6137 print $more;
6138 print '</div>';
6139 }
6140 print '</form>';
6141 } else {
6142 if ($selected) {
6143 print $selected;
6144 } else {
6145 print "0";
6146 }
6147 }
6148 }
6149
6150
6151 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6152
6162 public function form_contacts($page, $societe, $selected = '', $htmlname = 'contactid')
6163 {
6164 // phpcs:enable
6165 global $langs, $conf;
6166
6167 if ($htmlname != "none") {
6168 print '<form method="post" action="' . $page . '">';
6169 print '<input type="hidden" name="action" value="set_contact">';
6170 print '<input type="hidden" name="token" value="' . newToken() . '">';
6171 print '<table class="nobordernopadding">';
6172 print '<tr><td>';
6173 print $this->selectcontacts($societe->id, $selected, $htmlname);
6174 $num = $this->num;
6175 if ($num == 0) {
6176 $addcontact = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("AddContact") : $langs->trans("AddContactAddress"));
6177 print '<a href="' . DOL_URL_ROOT . '/contact/card.php?socid=' . $societe->id . '&amp;action=create&amp;backtoreferer=1">' . $addcontact . '</a>';
6178 }
6179 print '</td>';
6180 print '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6181 print '</tr></table></form>';
6182 } else {
6183 if ($selected) {
6184 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
6185 $contact = new Contact($this->db);
6186 $contact->fetch($selected);
6187 print $contact->getFullName($langs);
6188 } else {
6189 print "&nbsp;";
6190 }
6191 }
6192 }
6193
6194 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6195
6212 public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0, $excludeids = array(), $textifnothirdparty = '')
6213 {
6214 // phpcs:enable
6215 global $langs;
6216
6217 $out = '';
6218 if ($htmlname != "none") {
6219 $out .= '<form method="post" action="' . $page . '">';
6220 $out .= '<input type="hidden" name="action" value="set_thirdparty">';
6221 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6222 $out .= $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, 0, 'minwidth100', '', '', 1, array(), false, $excludeids);
6223 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6224 $out .= '</form>';
6225 } else {
6226 if ($selected) {
6227 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
6228 $soc = new Societe($this->db);
6229 $soc->fetch($selected);
6230 $out .= $soc->getNomUrl(0, '');
6231 } else {
6232 $out .= '<span class="opacitymedium">' . $textifnothirdparty . '</span>';
6233 }
6234 }
6235
6236 if ($nooutput) {
6237 return $out;
6238 } else {
6239 print $out;
6240 }
6241
6242 return '';
6243 }
6244
6245 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6246
6255 public function select_currency($selected = '', $htmlname = 'currency_id')
6256 {
6257 // phpcs:enable
6258 print $this->selectCurrency($selected, $htmlname);
6259 }
6260
6270 public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0, $useempty = '')
6271 {
6272 global $conf, $langs, $user;
6273
6274 $langs->loadCacheCurrencies('');
6275
6276 $out = '';
6277
6278 if ($selected == 'euro' || $selected == 'euros') {
6279 $selected = 'EUR'; // Pour compatibilite
6280 }
6281
6282 $out .= '<select class="flat maxwidth200onsmartphone minwidth300" name="' . $htmlname . '" id="' . $htmlname . '">';
6283 if ($useempty) {
6284 $out .= '<option value="-1" selected></option>';
6285 }
6286 foreach ($langs->cache_currencies as $code_iso => $currency) {
6287 $labeltoshow = $currency['label'];
6288 if ($mode == 1) {
6289 $labeltoshow .= ' <span class="opacitymedium">(' . $code_iso . ')</span>';
6290 } else {
6291 $labeltoshow .= ' <span class="opacitymedium">(' . $langs->getCurrencySymbol($code_iso) . ')</span>';
6292 }
6293
6294 if ($selected && $selected == $code_iso) {
6295 $out .= '<option value="' . $code_iso . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6296 } else {
6297 $out .= '<option value="' . $code_iso . '" data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6298 }
6299 $out .= $labeltoshow;
6300 $out .= '</option>';
6301 }
6302 $out .= '</select>';
6303 if ($user->admin) {
6304 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
6305 }
6306
6307 // Make select dynamic
6308 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6309 $out .= ajax_combobox($htmlname);
6310
6311 return $out;
6312 }
6313
6326 public function selectMultiCurrency($selected = '', $htmlname = 'multicurrency_code', $useempty = 0, $filter = '', $excludeConfCurrency = false, $morecss = '')
6327 {
6328 global $conf, $langs;