dolibarr 20.0.5
html.form.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
5 * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
6 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
7 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com>
8 * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
9 * Copyright (C) 2006 Marc Barilley/Ocebo <marc@ocebo.com>
10 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerker@telenet.be>
11 * Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
12 * Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
13 * Copyright (C) 2010-2021 Philippe Grand <philippe.grand@atoo-net.com>
14 * Copyright (C) 2011 Herve Prot <herve.prot@symeos.com>
15 * Copyright (C) 2012-2016 Marcos García <marcosgdf@gmail.com>
16 * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
17 * Copyright (C) 2012-2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
18 * Copyright (C) 2014-2023 Alexandre Spangaro <aspangaro@open-dsi.fr>
19 * Copyright (C) 2018-2022 Ferran Marcet <fmarcet@2byte.es>
20 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
21 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
22 * Copyright (C) 2018 Christophe Battarel <christophe@altairis.fr>
23 * Copyright (C) 2018 Josep Lluis Amador <joseplluis@lliuretic.cat>
24 * Copyright (C) 2023 Joachim Kueter <git-jk@bloxera.com>
25 * Copyright (C) 2023 Nick Fragoulis
26 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
27 *
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation; either version 3 of the License, or
31 * (at your option) any later version.
32 *
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
37 *
38 * You should have received a copy of the GNU General Public License
39 * along with this program. If not, see <https://www.gnu.org/licenses/>.
40 */
41
55class Form
56{
60 public $db;
61
65 public $error = '';
66
70 public $errors = array();
71
72 // Some properties used to return data by some methods
74 public $result;
76 public $num;
77
78 // Cache arrays
79 public $cache_types_paiements = array();
80 public $cache_conditions_paiements = array();
81 public $cache_transport_mode = array();
82 public $cache_availability = array();
83 public $cache_demand_reason = array();
84 public $cache_types_fees = array();
85 public $cache_vatrates = array();
86 public $cache_invoice_subtype = array();
87
88
94 public function __construct($db)
95 {
96 $this->db = $db;
97 }
98
115 public function editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata = 'string', $moreparam = '', $fieldrequired = 0, $notabletag = 0, $paramid = 'id', $help = '')
116 {
117 global $langs;
118
119 $ret = '';
120
121 // TODO change for compatibility
122 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;/', $typeofdata)) {
123 if (!empty($perm)) {
124 $tmp = explode(':', $typeofdata);
125 $ret .= '<div class="editkey_' . $tmp[0] . (!empty($tmp[1]) ? ' ' . $tmp[1] : '') . '" id="' . $htmlname . '">';
126 if ($fieldrequired) {
127 $ret .= '<span class="fieldrequired">';
128 }
129 if ($help) {
130 $ret .= $this->textwithpicto($langs->trans($text), $help);
131 } else {
132 $ret .= $langs->trans($text);
133 }
134 if ($fieldrequired) {
135 $ret .= '</span>';
136 }
137 $ret .= '</div>' . "\n";
138 } else {
139 if ($fieldrequired) {
140 $ret .= '<span class="fieldrequired">';
141 }
142 if ($help) {
143 $ret .= $this->textwithpicto($langs->trans($text), $help);
144 } else {
145 $ret .= $langs->trans($text);
146 }
147 if ($fieldrequired) {
148 $ret .= '</span>';
149 }
150 }
151 } else {
152 if (empty($notabletag) && $perm) {
153 $ret .= '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
154 }
155 if ($fieldrequired) {
156 $ret .= '<span class="fieldrequired">';
157 }
158 if ($help) {
159 $ret .= $this->textwithpicto($langs->trans($text), $help);
160 } else {
161 $ret .= $langs->trans($text);
162 }
163 if ($fieldrequired) {
164 $ret .= '</span>';
165 }
166 if (!empty($notabletag)) {
167 $ret .= ' ';
168 }
169 if (empty($notabletag) && $perm) {
170 $ret .= '</td>';
171 }
172 if (empty($notabletag) && $perm) {
173 $ret .= '<td class="right">';
174 }
175 if ($htmlname && GETPOST('action', 'aZ09') != 'edit' . $htmlname && $perm) {
176 $ret .= '<a class="editfielda reposition" href="' . $_SERVER["PHP_SELF"] . '?action=edit' . $htmlname . '&token=' . newToken() . '&' . $paramid . '=' . $object->id . $moreparam . '">' . img_edit($langs->trans('Edit'), ($notabletag ? 0 : 1)) . '</a>';
177 }
178 if (!empty($notabletag) && $notabletag == 1) {
179 if ($text) {
180 $ret .= ' : ';
181 } else {
182 $ret .= ' ';
183 }
184 }
185 if (!empty($notabletag) && $notabletag == 3) {
186 $ret .= ' ';
187 }
188 if (empty($notabletag) && $perm) {
189 $ret .= '</td>';
190 }
191 if (empty($notabletag) && $perm) {
192 $ret .= '</tr></table>';
193 }
194 }
195
196 return $ret;
197 }
198
222 public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 1, $formatfunc = '', $paramid = 'id', $gm = 'auto', $moreoptions = array(), $editaction = '')
223 {
224 global $conf, $langs;
225
226 $ret = '';
227
228 // Check parameters
229 if (empty($typeofdata)) {
230 return 'ErrorBadParameter typeofdata is empty';
231 }
232 // Clean parameter $typeofdata
233 if ($typeofdata == 'datetime') {
234 $typeofdata = 'dayhour';
235 }
236 $reg = array();
237 if (preg_match('/^(\w+)\‍((\d+)\‍)$/', $typeofdata, $reg)) {
238 if ($reg[1] == 'varchar') {
239 $typeofdata = 'string';
240 } elseif ($reg[1] == 'int') {
241 $typeofdata = 'numeric';
242 } else {
243 return 'ErrorBadParameter ' . $typeofdata;
244 }
245 }
246
247 // When option to edit inline is activated
248 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;|day|datepicker|dayhour|datehourpicker/', $typeofdata)) { // TODO add jquery timepicker and support select
249 $ret .= $this->editInPlace($object, $value, $htmlname, $perm, $typeofdata, $editvalue, $extObject, $custommsg);
250 } else {
251 if ($editaction == '') {
252 $editaction = GETPOST('action', 'aZ09');
253 }
254 $editmode = ($editaction == 'edit' . $htmlname);
255 if ($editmode) { // edit mode
256 $ret .= "\n";
257 $ret .= '<form method="post" action="' . $_SERVER["PHP_SELF"] . ($moreparam ? '?' . $moreparam : '') . '">';
258 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
259 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
260 $ret .= '<input type="hidden" name="' . $paramid . '" value="' . $object->id . '">';
261 if (empty($notabletag)) {
262 $ret .= '<table class="nobordernopadding centpercent">';
263 }
264 if (empty($notabletag)) {
265 $ret .= '<tr><td>';
266 }
267 if (preg_match('/^(string|safehtmlstring|email|phone|url)/', $typeofdata)) {
268 $tmp = explode(':', $typeofdata);
269 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($editvalue ? $editvalue : $value) . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
270 } elseif (preg_match('/^(integer)/', $typeofdata)) {
271 $tmp = explode(':', $typeofdata);
272 $valuetoshow = price2num($editvalue ? $editvalue : $value, 0);
273 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . $valuetoshow . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
274 } elseif (preg_match('/^(numeric|amount)/', $typeofdata)) {
275 $tmp = explode(':', $typeofdata);
276 $valuetoshow = price2num($editvalue ? $editvalue : $value);
277 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($valuetoshow != '' ? price($valuetoshow) : '') . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
278 } elseif (preg_match('/^(checkbox)/', $typeofdata)) {
279 $tmp = explode(':', $typeofdata);
280 $ret .= '<input type="checkbox" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($value ? $value : 'on') . '"' . ($value ? ' checked' : '') . (empty($tmp[1]) ? '' : $tmp[1]) . '/>';
281 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) { // if wysiwyg is enabled $typeofdata = 'ckeditor'
282 $tmp = explode(':', $typeofdata);
283 $cols = (empty($tmp[2]) ? '' : $tmp[2]);
284 $morealt = '';
285 if (preg_match('/%/', $cols)) {
286 $morealt = ' style="width: ' . $cols . '"';
287 $cols = '';
288 }
289 $valuetoshow = ($editvalue ? $editvalue : $value);
290 $ret .= '<textarea id="' . $htmlname . '" name="' . $htmlname . '" wrap="soft" rows="' . (empty($tmp[1]) ? '20' : $tmp[1]) . '"' . ($cols ? ' cols="' . $cols . '"' : 'class="quatrevingtpercent"') . $morealt . '" autofocus>';
291 // textarea convert automatically entities chars into simple chars.
292 // So we convert & into &amp; so a string like 'a &lt; <b>b</b><br>é<br>&lt;script&gt;alert('X');&lt;script&gt;' stay a correct html and is not converted by textarea component when wysiwyg is off.
293 $valuetoshow = str_replace('&', '&amp;', $valuetoshow);
294 $ret .= dol_htmlwithnojs(dol_string_neverthesehtmltags($valuetoshow, array('textarea')));
295 $ret .= '</textarea><div class="clearboth"></div>';
296 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
297 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
298 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
299 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
300 $ret .= $this->selectDate($value, $htmlname, 0, 0, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
301 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
302 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
303 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
304 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
305 $ret .= $this->selectDate($value, $htmlname, 1, 1, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
306 } elseif (preg_match('/^select;/', $typeofdata)) {
307 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
308 $arraylist = array();
309 foreach ($arraydata as $val) {
310 $tmp = explode(':', $val);
311 $tmpkey = str_replace('|', ':', $tmp[0]);
312 $arraylist[$tmpkey] = $tmp[1];
313 }
314 $ret .= $this->selectarray($htmlname, $arraylist, $value);
315 } elseif (preg_match('/^link/', $typeofdata)) {
316 // TODO Not yet implemented. See code for extrafields
317 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
318 $tmp = explode(':', $typeofdata); // Example: ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols:uselocalbrowser
319 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
320 $doleditor = new DolEditor($htmlname, ($editvalue ? $editvalue : $value), (empty($tmp[2]) ? '' : $tmp[2]), (empty($tmp[3]) ? '100' : $tmp[3]), (empty($tmp[1]) ? 'dolibarr_notes' : $tmp[1]), 'In', (empty($tmp[5]) ? 0 : $tmp[5]), (isset($tmp[8]) ? ($tmp[8] ? true : false) : true), true, (empty($tmp[6]) ? '20' : $tmp[6]), (empty($tmp[7]) ? '100' : $tmp[7]));
321 $ret .= $doleditor->Create(1);
322 } elseif ($typeofdata == 'asis') {
323 $ret .= ($editvalue ? $editvalue : $value);
324 }
325 if (empty($notabletag)) {
326 $ret .= '</td>';
327 }
328
329 // Button save-cancel
330 if (empty($notabletag)) {
331 $ret .= '<td>';
332 }
333 //else $ret.='<div class="clearboth"></div>';
334 $ret .= '<input type="submit" class="smallpaddingimp button' . (empty($notabletag) ? '' : ' ') . '" name="modify" value="' . $langs->trans("Modify") . '">';
335 if (preg_match('/ckeditor|textarea/', $typeofdata) && empty($notabletag)) {
336 $ret .= '<br>' . "\n";
337 }
338 $ret .= '<input type="submit" class="smallpaddingimp button button-cancel' . (empty($notabletag) ? '' : ' ') . '" name="cancel" value="' . $langs->trans("Cancel") . '">';
339 if (empty($notabletag)) {
340 $ret .= '</td>';
341 }
342
343 if (empty($notabletag)) {
344 $ret .= '</tr></table>' . "\n";
345 }
346 $ret .= '</form>' . "\n";
347 } else { // view mode
348 if (preg_match('/^email/', $typeofdata)) {
349 $ret .= dol_print_email($value, 0, 0, 0, 0, 1);
350 } elseif (preg_match('/^phone/', $typeofdata)) {
351 $ret .= dol_print_phone($value, '_blank', 32, 1);
352 } elseif (preg_match('/^url/', $typeofdata)) {
353 $ret .= dol_print_url($value, '_blank', 32, 1);
354 } elseif (preg_match('/^(amount|numeric)/', $typeofdata)) {
355 $ret .= ($value != '' ? price($value, 0, $langs, 0, -1, -1, $conf->currency) : '');
356 } elseif (preg_match('/^checkbox/', $typeofdata)) {
357 $tmp = explode(':', $typeofdata);
358 $ret .= '<input type="checkbox" disabled id="' . $htmlname . '" name="' . $htmlname . '" value="' . $value . '"' . ($value ? ' checked' : '') . ($tmp[1] ? $tmp[1] : '') . '/>';
359 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) {
361 } elseif (preg_match('/^(safehtmlstring|restricthtml)/', $typeofdata)) { // 'restricthtml' is not an allowed type for editfieldval. Value is 'safehtmlstring'
363 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
364 $ret .= '<span class="valuedate">' . dol_print_date($value, 'day', $gm) . '</span>';
365 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
366 $ret .= '<span class="valuedate">' . dol_print_date($value, 'dayhour', $gm) . '</span>';
367 } elseif (preg_match('/^select;/', $typeofdata)) {
368 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
369 $arraylist = array();
370 foreach ($arraydata as $val) {
371 $tmp = explode(':', $val);
372 $arraylist[$tmp[0]] = $tmp[1];
373 }
374 $ret .= $arraylist[$value];
375 if ($htmlname == 'fk_product_type') {
376 if ($value == 0) {
377 $ret = img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
378 } else {
379 $ret = img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
380 }
381 }
382 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
383 $tmpcontent = dol_htmlentitiesbr($value);
384 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
385 $firstline = preg_replace('/<br>.*/', '', $tmpcontent);
386 $firstline = preg_replace('/[\n\r].*/', '', $firstline);
387 $tmpcontent = $firstline . ((strlen($firstline) != strlen($tmpcontent)) ? '...' : '');
388 }
389 // We don't use dol_escape_htmltag to get the html formatting active, but this need we must also
390 // clean data from some dangerous html
392 } else {
393 if (empty($moreoptions['valuealreadyhtmlescaped'])) {
394 $ret .= dol_escape_htmltag($value);
395 } else {
396 $ret .= $value; // $value must be already html escaped.
397 }
398 }
399
400 // Custom format if parameter $formatfunc has been provided
401 if ($formatfunc && method_exists($object, $formatfunc)) {
402 $ret = $object->$formatfunc($ret);
403 }
404 }
405 }
406 return $ret;
407 }
408
420 public function widgetForTranslation($fieldname, $object, $perm, $typeofdata = 'string', $check = '', $morecss = '')
421 {
422 global $conf, $langs, $extralanguages;
423
424 $result = '';
425
426 // List of extra languages
427 $arrayoflangcode = array();
428 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
429 $arrayoflangcode[] = getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE');
430 }
431
432 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
433 if (!is_object($extralanguages)) {
434 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
435 $extralanguages = new ExtraLanguages($this->db);
436 }
437 $extralanguages->fetch_name_extralanguages('societe');
438
439 if (!is_array($extralanguages->attributes[$object->element]) || empty($extralanguages->attributes[$object->element][$fieldname])) {
440 return ''; // No extralang field to show
441 }
442
443 $result .= '<!-- Widget for translation -->' . "\n";
444 $result .= '<div class="inline-block paddingleft image-' . $object->element . '-' . $fieldname . '">';
445 $s = img_picto($langs->trans("ShowOtherLanguages"), 'language', '', false, 0, 0, '', 'fa-15 editfieldlang');
446 $result .= $s;
447 $result .= '</div>';
448
449 $result .= '<div class="inline-block hidden field-' . $object->element . '-' . $fieldname . '">';
450
451 $resultforextrlang = '';
452 foreach ($arrayoflangcode as $langcode) {
453 $valuetoshow = GETPOSTISSET('field-' . $object->element . "-" . $fieldname . "-" . $langcode) ? GETPOST('field-' . $object->element . '-' . $fieldname . "-" . $langcode, $check) : '';
454 if (empty($valuetoshow)) {
455 $object->fetchValuesForExtraLanguages();
456 //var_dump($object->array_languages);
457 $valuetoshow = $object->array_languages[$fieldname][$langcode];
458 }
459
460 $s = picto_from_langcode($langcode, 'class="pictoforlang paddingright"');
461 $resultforextrlang .= $s;
462
463 // TODO Use the showInputField() method of ExtraLanguages object
464 if ($typeofdata == 'textarea') {
465 $resultforextrlang .= '<textarea name="field-' . $object->element . "-" . $fieldname . "-" . $langcode . '" id="' . $fieldname . "-" . $langcode . '" class="' . $morecss . '" rows="' . ROWS_2 . '" wrap="soft">';
466 $resultforextrlang .= $valuetoshow;
467 $resultforextrlang .= '</textarea>';
468 } else {
469 $resultforextrlang .= '<input type="text" class="inputfieldforlang ' . ($morecss ? ' ' . $morecss : '') . '" name="field-' . $object->element . '-' . $fieldname . '-' . $langcode . '" value="' . $valuetoshow . '">';
470 }
471 }
472 $result .= $resultforextrlang;
473
474 $result .= '</div>';
475 $result .= '<script nonce="' . getNonce() . '">$(".image-' . $object->element . '-' . $fieldname . '").click(function() { console.log("Toggle lang widget"); jQuery(".field-' . $object->element . '-' . $fieldname . '").toggle(); });</script>';
476 }
477
478 return $result;
479 }
480
494 protected function editInPlace($object, $value, $htmlname, $condition, $inputType = 'textarea', $editvalue = null, $extObject = null, $custommsg = null)
495 {
496 $out = '';
497
498 // Check parameters
499 if (preg_match('/^text/', $inputType)) {
500 $value = dol_nl2br($value);
501 } elseif (preg_match('/^numeric/', $inputType)) {
502 $value = price($value);
503 } elseif ($inputType == 'day' || $inputType == 'datepicker') {
504 $value = dol_print_date($value, 'day');
505 }
506
507 if ($condition) {
508 $element = false;
509 $table_element = false;
510 $fk_element = false;
511 $loadmethod = false;
512 $savemethod = false;
513 $ext_element = false;
514 $button_only = false;
515 $inputOption = '';
516 $rows = '';
517 $cols = '';
518
519 if (is_object($object)) {
520 $element = $object->element;
521 $table_element = $object->table_element;
522 $fk_element = $object->id;
523 }
524
525 if (is_object($extObject)) {
526 $ext_element = $extObject->element;
527 }
528
529 if (preg_match('/^(string|email|numeric)/', $inputType)) {
530 $tmp = explode(':', $inputType);
531 $inputType = $tmp[0];
532 if (!empty($tmp[1])) {
533 $inputOption = $tmp[1];
534 }
535 if (!empty($tmp[2])) {
536 $savemethod = $tmp[2];
537 }
538 $out .= '<input id="width_' . $htmlname . '" value="' . $inputOption . '" type="hidden"/>' . "\n";
539 } elseif ((preg_match('/^day$/', $inputType)) || (preg_match('/^datepicker/', $inputType)) || (preg_match('/^datehourpicker/', $inputType))) {
540 $tmp = explode(':', $inputType);
541 $inputType = $tmp[0];
542 if (!empty($tmp[1])) {
543 $inputOption = $tmp[1];
544 }
545 if (!empty($tmp[2])) {
546 $savemethod = $tmp[2];
547 }
548
549 $out .= '<input id="timestamp" type="hidden"/>' . "\n"; // Use for timestamp format
550 } elseif (preg_match('/^(select|autocomplete)/', $inputType)) {
551 $tmp = explode(':', $inputType);
552 $inputType = $tmp[0];
553 $loadmethod = $tmp[1];
554 if (!empty($tmp[2])) {
555 $savemethod = $tmp[2];
556 }
557 if (!empty($tmp[3])) {
558 $button_only = true;
559 }
560 } elseif (preg_match('/^textarea/', $inputType)) {
561 $tmp = explode(':', $inputType);
562 $inputType = $tmp[0];
563 $rows = (empty($tmp[1]) ? '8' : $tmp[1]);
564 $cols = (empty($tmp[2]) ? '80' : $tmp[2]);
565 } elseif (preg_match('/^ckeditor/', $inputType)) {
566 $tmp = explode(':', $inputType);
567 $inputType = $tmp[0];
568 $toolbar = $tmp[1];
569 if (!empty($tmp[2])) {
570 $width = $tmp[2];
571 }
572 if (!empty($tmp[3])) {
573 $height = $tmp[3];
574 }
575 if (!empty($tmp[4])) {
576 $savemethod = $tmp[4];
577 }
578
579 if (isModEnabled('fckeditor')) {
580 $out .= '<input id="ckeditor_toolbar" value="' . $toolbar . '" type="hidden"/>' . "\n";
581 } else {
582 $inputType = 'textarea';
583 }
584 }
585
586 $out .= '<input id="element_' . $htmlname . '" value="' . $element . '" type="hidden"/>' . "\n";
587 $out .= '<input id="table_element_' . $htmlname . '" value="' . $table_element . '" type="hidden"/>' . "\n";
588 $out .= '<input id="fk_element_' . $htmlname . '" value="' . $fk_element . '" type="hidden"/>' . "\n";
589 $out .= '<input id="loadmethod_' . $htmlname . '" value="' . $loadmethod . '" type="hidden"/>' . "\n";
590 if (!empty($savemethod)) {
591 $out .= '<input id="savemethod_' . $htmlname . '" value="' . $savemethod . '" type="hidden"/>' . "\n";
592 }
593 if (!empty($ext_element)) {
594 $out .= '<input id="ext_element_' . $htmlname . '" value="' . $ext_element . '" type="hidden"/>' . "\n";
595 }
596 if (!empty($custommsg)) {
597 if (is_array($custommsg)) {
598 if (!empty($custommsg['success'])) {
599 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg['success'] . '" type="hidden"/>' . "\n";
600 }
601 if (!empty($custommsg['error'])) {
602 $out .= '<input id="errormsg_' . $htmlname . '" value="' . $custommsg['error'] . '" type="hidden"/>' . "\n";
603 }
604 } else {
605 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg . '" type="hidden"/>' . "\n";
606 }
607 }
608 if ($inputType == 'textarea') {
609 $out .= '<input id="textarea_' . $htmlname . '_rows" value="' . $rows . '" type="hidden"/>' . "\n";
610 $out .= '<input id="textarea_' . $htmlname . '_cols" value="' . $cols . '" type="hidden"/>' . "\n";
611 }
612 $out .= '<span id="viewval_' . $htmlname . '" class="viewval_' . $inputType . ($button_only ? ' inactive' : ' active') . '">' . $value . '</span>' . "\n";
613 $out .= '<span id="editval_' . $htmlname . '" class="editval_' . $inputType . ($button_only ? ' inactive' : ' active') . ' hideobject">' . (!empty($editvalue) ? $editvalue : $value) . '</span>' . "\n";
614 } else {
615 $out = $value;
616 }
617
618 return $out;
619 }
620
639 public function textwithtooltip($text, $htmltext, $tooltipon = 1, $direction = 0, $img = '', $extracss = '', $notabs = 3, $incbefore = '', $noencodehtmltext = 0, $tooltiptrigger = '', $forcenowrap = 0)
640 {
641 if ($incbefore) {
642 $text = $incbefore . $text;
643 }
644 if (!$htmltext) {
645 return $text;
646 }
647 $direction = (int) $direction; // For backward compatibility when $direction was set to '' instead of 0
648
649 $tag = 'td';
650 if ($notabs == 2) {
651 $tag = 'div';
652 }
653 if ($notabs == 3) {
654 $tag = 'span';
655 }
656 // Sanitize tooltip
657 $htmltext = str_replace(array("\r", "\n"), '', $htmltext);
658
659 $extrastyle = '';
660 if ($direction < 0) {
661 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
662 $extrastyle = 'padding: 0px; padding-left: 2px;';
663 }
664 if ($direction > 0) {
665 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
666 $extrastyle = 'padding: 0px; padding-right: 2px;';
667 }
668
669 $classfortooltip = 'classfortooltip';
670
671 $s = '';
672 $textfordialog = '';
673
674 if ($tooltiptrigger == '') {
675 $htmltext = str_replace('"', '&quot;', $htmltext);
676 } else {
677 $classfortooltip = 'classfortooltiponclick';
678 $textfordialog .= '<div style="display: none;" id="idfortooltiponclick_' . $tooltiptrigger . '" class="classfortooltiponclicktext">' . $htmltext . '</div>';
679 }
680 if ($tooltipon == 2 || $tooltipon == 3) {
681 $paramfortooltipimg = ' class="' . $classfortooltip . ($notabs != 3 ? ' inline-block' : '') . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '"';
682 if ($tooltiptrigger == '') {
683 $paramfortooltipimg .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribute to put on img tag to store tooltip
684 } else {
685 $paramfortooltipimg .= ' dolid="' . $tooltiptrigger . '"';
686 }
687 } else {
688 $paramfortooltipimg = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribute to put on td text tag
689 }
690 if ($tooltipon == 1 || $tooltipon == 3) {
691 $paramfortooltiptd = ' class="' . ($tooltipon == 3 ? 'cursorpointer ' : '') . $classfortooltip . ' inline-block' . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '" ';
692 if ($tooltiptrigger == '') {
693 $paramfortooltiptd .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribute to put on td tag to store tooltip
694 } else {
695 $paramfortooltiptd .= ' dolid="' . $tooltiptrigger . '"';
696 }
697 } else {
698 $paramfortooltiptd = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribute to put on td text tag
699 }
700 if (empty($notabs)) {
701 $s .= '<table class="nobordernopadding"><tr style="height: auto;">';
702 } elseif ($notabs == 2) {
703 $s .= '<div class="inline-block' . ($forcenowrap ? ' nowrap' : '') . '">';
704 }
705 // Define value if value is before
706 if ($direction < 0) {
707 $s .= '<' . $tag . $paramfortooltipimg;
708 if ($tag == 'td') {
709 $s .= ' class="valigntop" width="14"';
710 }
711 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
712 }
713 // Use another method to help avoid having a space in value in order to use this value with jquery
714 // Define label
715 if ((string) $text != '') {
716 $s .= '<' . $tag . $paramfortooltiptd . '>' . $text . '</' . $tag . '>';
717 }
718 // Define value if value is after
719 if ($direction > 0) {
720 $s .= '<' . $tag . $paramfortooltipimg;
721 if ($tag == 'td') {
722 $s .= ' class="valignmiddle" width="14"';
723 }
724 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
725 }
726 if (empty($notabs)) {
727 $s .= '</tr></table>';
728 } elseif ($notabs == 2) {
729 $s .= '</div>';
730 }
731
732 return $s;
733 }
734
749 public function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 3, $tooltiptrigger = '', $forcenowrap = 0)
750 {
751 global $conf, $langs;
752
753 //For backwards compatibility
754 if ($type == '0') {
755 $type = 'info';
756 } elseif ($type == '1') {
757 $type = 'help';
758 }
759 // Clean parameters
760 $tooltiptrigger = preg_replace('/[^a-z0-9]/i', '', $tooltiptrigger);
761
762 if (preg_match('/onsmartphone$/', $tooltiptrigger) && empty($conf->dol_no_mouse_hover)) {
763 $tooltiptrigger = preg_replace('/^.*onsmartphone$/', '', $tooltiptrigger);
764 }
765 $alt = '';
766 if ($tooltiptrigger) {
767 $alt = $langs->transnoentitiesnoconv("ClickToShowHelp");
768 }
769
770 // If info or help with no javascript, show only text
771 if (empty($conf->use_javascript_ajax)) {
772 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
773 return $text;
774 } else {
775 $alt = $htmltext;
776 $htmltext = '';
777 }
778 }
779
780 // If info or help with smartphone, show only text (tooltip hover can't works)
781 if (!empty($conf->dol_no_mouse_hover) && empty($tooltiptrigger)) {
782 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
783 return $text;
784 }
785 }
786 // If info or help with smartphone, show only text (tooltip on click does not works with dialog on smaprtphone)
787 //if (!empty($conf->dol_no_mouse_hover) && !empty($tooltiptrigger))
788 //{
789 //if ($type == 'info' || $type == 'help') return '<a href="'..'">'.$text.'</a>';
790 //}
791
792 $img = '';
793 if ($type == 'info') {
794 $img = img_help(0, $alt);
795 } elseif ($type == 'help') {
796 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
797 } elseif ($type == 'helpclickable') {
798 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
799 } elseif ($type == 'superadmin') {
800 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
801 $img = img_picto($alt, 'redstar');
802 } elseif ($type == 'admin') {
803 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
804 $img = img_picto($alt, 'star');
805 } elseif ($type == 'warning') {
806 $img = img_warning($alt);
807 } elseif ($type != 'none') {
808 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
809 $img = img_picto($alt, $type); // $type can be an image path
810 }
811
812 return $this->textwithtooltip($text, $htmltext, ((($tooltiptrigger && !$img) || strpos($type, 'clickable')) ? 3 : 2), $direction, $img, $extracss, $notabs, '', $noencodehtmltext, $tooltiptrigger, $forcenowrap);
813 }
814
825 public function selectMassAction($selected, $arrayofaction, $alwaysvisible = 0, $name = 'massaction', $cssclass = 'checkforselect')
826 {
827 global $conf, $langs, $hookmanager;
828
829 $disabled = 0;
830 $ret = '<div class="centpercent center">';
831 $ret .= '<select class="flat' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'select valignmiddle alignstart" id="' . $name . '" name="' . $name . '"' . ($disabled ? ' disabled="disabled"' : '') . '>';
832
833 // Complete list with data from external modules. THe module can use $_SERVER['PHP_SELF'] to know on which page we are, or use the $parameters['currentcontext'] completed by executeHooks.
834 $parameters = array();
835 $reshook = $hookmanager->executeHooks('addMoreMassActions', $parameters); // Note that $action and $object may have been modified by hook
836 // check if there is a mass action
837
838 if (is_array($arrayofaction) && count($arrayofaction) == 0 && empty($hookmanager->resPrint)) {
839 return;
840 }
841 if (empty($reshook)) {
842 $ret .= '<option value="0"' . ($disabled ? ' disabled="disabled"' : '') . '>-- ' . $langs->trans("SelectAction") . ' --</option>';
843 if (is_array($arrayofaction)) {
844 foreach ($arrayofaction as $code => $label) {
845 $ret .= '<option value="' . $code . '"' . ($disabled ? ' disabled="disabled"' : '') . ' data-html="' . dol_escape_htmltag($label) . '">' . $label . '</option>';
846 }
847 }
848 }
849 $ret .= $hookmanager->resPrint;
850
851 $ret .= '</select>';
852
853 if (empty($conf->dol_optimize_smallscreen)) {
854 $ret .= ajax_combobox('.' . $name . 'select');
855 }
856
857 // Warning: if you set submit button to disabled, post using 'Enter' will no more work if there is no another input submit. So we add a hidden button
858 $ret .= '<input type="submit" name="confirmmassactioninvisible" style="display: none" tabindex="-1">'; // Hidden button BEFORE so it is the one used when we submit with ENTER.
859 $ret .= '<input type="submit" disabled name="confirmmassaction"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display: none"') . ' class="reposition button smallpaddingimp' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'confirmed" value="' . dol_escape_htmltag($langs->trans("Confirm")) . '">';
860 $ret .= '</div>';
861
862 if (!empty($conf->use_javascript_ajax)) {
863 $ret .= '<!-- JS CODE TO ENABLE mass action select -->
864 <script nonce="' . getNonce() . '">
865 function initCheckForSelect(mode, name, cssclass) /* mode is 0 during init of page or click all, 1 when we click on 1 checkboxi, "name" refers to the class of the massaction button, "cssclass" to the class of the checkfor select boxes */
866 {
867 atleastoneselected=0;
868 jQuery("."+cssclass).each(function( index ) {
869 /* console.log( index + ": " + $( this ).text() ); */
870 if ($(this).is(\':checked\')) atleastoneselected++;
871 });
872
873 console.log("initCheckForSelect mode="+mode+" name="+name+" cssclass="+cssclass+" atleastoneselected="+atleastoneselected);
874
875 if (atleastoneselected || ' . $alwaysvisible . ')
876 {
877 jQuery("."+name).show();
878 ' . ($selected ? 'if (atleastoneselected) { jQuery("."+name+"select").val("' . $selected . '").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', false); }' : '') . '
879 ' . ($selected ? 'if (! atleastoneselected) { jQuery("."+name+"select").val("0").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', true); } ' : '') . '
880 }
881 else
882 {
883 jQuery("."+name).hide();
884 jQuery("."+name+"other").hide();
885 }
886 }
887
888 jQuery(document).ready(function () {
889 initCheckForSelect(0, "' . $name . '", "' . $cssclass . '");
890 jQuery(".' . $cssclass . '").click(function() {
891 initCheckForSelect(1, "' . $name . '", "' . $cssclass . '");
892 });
893 jQuery(".' . $name . 'select").change(function() {
894 var massaction = $( this ).val();
895 var urlform = $( this ).closest("form").attr("action").replace("#show_files","");
896 if (massaction == "builddoc")
897 {
898 urlform = urlform + "#show_files";
899 }
900 $( this ).closest("form").attr("action", urlform);
901 console.log("we select a mass action name=' . $name . ' massaction="+massaction+" - "+urlform);
902 /* Warning: if you set submit button to disabled, post using Enter will no more work if there is no other button */
903 if ($(this).val() != \'0\')
904 {
905 jQuery(".' . $name . 'confirmed").prop(\'disabled\', false);
906 jQuery(".' . $name . 'other").hide(); /* To disable if another div was open */
907 jQuery(".' . $name . '"+massaction).show();
908 }
909 else
910 {
911 jQuery(".' . $name . 'confirmed").prop(\'disabled\', true);
912 jQuery(".' . $name . 'other").hide(); /* To disable any div open */
913 }
914 });
915 });
916 </script>
917 ';
918 }
919
920 return $ret;
921 }
922
923 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
924
941 public function select_country($selected = '', $htmlname = 'country_id', $htmloption = '', $maxlength = 0, $morecss = 'minwidth300', $usecodeaskey = '', $showempty = 1, $disablefavorites = 0, $addspecialentries = 0, $exclude_country_code = array(), $hideflags = 0)
942 {
943 // phpcs:enable
944 global $conf, $langs, $mysoc;
945
946 $langs->load("dict");
947
948 $out = '';
949 $countryArray = array();
950 $favorite = array();
951 $label = array();
952 $atleastonefavorite = 0;
953
954 $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite, eec";
955 $sql .= " FROM " . $this->db->prefix() . "c_country";
956 $sql .= " WHERE active > 0";
957 //$sql.= " ORDER BY code ASC";
958
959 dol_syslog(get_class($this) . "::select_country", LOG_DEBUG);
960 $resql = $this->db->query($sql);
961 if ($resql) {
962 $out .= '<select id="select' . $htmlname . '" class="flat maxwidth200onsmartphone selectcountry' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" ' . $htmloption . '>';
963 $num = $this->db->num_rows($resql);
964 $i = 0;
965 if ($num) {
966 while ($i < $num) {
967 $obj = $this->db->fetch_object($resql);
968
969 $countryArray[$i]['rowid'] = $obj->rowid;
970 $countryArray[$i]['code_iso'] = $obj->code_iso;
971 $countryArray[$i]['code_iso3'] = $obj->code_iso3;
972 $countryArray[$i]['label'] = ($obj->code_iso && $langs->transnoentitiesnoconv("Country" . $obj->code_iso) != "Country" . $obj->code_iso ? $langs->transnoentitiesnoconv("Country" . $obj->code_iso) : ($obj->label != '-' ? $obj->label : ''));
973 $countryArray[$i]['favorite'] = $obj->favorite;
974 $countryArray[$i]['eec'] = $obj->eec;
975 $favorite[$i] = $obj->favorite;
976 $label[$i] = dol_string_unaccent($countryArray[$i]['label']);
977 $i++;
978 }
979
980 if (empty($disablefavorites)) {
981 $array1_sort_order = SORT_DESC;
982 $array2_sort_order = SORT_ASC;
983 array_multisort($favorite, $array1_sort_order, $label, $array2_sort_order, $countryArray);
984 } else {
985 $countryArray = dol_sort_array($countryArray, 'label');
986 }
987
988 if ($showempty) {
989 if (is_numeric($showempty)) {
990 $out .= '<option value="">&nbsp;</option>' . "\n";
991 } else {
992 $out .= '<option value="-1">' . $langs->trans($showempty) . '</option>' . "\n";
993 }
994 }
995
996 if ($addspecialentries) { // Add dedicated entries for groups of countries
997 //if ($showempty) $out.= '<option value="" disabled class="selectoptiondisabledwhite">--------------</option>';
998 $out .= '<option value="special_allnotme"' . ($selected == 'special_allnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
999 $out .= '<option value="special_eec"' . ($selected == 'special_eec' ? ' selected' : '') . '>' . $langs->trans("CountriesInEEC") . '</option>';
1000 if ($mysoc->isInEEC()) {
1001 $out .= '<option value="special_eecnotme"' . ($selected == 'special_eecnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesInEECExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
1002 }
1003 $out .= '<option value="special_noteec"' . ($selected == 'special_noteec' ? ' selected' : '') . '>' . $langs->trans("CountriesNotInEEC") . '</option>';
1004 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1005 }
1006
1007 foreach ($countryArray as $row) {
1008 //if (empty($showempty) && empty($row['rowid'])) continue;
1009 if (empty($row['rowid'])) {
1010 continue;
1011 }
1012 if (is_array($exclude_country_code) && count($exclude_country_code) && in_array($row['code_iso'], $exclude_country_code)) {
1013 continue; // exclude some countries
1014 }
1015
1016 if (empty($disablefavorites) && $row['favorite'] && $row['code_iso']) {
1017 $atleastonefavorite++;
1018 }
1019 if (empty($row['favorite']) && $atleastonefavorite) {
1020 $atleastonefavorite = 0;
1021 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1022 }
1023
1024 $labeltoshow = '';
1025 if ($row['label']) {
1026 $labeltoshow .= dol_trunc($row['label'], $maxlength, 'middle');
1027 } else {
1028 $labeltoshow .= '&nbsp;';
1029 }
1030 if ($row['code_iso']) {
1031 $labeltoshow .= ' <span class="opacitymedium">(' . $row['code_iso'] . ')</span>';
1032 if (empty($hideflags)) {
1033 $tmpflag = picto_from_langcode($row['code_iso'], 'class="saturatemedium paddingrightonly"', 1);
1034 $labeltoshow = $tmpflag . ' ' . $labeltoshow;
1035 }
1036 }
1037
1038 if ($selected && $selected != '-1' && ($selected == $row['rowid'] || $selected == $row['code_iso'] || $selected == $row['code_iso3'] || $selected == $row['label'])) {
1039 $out .= '<option value="' . ($usecodeaskey ? ($usecodeaskey == 'code2' ? $row['code_iso'] : $row['code_iso3']) : $row['rowid']) . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '" data-eec="' . ((int) $row['eec']) . '">';
1040 } else {
1041 $out .= '<option value="' . ($usecodeaskey ? ($usecodeaskey == 'code2' ? $row['code_iso'] : $row['code_iso3']) : $row['rowid']) . '" data-html="' . dol_escape_htmltag($labeltoshow) . '" data-eec="' . ((int) $row['eec']) . '">';
1042 }
1043 $out .= $labeltoshow;
1044 $out .= '</option>' . "\n";
1045 }
1046 }
1047 $out .= '</select>';
1048 } else {
1049 dol_print_error($this->db);
1050 }
1051
1052 // Make select dynamic
1053 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1054 $out .= ajax_combobox('select' . $htmlname, array(), 0, 0, 'resolve');
1055
1056 return $out;
1057 }
1058
1059 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1060
1074 public function select_incoterms($selected = '', $location_incoterms = '', $page = '', $htmlname = 'incoterm_id', $htmloption = '', $forcecombo = 1, $events = array(), $disableautocomplete = 0)
1075 {
1076 // phpcs:enable
1077 global $conf, $langs;
1078
1079 $langs->load("dict");
1080
1081 $out = '';
1082 $moreattrib = '';
1083 $incotermArray = array();
1084
1085 $sql = "SELECT rowid, code";
1086 $sql .= " FROM " . $this->db->prefix() . "c_incoterms";
1087 $sql .= " WHERE active > 0";
1088 $sql .= " ORDER BY code ASC";
1089
1090 dol_syslog(get_class($this) . "::select_incoterm", LOG_DEBUG);
1091 $resql = $this->db->query($sql);
1092 if ($resql) {
1093 if ($conf->use_javascript_ajax && !$forcecombo) {
1094 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1095 $out .= ajax_combobox($htmlname, $events);
1096 }
1097
1098 if (!empty($page)) {
1099 $out .= '<form method="post" action="' . $page . '">';
1100 $out .= '<input type="hidden" name="action" value="set_incoterms">';
1101 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
1102 }
1103
1104 $out .= '<select id="' . $htmlname . '" class="flat selectincoterm width75" name="' . $htmlname . '" ' . $htmloption . '>';
1105 $out .= '<option value="0">&nbsp;</option>';
1106 $num = $this->db->num_rows($resql);
1107 $i = 0;
1108 if ($num) {
1109 while ($i < $num) {
1110 $obj = $this->db->fetch_object($resql);
1111 $incotermArray[$i]['rowid'] = $obj->rowid;
1112 $incotermArray[$i]['code'] = $obj->code;
1113 $i++;
1114 }
1115
1116 foreach ($incotermArray as $row) {
1117 if ($selected && ($selected == $row['rowid'] || $selected == $row['code'])) {
1118 $out .= '<option value="' . $row['rowid'] . '" selected>';
1119 } else {
1120 $out .= '<option value="' . $row['rowid'] . '">';
1121 }
1122
1123 if ($row['code']) {
1124 $out .= $row['code'];
1125 }
1126
1127 $out .= '</option>';
1128 }
1129 }
1130 $out .= '</select>';
1131
1132 if ($conf->use_javascript_ajax && empty($disableautocomplete)) {
1133 $out .= ajax_multiautocompleter('location_incoterms', array(), DOL_URL_ROOT . '/core/ajax/locationincoterms.php') . "\n";
1134 $moreattrib .= ' autocomplete="off"';
1135 }
1136 $out .= '<input id="location_incoterms" class="maxwidthonsmartphone type="text" name="location_incoterms" value="' . $location_incoterms . '">' . "\n";
1137
1138 if (!empty($page)) {
1139 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp nomargintop nomarginbottom" value="' . $langs->trans("Modify") . '"></form>';
1140 }
1141 } else {
1142 dol_print_error($this->db);
1143 }
1144
1145 return $out;
1146 }
1147
1148 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1149
1162 public function select_type_of_lines($selected = '', $htmlname = 'type', $showempty = 0, $hidetext = 0, $forceall = 0, $morecss = "")
1163 {
1164 // phpcs:enable
1165 global $langs;
1166
1167 // If product & services are enabled or both disabled.
1168 if ($forceall == 1 || (empty($forceall) && isModEnabled("product") && isModEnabled("service"))
1169 || (empty($forceall) && !isModEnabled('product') && !isModEnabled('service'))) {
1170 if (empty($hidetext)) {
1171 print $langs->trans("Type") . ': ';
1172 }
1173 print '<select class="flat'.($morecss ? ' '.$morecss : '').'" id="select_' . $htmlname . '" name="' . $htmlname . '">';
1174 if ($showempty) {
1175 print '<option value="-1"';
1176 if ($selected == -1) {
1177 print ' selected';
1178 }
1179 print '>';
1180 if (is_numeric($showempty)) {
1181 print '&nbsp;';
1182 } else {
1183 print $showempty;
1184 }
1185 print '</option>';
1186 }
1187
1188 print '<option value="0"';
1189 if (0 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'product')) {
1190 print ' selected';
1191 }
1192 print '>' . $langs->trans("Product");
1193
1194 print '<option value="1"';
1195 if (1 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'service')) {
1196 print ' selected';
1197 }
1198 print '>' . $langs->trans("Service");
1199
1200 print '</select>';
1201 print ajax_combobox('select_' . $htmlname);
1202 //if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1203 }
1204 if ((empty($forceall) && !isModEnabled('product') && isModEnabled("service")) || $forceall == 3) {
1205 print $langs->trans("Service");
1206 print '<input type="hidden" name="' . $htmlname . '" value="1">';
1207 }
1208 if ((empty($forceall) && isModEnabled("product") && !isModEnabled('service')) || $forceall == 2) {
1209 print $langs->trans("Product");
1210 print '<input type="hidden" name="' . $htmlname . '" value="0">';
1211 }
1212 if ($forceall < 0) { // This should happened only for contracts when both predefined product and service are disabled.
1213 print '<input type="hidden" name="' . $htmlname . '" value="1">'; // By default we set on service for contract. If CONTRACT_SUPPORT_PRODUCTS is set, forceall should be 1 not -1
1214 }
1215 }
1216
1217 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1218
1224 public function load_cache_types_fees()
1225 {
1226 // phpcs:enable
1227 global $langs;
1228
1229 $num = count($this->cache_types_fees);
1230 if ($num > 0) {
1231 return 0; // Cache already loaded
1232 }
1233
1234 dol_syslog(__METHOD__, LOG_DEBUG);
1235
1236 $langs->load("trips");
1237
1238 $sql = "SELECT c.code, c.label";
1239 $sql .= " FROM " . $this->db->prefix() . "c_type_fees as c";
1240 $sql .= " WHERE active > 0";
1241
1242 $resql = $this->db->query($sql);
1243 if ($resql) {
1244 $num = $this->db->num_rows($resql);
1245 $i = 0;
1246
1247 while ($i < $num) {
1248 $obj = $this->db->fetch_object($resql);
1249
1250 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
1251 $label = ($obj->code != $langs->trans($obj->code) ? $langs->trans($obj->code) : $langs->trans($obj->label));
1252 $this->cache_types_fees[$obj->code] = $label;
1253 $i++;
1254 }
1255
1256 asort($this->cache_types_fees);
1257
1258 return $num;
1259 } else {
1260 dol_print_error($this->db);
1261 return -1;
1262 }
1263 }
1264
1265 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1266
1275 public function select_type_fees($selected = '', $htmlname = 'type', $showempty = 0)
1276 {
1277 // phpcs:enable
1278 global $user, $langs;
1279
1280 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
1281
1282 $this->load_cache_types_fees();
1283
1284 print '<select id="select_' . $htmlname . '" class="flat" name="' . $htmlname . '">';
1285 if ($showempty) {
1286 print '<option value="-1"';
1287 if ($selected == -1) {
1288 print ' selected';
1289 }
1290 print '>&nbsp;</option>';
1291 }
1292
1293 foreach ($this->cache_types_fees as $key => $value) {
1294 print '<option value="' . $key . '"';
1295 if ($key == $selected) {
1296 print ' selected';
1297 }
1298 print '>';
1299 print $value;
1300 print '</option>';
1301 }
1302
1303 print '</select>';
1304 if ($user->admin) {
1305 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1306 }
1307 }
1308
1309
1310 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1311
1334 public function select_company($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $limit = 0, $morecss = 'minwidth100', $moreparam = '', $selected_input_value = '', $hidelabel = 1, $ajaxoptions = array(), $multiple = false, $excludeids = array(), $showcode = 0)
1335 {
1336 // phpcs:enable
1337 global $conf, $langs;
1338
1339 $out = '';
1340
1341 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT') && !$forcecombo) {
1342 if (is_null($ajaxoptions)) {
1343 $ajaxoptions = array();
1344 }
1345
1346 require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1347
1348 // No immediate load of all database
1349 $placeholder = '';
1350 if ($selected && empty($selected_input_value)) {
1351 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1352 $societetmp = new Societe($this->db);
1353 $societetmp->fetch($selected);
1354 $selected_input_value = $societetmp->name;
1355 unset($societetmp);
1356 }
1357
1358 // mode 1
1359 $urloption = 'htmlname=' . urlencode((string) (str_replace('.', '_', $htmlname))) . '&outjson=1&filter=' . urlencode((string) ($filter)) . (empty($excludeids) ? '' : '&excludeids=' . implode(',', $excludeids)) . ($showtype ? '&showtype=' . urlencode((string) ($showtype)) : '') . ($showcode ? '&showcode=' . urlencode((string) ($showcode)) : '');
1360
1361 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
1362 if (empty($hidelabel)) {
1363 $out .= $langs->trans("RefOrLabel") . ' : ';
1364 } elseif ($hidelabel > 1) {
1365 $placeholder = $langs->trans("RefOrLabel");
1366 if ($hidelabel == 2) {
1367 $out .= img_picto($langs->trans("Search"), 'search');
1368 }
1369 }
1370 $out .= '<input type="text" class="' . $morecss . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '') . ' ' . (getDolGlobalString('THIRDPARTY_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
1371 if ($hidelabel == 3) {
1372 $out .= img_picto($langs->trans("Search"), 'search');
1373 }
1374
1375 $out .= ajax_event($htmlname, $events);
1376
1377 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/societe/ajax/company.php', $urloption, getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT'), 0, $ajaxoptions);
1378 } else {
1379 // Immediate load of all database
1380 $out .= $this->select_thirdparty_list($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, '', 0, $limit, $morecss, $moreparam, $multiple, $excludeids, $showcode);
1381 }
1382
1383 return $out;
1384 }
1385
1386
1387 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1388
1414 public function select_contact($socid, $selected = '', $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $nokeyifsocid = true, $showsoc = 0, $forcecombo = 0, $events = array(), $moreparam = '', $htmlid = '', $selected_input_value = '', $filter = '')
1415 {
1416 // phpcs:enable
1417
1418 global $conf, $langs;
1419
1420 $out = '';
1421
1422 $sav = getDolGlobalString('CONTACT_USE_SEARCH_TO_SELECT');
1423 if ($nokeyifsocid && $socid > 0) {
1424 $conf->global->CONTACT_USE_SEARCH_TO_SELECT = 0;
1425 }
1426
1427 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('CONTACT_USE_SEARCH_TO_SELECT') && !$forcecombo) {
1428 if (is_null($events)) {
1429 $events = array();
1430 }
1431
1432 require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1433
1434 // No immediate load of all database
1435 $placeholder = '';
1436 if ($selected && empty($selected_input_value)) {
1437 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1438 $contacttmp = new Contact($this->db);
1439 $contacttmp->fetch($selected);
1440 $selected_input_value = $contacttmp->getFullName($langs);
1441 unset($contacttmp);
1442 }
1443 if (!is_numeric($showempty)) {
1444 $placeholder = $showempty;
1445 }
1446
1447 // mode 1
1448 $urloption = 'htmlname=' . urlencode((string) (str_replace('.', '_', $htmlname))) . '&outjson=1&filter=' . urlencode((string) ($filter)) . (empty($exclude) ? '' : '&exclude=' . urlencode($exclude)) . ($showsoc ? '&showsoc=' . urlencode((string) ($showsoc)) : '');
1449
1450 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
1451
1452 $out .= '<input type="text" class="' . $morecss . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '') . ' ' . (getDolGlobalString('CONTACT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
1453
1454 $out .= ajax_event($htmlname, $events);
1455
1456 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/contact/ajax/contact.php', $urloption, getDolGlobalString('CONTACT_USE_SEARCH_TO_SELECT'), 0, $events);
1457 } else {
1458 // Immediate load of all database
1459 $multiple = false;
1460 $disableifempty = 0;
1461 $options_only = false;
1462 $limitto = '';
1463
1464 $out .= $this->selectcontacts($socid, $selected, $htmlname, $showempty, $exclude, $limitto, $showfunction, $morecss, $options_only, $showsoc, $forcecombo, $events, $moreparam, $htmlid, $multiple, $disableifempty);
1465 }
1466
1467 $conf->global->CONTACT_USE_SEARCH_TO_SELECT = $sav;
1468
1469 return $out;
1470 }
1471
1472
1473 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1474
1499 public function select_thirdparty_list($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $filterkey = '', $outputmode = 0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $multiple = false, $excludeids = array(), $showcode = 0)
1500 {
1501 // phpcs:enable
1502 global $user, $langs;
1503 global $hookmanager;
1504
1505 $out = '';
1506 $num = 0;
1507 $outarray = array();
1508
1509 if ($selected === '') {
1510 $selected = array();
1511 } elseif (!is_array($selected)) {
1512 $selected = array($selected);
1513 }
1514
1515 // Clean $filter that may contains sql conditions so sql code
1516 if (function_exists('testSqlAndScriptInject')) {
1517 if (testSqlAndScriptInject($filter, 3) > 0) {
1518 $filter = '';
1519 return 'SQLInjectionTryDetected';
1520 }
1521 }
1522
1523 if ($filter != '') { // If a filter was provided
1524 if (preg_match('/[\‍(\‍)]/', $filter)) {
1525 // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax.
1526 $errormsg = '';
1527 $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1);
1528
1529 // Redo clean $filter that may contains sql conditions so sql code
1530 if (function_exists('testSqlAndScriptInject')) {
1531 if (testSqlAndScriptInject($filter, 3) > 0) {
1532 $filter = '';
1533 return 'SQLInjectionTryDetected';
1534 }
1535 }
1536 } else {
1537 // If not, we do nothing. We already know that there is no parenthesis
1538 // TODO Disallow this case in a future.
1539 dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Syntax.", LOG_WARNING);
1540 }
1541 }
1542
1543 // We search companies
1544 $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.tva_intra, s.client, s.fournisseur, s.code_client, s.code_fournisseur";
1545 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1546 $sql .= ", s.address, s.zip, s.town";
1547 $sql .= ", dictp.code as country_code";
1548 }
1549 $sql .= " FROM " . $this->db->prefix() . "societe as s";
1550 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1551 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_country as dictp ON dictp.rowid = s.fk_pays";
1552 }
1553 if (!$user->hasRight('societe', 'client', 'voir')) {
1554 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
1555 }
1556 $sql .= " WHERE s.entity IN (" . getEntity('societe') . ")";
1557 if (!empty($user->socid)) {
1558 $sql .= " AND s.rowid = " . ((int) $user->socid);
1559 }
1560 if ($filter) {
1561 // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria()
1562 // if not, by testSqlAndScriptInject() only.
1563 $sql .= " AND (" . $filter . ")";
1564 }
1565 if (!$user->hasRight('societe', 'client', 'voir')) {
1566 $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
1567 }
1568 if (getDolGlobalString('COMPANY_HIDE_INACTIVE_IN_COMBOBOX')) {
1569 $sql .= " AND s.status <> 0";
1570 }
1571 if (!empty($excludeids)) {
1572 $sql .= " AND s.rowid NOT IN (" . $this->db->sanitize(implode(',', $excludeids)) . ")";
1573 }
1574 // Add where from hooks
1575 $parameters = array();
1576 $reshook = $hookmanager->executeHooks('selectThirdpartyListWhere', $parameters); // Note that $action and $object may have been modified by hook
1577 $sql .= $hookmanager->resPrint;
1578 // Add criteria
1579 if ($filterkey && $filterkey != '') {
1580 $sql .= " AND (";
1581 $prefix = !getDolGlobalString('COMPANY_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if COMPANY_DONOTSEARCH_ANYWHERE is on
1582 // For natural search
1583 $search_crit = explode(' ', $filterkey);
1584 $i = 0;
1585 if (count($search_crit) > 1) {
1586 $sql .= "(";
1587 }
1588 foreach ($search_crit as $crit) {
1589 if ($i > 0) {
1590 $sql .= " AND ";
1591 }
1592 $sql .= "(s.nom LIKE '" . $this->db->escape($prefix . $crit) . "%')";
1593 $i++;
1594 }
1595 if (count($search_crit) > 1) {
1596 $sql .= ")";
1597 }
1598 if (isModEnabled('barcode')) {
1599 $sql .= " OR s.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1600 }
1601 $sql .= " OR s.code_client LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.code_fournisseur LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1602 $sql .= " OR s.name_alias LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.tva_intra LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1603 $sql .= ")";
1604 }
1605 $sql .= $this->db->order("nom", "ASC");
1606 $sql .= $this->db->plimit($limit, 0);
1607
1608 // Build output string
1609 dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
1610 $resql = $this->db->query($sql);
1611 if ($resql) {
1612 // Construct $out and $outarray
1613 $out .= '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($moreparam ? ' ' . $moreparam : '') . ' name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . '>' . "\n";
1614
1615 $textifempty = (($showempty && !is_numeric($showempty)) ? $langs->trans($showempty) : '');
1616 if (getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
1617 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
1618 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
1619 if ($showempty && !is_numeric($showempty)) {
1620 $textifempty = $langs->trans($showempty);
1621 } else {
1622 $textifempty .= $langs->trans("All");
1623 }
1624 }
1625 if ($showempty) {
1626 $out .= '<option value="-1" data-html="' . dol_escape_htmltag('<span class="opacitymedium">' . ($textifempty ? $textifempty : '&nbsp;') . '</span>') . '">' . $textifempty . '</option>' . "\n";
1627 }
1628
1629 $companytemp = new Societe($this->db);
1630
1631 $num = $this->db->num_rows($resql);
1632 $i = 0;
1633 if ($num) {
1634 while ($i < $num) {
1635 $obj = $this->db->fetch_object($resql);
1636 $label = '';
1637 if ($showcode || getDolGlobalString('SOCIETE_ADD_REF_IN_LIST')) {
1638 if (($obj->client) && (!empty($obj->code_client))) {
1639 $label = $obj->code_client . ' - ';
1640 }
1641 if (($obj->fournisseur) && (!empty($obj->code_fournisseur))) {
1642 $label .= $obj->code_fournisseur . ' - ';
1643 }
1644 $label .= ' ' . $obj->name;
1645 } else {
1646 $label = $obj->name;
1647 }
1648
1649 if (!empty($obj->name_alias)) {
1650 $label .= ' (' . $obj->name_alias . ')';
1651 }
1652
1653 if (getDolGlobalString('SOCIETE_SHOW_VAT_IN_LIST') && !empty($obj->tva_intra)) {
1654 $label .= ' - '.$obj->tva_intra;
1655 }
1656
1657 $labelhtml = $label;
1658
1659 if ($showtype) {
1660 $companytemp->id = $obj->rowid;
1661 $companytemp->client = $obj->client;
1662 $companytemp->fournisseur = $obj->fournisseur;
1663 $tmptype = $companytemp->getTypeUrl(1, '', 0, 'span');
1664 if ($tmptype) {
1665 $labelhtml .= ' ' . $tmptype;
1666 }
1667
1668 if ($obj->client || $obj->fournisseur) {
1669 $label .= ' (';
1670 }
1671 if ($obj->client == 1 || $obj->client == 3) {
1672 $label .= $langs->trans("Customer");
1673 }
1674 if ($obj->client == 2 || $obj->client == 3) {
1675 $label .= ($obj->client == 3 ? ', ' : '') . $langs->trans("Prospect");
1676 }
1677 if ($obj->fournisseur) {
1678 $label .= ($obj->client ? ', ' : '') . $langs->trans("Supplier");
1679 }
1680 if ($obj->client || $obj->fournisseur) {
1681 $label .= ')';
1682 }
1683 }
1684
1685 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1686 $s = ($obj->address ? ' - ' . $obj->address : '') . ($obj->zip ? ' - ' . $obj->zip : '') . ($obj->town ? ' ' . $obj->town : '');
1687 if (!empty($obj->country_code)) {
1688 $s .= ', ' . $langs->trans('Country' . $obj->country_code);
1689 }
1690 $label .= $s;
1691 $labelhtml .= $s;
1692 }
1693
1694 if (empty($outputmode)) {
1695 if (in_array($obj->rowid, $selected)) {
1696 $out .= '<option value="' . $obj->rowid . '" selected data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1697 } else {
1698 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1699 }
1700 } else {
1701 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label, 'labelhtml' => $labelhtml));
1702 }
1703
1704 $i++;
1705 if (($i % 10) == 0) {
1706 $out .= "\n";
1707 }
1708 }
1709 }
1710 $out .= '</select>' . "\n";
1711 if (!$forcecombo) {
1712 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1713 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("COMPANY_USE_SEARCH_TO_SELECT"));
1714 }
1715 } else {
1716 dol_print_error($this->db);
1717 }
1718
1719 $this->result = array('nbofthirdparties' => $num);
1720
1721 if ($outputmode) {
1722 return $outarray;
1723 }
1724 return $out;
1725 }
1726
1727
1753 public function selectcontacts($socid, $selected = array(), $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $options_only = 0, $showsoc = 0, $forcecombo = 0, $events = array(), $moreparam = '', $htmlid = '', $multiple = false, $disableifempty = 0, $filter = '')
1754 {
1755 global $conf, $user, $langs, $hookmanager, $action;
1756
1757 $langs->load('companies');
1758
1759 if (empty($htmlid)) {
1760 $htmlid = $htmlname;
1761 }
1762 $num = 0;
1763 $out = '';
1764 $outarray = array();
1765
1766 if ($selected === '') {
1767 $selected = array();
1768 } elseif (!is_array($selected)) {
1769 $selected = array((int) $selected);
1770 }
1771
1772 // Clean $filter that may contains sql conditions so sql code
1773 if (function_exists('testSqlAndScriptInject')) {
1774 if (testSqlAndScriptInject($filter, 3) > 0) {
1775 $filter = '';
1776 return 'SQLInjectionTryDetected';
1777 }
1778 }
1779
1780 if ($filter != '') { // If a filter was provided
1781 if (preg_match('/[\‍(\‍)]/', $filter)) {
1782 // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax.
1783 $errormsg = '';
1784 $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1);
1785
1786 // Redo clean $filter that may contains sql conditions so sql code
1787 if (function_exists('testSqlAndScriptInject')) {
1788 if (testSqlAndScriptInject($filter, 3) > 0) {
1789 $filter = '';
1790 return 'SQLInjectionTryDetected';
1791 }
1792 }
1793 } else {
1794 // If not, we do nothing. We already know that there is no parenthesis
1795 // TODO Disallow this case in a future by returning an error here.
1796 dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Filter Syntax.", LOG_WARNING);
1797 }
1798 }
1799
1800 if (!is_object($hookmanager)) {
1801 include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
1802 $hookmanager = new HookManager($this->db);
1803 }
1804
1805 // We search third parties
1806 $sql = "SELECT sp.rowid, sp.lastname, sp.statut, sp.firstname, sp.poste, sp.email, sp.phone, sp.phone_perso, sp.phone_mobile, sp.town AS contact_town";
1807 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1808 $sql .= ", s.nom as company, s.town AS company_town";
1809 }
1810 $sql .= " FROM " . $this->db->prefix() . "socpeople as sp";
1811 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1812 $sql .= " LEFT OUTER JOIN " . $this->db->prefix() . "societe as s ON s.rowid=sp.fk_soc";
1813 }
1814 $sql .= " WHERE sp.entity IN (" . getEntity('contact') . ")";
1815 $sql .= " AND ((sp.fk_user_creat = ".((int) $user->id)." AND sp.priv = 1) OR sp.priv = 0)"; // check if this is a private contact
1816 if ($socid > 0 || $socid == -1) {
1817 $sql .= " AND sp.fk_soc = " . ((int) $socid);
1818 }
1819 if (getDolGlobalString('CONTACT_HIDE_INACTIVE_IN_COMBOBOX')) {
1820 $sql .= " AND sp.statut <> 0";
1821 }
1822 if ($filter) {
1823 // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria()
1824 // if not, by testSqlAndScriptInject() only.
1825 $sql .= " AND (" . $filter . ")";
1826 }
1827 // Add where from hooks
1828 $parameters = array();
1829 $reshook = $hookmanager->executeHooks('selectContactListWhere', $parameters); // Note that $action and $object may have been modified by hook
1830 $sql .= $hookmanager->resPrint;
1831 $sql .= " ORDER BY sp.lastname ASC";
1832
1833 dol_syslog(get_class($this) . "::selectcontacts", LOG_DEBUG);
1834 $resql = $this->db->query($sql);
1835 if ($resql) {
1836 $num = $this->db->num_rows($resql);
1837
1838 if ($htmlname != 'none' && !$options_only) {
1839 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlid . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . (($num || empty($disableifempty)) ? '' : ' disabled') . ($multiple ? 'multiple' : '') . ' ' . (!empty($moreparam) ? $moreparam : '') . '>';
1840 }
1841
1842 if ($showempty && !is_numeric($showempty)) {
1843 $textforempty = $showempty;
1844 $out .= '<option class="optiongrey" value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>' . $textforempty . '</option>';
1845 } else {
1846 if (($showempty == 1 || ($showempty == 3 && $num > 1)) && !$multiple) {
1847 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>&nbsp;</option>';
1848 }
1849 if ($showempty == 2) {
1850 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>-- ' . $langs->trans("Internal") . ' --</option>';
1851 }
1852 }
1853
1854 $i = 0;
1855 if ($num) {
1856 include_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1857 $contactstatic = new Contact($this->db);
1858
1859 while ($i < $num) {
1860 $obj = $this->db->fetch_object($resql);
1861
1862 // Set email (or phones) and town extended infos
1863 $extendedInfos = '';
1864 if (getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1865 $extendedInfos = array();
1866 $email = trim($obj->email);
1867 if (!empty($email)) {
1868 $extendedInfos[] = $email;
1869 } else {
1870 $phone = trim($obj->phone);
1871 $phone_perso = trim($obj->phone_perso);
1872 $phone_mobile = trim($obj->phone_mobile);
1873 if (!empty($phone)) {
1874 $extendedInfos[] = $phone;
1875 }
1876 if (!empty($phone_perso)) {
1877 $extendedInfos[] = $phone_perso;
1878 }
1879 if (!empty($phone_mobile)) {
1880 $extendedInfos[] = $phone_mobile;
1881 }
1882 }
1883 $contact_town = trim($obj->contact_town);
1884 $company_town = trim($obj->company_town);
1885 if (!empty($contact_town)) {
1886 $extendedInfos[] = $contact_town;
1887 } elseif (!empty($company_town)) {
1888 $extendedInfos[] = $company_town;
1889 }
1890 $extendedInfos = implode(' - ', $extendedInfos);
1891 if (!empty($extendedInfos)) {
1892 $extendedInfos = ' - ' . $extendedInfos;
1893 }
1894 }
1895
1896 $contactstatic->id = $obj->rowid;
1897 $contactstatic->lastname = $obj->lastname;
1898 $contactstatic->firstname = $obj->firstname;
1899 if ($obj->statut == 1) {
1900 $tmplabel = '';
1901 if ($htmlname != 'none') {
1902 $disabled = 0;
1903 if (is_array($exclude) && count($exclude) && in_array($obj->rowid, $exclude)) {
1904 $disabled = 1;
1905 }
1906 if (is_array($limitto) && count($limitto) && !in_array($obj->rowid, $limitto)) {
1907 $disabled = 1;
1908 }
1909 if (!empty($selected) && in_array($obj->rowid, $selected)) {
1910 $out .= '<option value="' . $obj->rowid . '"';
1911 if ($disabled) {
1912 $out .= ' disabled';
1913 }
1914 $out .= ' selected>';
1915
1916 $tmplabel = $contactstatic->getFullName($langs) . $extendedInfos;
1917 if ($showfunction && $obj->poste) {
1918 $tmplabel .= ' (' . $obj->poste . ')';
1919 }
1920 if (($showsoc > 0) && $obj->company) {
1921 $tmplabel .= ' - (' . $obj->company . ')';
1922 }
1923
1924 $out .= $tmplabel;
1925 $out .= '</option>';
1926 } else {
1927 $out .= '<option value="' . $obj->rowid . '"';
1928 if ($disabled) {
1929 $out .= ' disabled';
1930 }
1931 $out .= '>';
1932
1933 $tmplabel = $contactstatic->getFullName($langs) . $extendedInfos;
1934 if ($showfunction && $obj->poste) {
1935 $tmplabel .= ' (' . $obj->poste . ')';
1936 }
1937 if (($showsoc > 0) && $obj->company) {
1938 $tmplabel .= ' - (' . $obj->company . ')';
1939 }
1940
1941 $out .= $tmplabel;
1942 $out .= '</option>';
1943 }
1944 } else {
1945 if (in_array($obj->rowid, $selected)) {
1946 $tmplabel = $contactstatic->getFullName($langs) . $extendedInfos;
1947 if ($showfunction && $obj->poste) {
1948 $tmplabel .= ' (' . $obj->poste . ')';
1949 }
1950 if (($showsoc > 0) && $obj->company) {
1951 $tmplabel .= ' - (' . $obj->company . ')';
1952 }
1953
1954 $out .= $tmplabel;
1955 }
1956 }
1957
1958 if ($tmplabel != '') {
1959 array_push($outarray, array('key' => $obj->rowid, 'value' => $tmplabel, 'label' => $tmplabel, 'labelhtml' => $tmplabel));
1960 }
1961 }
1962 $i++;
1963 }
1964 } else {
1965 $labeltoshow = ($socid != -1) ? ($langs->trans($socid ? "NoContactDefinedForThirdParty" : "NoContactDefined")) : $langs->trans('SelectAThirdPartyFirst');
1966 $out .= '<option class="disabled" value="-1"' . (($showempty == 2 || $multiple) ? '' : ' selected') . ' disabled="disabled">';
1967 $out .= $labeltoshow;
1968 $out .= '</option>';
1969 }
1970
1971 $parameters = array(
1972 'socid' => $socid,
1973 'htmlname' => $htmlname,
1974 'resql' => $resql,
1975 'out' => &$out,
1976 'showfunction' => $showfunction,
1977 'showsoc' => $showsoc,
1978 );
1979
1980 $reshook = $hookmanager->executeHooks('afterSelectContactOptions', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1981
1982 if ($htmlname != 'none' && !$options_only) {
1983 $out .= '</select>';
1984 }
1985
1986 if ($conf->use_javascript_ajax && !$forcecombo && !$options_only) {
1987 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1988 $out .= ajax_combobox($htmlid, $events, getDolGlobalInt("CONTACT_USE_SEARCH_TO_SELECT"));
1989 }
1990
1991 $this->num = $num;
1992
1993 if ($options_only === 2) {
1994 // Return array of options
1995 return $outarray;
1996 } else {
1997 return $out;
1998 }
1999 } else {
2000 dol_print_error($this->db);
2001 return -1;
2002 }
2003 }
2004
2005
2006 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2007
2018 public function select_remises($selected, $htmlname, $filter, $socid, $maxvalue = 0)
2019 {
2020 // phpcs:enable
2021 global $langs, $conf;
2022
2023 // On recherche les remises
2024 $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
2025 $sql .= " re.description, re.fk_facture_source";
2026 $sql .= " FROM " . $this->db->prefix() . "societe_remise_except as re";
2027 $sql .= " WHERE re.fk_soc = " . (int) $socid;
2028 $sql .= " AND re.entity = " . $conf->entity;
2029 if ($filter) {
2030 $sql .= " AND " . $filter;
2031 }
2032 $sql .= " ORDER BY re.description ASC";
2033
2034 dol_syslog(get_class($this) . "::select_remises", LOG_DEBUG);
2035 $resql = $this->db->query($sql);
2036 if ($resql) {
2037 print '<select id="select_' . $htmlname . '" class="flat maxwidthonsmartphone" name="' . $htmlname . '">';
2038 $num = $this->db->num_rows($resql);
2039
2040 $qualifiedlines = $num;
2041
2042 $i = 0;
2043 if ($num) {
2044 print '<option value="0">&nbsp;</option>';
2045 while ($i < $num) {
2046 $obj = $this->db->fetch_object($resql);
2047 $desc = dol_trunc($obj->description, 40);
2048 if (preg_match('/\‍(CREDIT_NOTE\‍)/', $desc)) {
2049 $desc = preg_replace('/\‍(CREDIT_NOTE\‍)/', $langs->trans("CreditNote"), $desc);
2050 }
2051 if (preg_match('/\‍(DEPOSIT\‍)/', $desc)) {
2052 $desc = preg_replace('/\‍(DEPOSIT\‍)/', $langs->trans("Deposit"), $desc);
2053 }
2054 if (preg_match('/\‍(EXCESS RECEIVED\‍)/', $desc)) {
2055 $desc = preg_replace('/\‍(EXCESS RECEIVED\‍)/', $langs->trans("ExcessReceived"), $desc);
2056 }
2057 if (preg_match('/\‍(EXCESS PAID\‍)/', $desc)) {
2058 $desc = preg_replace('/\‍(EXCESS PAID\‍)/', $langs->trans("ExcessPaid"), $desc);
2059 }
2060
2061 $selectstring = '';
2062 if ($selected > 0 && $selected == $obj->rowid) {
2063 $selectstring = ' selected';
2064 }
2065
2066 $disabled = '';
2067 if ($maxvalue > 0 && $obj->amount_ttc > $maxvalue) {
2068 $qualifiedlines--;
2069 $disabled = ' disabled';
2070 }
2071
2072 if (getDolGlobalString('MAIN_SHOW_FACNUMBER_IN_DISCOUNT_LIST') && !empty($obj->fk_facture_source)) {
2073 $tmpfac = new Facture($this->db);
2074 if ($tmpfac->fetch($obj->fk_facture_source) > 0) {
2075 $desc = $desc . ' - ' . $tmpfac->ref;
2076 }
2077 }
2078
2079 print '<option value="' . $obj->rowid . '"' . $selectstring . $disabled . '>' . $desc . ' (' . price($obj->amount_ht) . ' ' . $langs->trans("HT") . ' - ' . price($obj->amount_ttc) . ' ' . $langs->trans("TTC") . ')</option>';
2080 $i++;
2081 }
2082 }
2083 print '</select>';
2084 print ajax_combobox('select_' . $htmlname);
2085
2086 return $qualifiedlines;
2087 } else {
2088 dol_print_error($this->db);
2089 return -1;
2090 }
2091 }
2092
2093
2094 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2095
2111 public function select_users($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0')
2112 {
2113 // phpcs:enable
2114 print $this->select_dolusers($selected, $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity);
2115 }
2116
2117 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2118
2143 public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '', $maxlength = 0, $showstatus = 0, $morefilter = '', $show_every = 0, $enableonlytext = '', $morecss = '', $notdisabled = 0, $outputmode = 0, $multiple = false, $forcecombo = 0)
2144 {
2145 // phpcs:enable
2146 global $conf, $user, $langs, $hookmanager;
2147 global $action;
2148
2149 // If no preselected user defined, we take current user
2150 if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) {
2151 $selected = $user->id;
2152 }
2153
2154 if ($selected === '') {
2155 $selected = array();
2156 } elseif (!is_array($selected)) {
2157 $selected = array($selected);
2158 }
2159
2160 $excludeUsers = null;
2161 $includeUsers = null;
2162
2163 // Exclude some users
2164 if (is_array($exclude)) {
2165 $excludeUsers = implode(",", $exclude);
2166 }
2167 // Include some uses
2168 if (is_array($include)) {
2169 $includeUsers = implode(",", $include);
2170 } elseif ($include == 'hierarchy') {
2171 // Build list includeUsers to have only hierarchy
2172 $includeUsers = implode(",", $user->getAllChildIds(0));
2173 } elseif ($include == 'hierarchyme') {
2174 // Build list includeUsers to have only hierarchy and current user
2175 $includeUsers = implode(",", $user->getAllChildIds(1));
2176 }
2177
2178 $num = 0;
2179
2180 $out = '';
2181 $outarray = array();
2182 $outarray2 = array();
2183
2184 // Do we want to show the label of entity into the combo list ?
2185 $showlabelofentity = isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1 && !empty($user->admin) && empty($user->entity);
2186 $userissuperadminentityone = isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && empty($user->entity);
2187
2188 // Forge request to select users
2189 $sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut as status, u.login, u.admin, u.entity, u.gender, u.photo";
2190 if ($showlabelofentity) {
2191 $sql .= ", e.label";
2192 }
2193 $sql .= " FROM " . $this->db->prefix() . "user as u";
2194 if ($showlabelofentity) {
2195 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid = u.entity";
2196 }
2197 // Condition here should be the same than into societe->getSalesRepresentatives().
2198 if ($userissuperadminentityone && $force_entity !== 'default') {
2199 if (!empty($force_entity)) {
2200 $sql .= " WHERE u.entity IN (0, " . $this->db->sanitize($force_entity) . ")";
2201 } else {
2202 $sql .= " WHERE u.entity IS NOT NULL";
2203 }
2204 } else {
2205 if (isModEnabled('multicompany') && getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE')) {
2206 $sql .= " WHERE u.rowid IN (SELECT ug.fk_user FROM ".$this->db->prefix()."usergroup_user as ug WHERE ug.entity IN (".getEntity('usergroup')."))";
2207 } else {
2208 $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
2209 }
2210 }
2211
2212 if (!empty($user->socid)) {
2213 $sql .= " AND u.fk_soc = " . ((int) $user->socid);
2214 }
2215 if (is_array($exclude) && $excludeUsers) {
2216 $sql .= " AND u.rowid NOT IN (" . $this->db->sanitize($excludeUsers) . ")";
2217 }
2218 if ($includeUsers) {
2219 $sql .= " AND u.rowid IN (" . $this->db->sanitize($includeUsers) . ")";
2220 }
2221 if (getDolGlobalString('USER_HIDE_INACTIVE_IN_COMBOBOX') || $notdisabled) {
2222 $sql .= " AND u.statut <> 0";
2223 }
2224 if (getDolGlobalString('USER_HIDE_NONEMPLOYEE_IN_COMBOBOX') || $notdisabled) {
2225 $sql .= " AND u.employee <> 0";
2226 }
2227 if (getDolGlobalString('USER_HIDE_EXTERNAL_IN_COMBOBOX') || $notdisabled) {
2228 $sql .= " AND u.fk_soc IS NULL";
2229 }
2230 if (!empty($morefilter)) {
2231 $sql .= " " . $morefilter;
2232 }
2233
2234 //Add hook to filter on user (for example on usergroup define in custom modules)
2235 $reshook = $hookmanager->executeHooks('addSQLWhereFilterOnSelectUsers', array(), $this, $action);
2236 if (!empty($reshook)) {
2237 $sql .= $hookmanager->resPrint;
2238 }
2239
2240 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) { // MAIN_FIRSTNAME_NAME_POSITION is 0 means firstname+lastname
2241 $sql .= " ORDER BY u.statut DESC, u.firstname ASC, u.lastname ASC";
2242 } else {
2243 $sql .= " ORDER BY u.statut DESC, u.lastname ASC, u.firstname ASC";
2244 }
2245
2246 dol_syslog(get_class($this) . "::select_dolusers", LOG_DEBUG);
2247
2248 $resql = $this->db->query($sql);
2249 if ($resql) {
2250 $num = $this->db->num_rows($resql);
2251 $i = 0;
2252 if ($num) {
2253 // do not use maxwidthonsmartphone by default. Set it by caller so auto size to 100% will work when not defined
2254 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : ' minwidth200') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
2255 if ($show_empty && !$multiple) {
2256 $textforempty = ' ';
2257 if (!empty($conf->use_javascript_ajax)) {
2258 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
2259 }
2260 if (!is_numeric($show_empty)) {
2261 $textforempty = $show_empty;
2262 }
2263 $out .= '<option class="optiongrey" value="' . ($show_empty < 0 ? $show_empty : -1) . '"' . ((empty($selected) || in_array(-1, $selected)) ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
2264
2265 $outarray[($show_empty < 0 ? $show_empty : -1)] = $textforempty;
2266 $outarray2[($show_empty < 0 ? $show_empty : -1)] = array(
2267 'id' => ($show_empty < 0 ? $show_empty : -1),
2268 'label' => $textforempty,
2269 'labelhtml' => $textforempty,
2270 'color' => '',
2271 'picto' => ''
2272 );
2273 }
2274 if ($show_every) {
2275 $out .= '<option value="-2"' . ((in_array(-2, $selected)) ? ' selected' : '') . '>-- ' . $langs->trans("Everybody") . ' --</option>' . "\n";
2276
2277 $outarray[-2] = '-- ' . $langs->trans("Everybody") . ' --';
2278 $outarray2[-2] = array(
2279 'id' => -2,
2280 'label' => '-- ' . $langs->trans("Everybody") . ' --',
2281 'labelhtml' => '-- ' . $langs->trans("Everybody") . ' --',
2282 'color' => '',
2283 'picto' => ''
2284 );
2285 }
2286
2287 $userstatic = new User($this->db);
2288
2289 while ($i < $num) {
2290 $obj = $this->db->fetch_object($resql);
2291
2292 $userstatic->id = $obj->rowid;
2293 $userstatic->lastname = $obj->lastname;
2294 $userstatic->firstname = $obj->firstname;
2295 $userstatic->photo = $obj->photo;
2296 $userstatic->status = $obj->status;
2297 $userstatic->entity = $obj->entity;
2298 $userstatic->admin = $obj->admin;
2299 $userstatic->gender = $obj->gender;
2300
2301 $disableline = '';
2302 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
2303 $disableline = ($enableonlytext ? $enableonlytext : '1');
2304 }
2305
2306 $labeltoshow = '';
2307 $labeltoshowhtml = '';
2308
2309 // $fullNameMode is 0=Lastname+Firstname (MAIN_FIRSTNAME_NAME_POSITION=1), 1=Firstname+Lastname (MAIN_FIRSTNAME_NAME_POSITION=0)
2310 $fullNameMode = 0;
2311 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) {
2312 $fullNameMode = 1; //Firstname+lastname
2313 }
2314 $labeltoshow .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2315 $labeltoshowhtml .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2316 if (empty($obj->firstname) && empty($obj->lastname)) {
2317 $labeltoshow .= $obj->login;
2318 $labeltoshowhtml .= $obj->login;
2319 }
2320
2321 // Complete name with a more info string like: ' (info1 - info2 - ...)'
2322 $moreinfo = '';
2323 $moreinfohtml = '';
2324 if (getDolGlobalString('MAIN_SHOW_LOGIN')) {
2325 $moreinfo .= ($moreinfo ? ' - ' : ' (');
2326 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(');
2327 $moreinfo .= $obj->login;
2328 $moreinfohtml .= $obj->login;
2329 }
2330 if ($showstatus >= 0) {
2331 if ($obj->status == 1 && $showstatus == 1) {
2332 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Enabled');
2333 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Enabled');
2334 }
2335 if ($obj->status == 0 && $showstatus == 1) {
2336 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Disabled');
2337 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Disabled');
2338 }
2339 }
2340 if ($showlabelofentity) {
2341 if (empty($obj->entity)) {
2342 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans("AllEntities");
2343 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans("AllEntities");
2344 } else {
2345 if ($obj->entity != $conf->entity) {
2346 $moreinfo .= ($moreinfo ? ' - ' : ' (') . ($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2347 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(').($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2348 }
2349 }
2350 }
2351 $moreinfo .= (!empty($moreinfo) ? ')' : '');
2352 $moreinfohtml .= (!empty($moreinfohtml) ? ')</span>' : '');
2353 if (!empty($disableline) && $disableline != '1') {
2354 // Add text from $enableonlytext parameter
2355 $moreinfo .= ' - ' . $disableline;
2356 $moreinfohtml .= ' - ' . $disableline;
2357 }
2358 $labeltoshow .= $moreinfo;
2359 $labeltoshowhtml .= $moreinfohtml;
2360
2361 $out .= '<option value="' . $obj->rowid . '"';
2362 if (!empty($disableline)) {
2363 $out .= ' disabled';
2364 }
2365 if ((!empty($selected[0]) && is_object($selected[0])) ? $selected[0]->id == $obj->rowid : in_array($obj->rowid, $selected)) {
2366 $out .= ' selected';
2367 }
2368 $out .= ' data-html="';
2369
2370 $outhtml = $userstatic->getNomUrl(-3, '', 0, 1, 24, 1, 'login', '', 1) . ' ';
2371 if ($showstatus >= 0 && $obj->status == 0) {
2372 $outhtml .= '<strike class="opacitymediumxxx">';
2373 }
2374 $outhtml .= $labeltoshowhtml;
2375 if ($showstatus >= 0 && $obj->status == 0) {
2376 $outhtml .= '</strike>';
2377 }
2378 $labeltoshowhtml = $outhtml;
2379
2380 $out .= dol_escape_htmltag($outhtml);
2381 $out .= '">';
2382 $out .= $labeltoshow;
2383 $out .= '</option>';
2384
2385 $outarray[$userstatic->id] = $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength) . $moreinfo;
2386 $outarray2[$userstatic->id] = array(
2387 'id' => $userstatic->id,
2388 'label' => $labeltoshow,
2389 'labelhtml' => $labeltoshowhtml,
2390 'color' => '',
2391 'picto' => ''
2392 );
2393
2394 $i++;
2395 }
2396 } else {
2397 $out .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '" disabled>';
2398 $out .= '<option value="">' . $langs->trans("None") . '</option>';
2399 }
2400 $out .= '</select>';
2401
2402 if ($num && !$forcecombo) {
2403 // Enhance with select2
2404 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2405 $out .= ajax_combobox($htmlname);
2406 }
2407 } else {
2408 dol_print_error($this->db);
2409 }
2410
2411 $this->num = $num;
2412
2413 if ($outputmode == 2) {
2414 return $outarray2;
2415 } elseif ($outputmode) {
2416 return $outarray;
2417 }
2418
2419 return $out;
2420 }
2421
2422
2423 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2446 public function select_dolusers_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = array(), $enableonly = array(), $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofuserid = array(), $listofcontactid = array(), $listofotherid = array())
2447 {
2448 // phpcs:enable
2449 global $langs;
2450
2451 $userstatic = new User($this->db);
2452 $out = '';
2453
2454 if (!empty($_SESSION['assignedtouser'])) {
2455 $assignedtouser = json_decode($_SESSION['assignedtouser'], true);
2456 if (!is_array($assignedtouser)) {
2457 $assignedtouser = array();
2458 }
2459 } else {
2460 $assignedtouser = array();
2461 }
2462 $nbassignetouser = count($assignedtouser);
2463
2464 //if ($nbassignetouser && $action != 'view') $out .= '<br>';
2465 if ($nbassignetouser) {
2466 $out .= '<ul class="attendees">';
2467 }
2468 $i = 0;
2469 $ownerid = 0;
2470 foreach ($assignedtouser as $key => $value) {
2471 if ($value['id'] == $ownerid) {
2472 continue;
2473 }
2474
2475 $out .= '<li>';
2476 $userstatic->fetch($value['id']);
2477 $out .= $userstatic->getNomUrl(-1);
2478 if ($i == 0) {
2479 $ownerid = $value['id'];
2480 $out .= ' (' . $langs->trans("Owner") . ')';
2481 }
2482 if ($nbassignetouser > 1 && $action != 'view') {
2483 $out .= ' <input type="image" style="border: 0px;" src="' . img_picto($langs->trans("Remove"), 'delete', '', 0, 1) . '" value="' . $userstatic->id . '" class="removedassigned reposition" id="removedassigned_' . $userstatic->id . '" name="removedassigned_' . $userstatic->id . '">';
2484 }
2485 // Show my availability
2486 if ($showproperties) {
2487 if ($ownerid == $value['id'] && is_array($listofuserid) && count($listofuserid) && in_array($ownerid, array_keys($listofuserid))) {
2488 $out .= '<div class="myavailability inline-block">';
2489 $out .= '<span class="hideonsmartphone">&nbsp;-&nbsp;<span class="opacitymedium">' . $langs->trans("Availability") . ':</span> </span><input id="transparency" class="paddingrightonly" ' . ($action == 'view' ? 'disabled' : '') . ' type="checkbox" name="transparency"' . ($listofuserid[$ownerid]['transparency'] ? ' checked' : '') . '><label for="transparency">' . $langs->trans("Busy") . '</label>';
2490 $out .= '</div>';
2491 }
2492 }
2493 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2494 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2495
2496 $out .= '</li>';
2497 $i++;
2498 }
2499 if ($nbassignetouser) {
2500 $out .= '</ul>';
2501 }
2502
2503 // Method with no ajax
2504 if ($action != 'view') {
2505 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassigned" value="">';
2506 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2507 $out .= 'jQuery(".removedassigned").click(function() { jQuery(".removedassignedhidden").val(jQuery(this).val()); });';
2508 $out .= 'jQuery(".assignedtouser").change(function() { console.log(jQuery(".assignedtouser option:selected").val());';
2509 $out .= ' if (jQuery(".assignedtouser option:selected").val() > 0) { jQuery("#' . $action . 'assignedtouser").attr("disabled", false); }';
2510 $out .= ' else { jQuery("#' . $action . 'assignedtouser").attr("disabled", true); }';
2511 $out .= '});';
2512 $out .= '})</script>';
2513 $out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2514 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtouser" name="' . $action . 'assignedtouser" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2515 $out .= '<br>';
2516 }
2517
2518 return $out;
2519 }
2520
2521 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2541 public function select_dolresources_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = array(), $enableonly = array(), $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofresourceid = array())
2542 {
2543 // phpcs:enable
2544 global $langs;
2545
2546 require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php';
2547 require_once DOL_DOCUMENT_ROOT.'/resource/class/dolresource.class.php';
2548 $formresources = new FormResource($this->db);
2549 $resourcestatic = new Dolresource($this->db);
2550
2551 $out = '';
2552 if (!empty($_SESSION['assignedtoresource'])) {
2553 $assignedtoresource = json_decode($_SESSION['assignedtoresource'], true);
2554 if (!is_array($assignedtoresource)) {
2555 $assignedtoresource = array();
2556 }
2557 } else {
2558 $assignedtoresource = array();
2559 }
2560 $nbassignetoresource = count($assignedtoresource);
2561
2562 //if ($nbassignetoresource && $action != 'view') $out .= '<br>';
2563 if ($nbassignetoresource) {
2564 $out .= '<ul class="attendees">';
2565 }
2566 $i = 0;
2567
2568 foreach ($assignedtoresource as $key => $value) {
2569 $out .= '<li>';
2570 $resourcestatic->fetch($value['id']);
2571 $out .= $resourcestatic->getNomUrl(-1);
2572 if ($nbassignetoresource > 1 && $action != 'view') {
2573 $out .= ' <input type="image" style="border: 0px;" src="' . img_picto($langs->trans("Remove"), 'delete', '', 0, 1) . '" value="' . $resourcestatic->id . '" class="removedassigned reposition" id="removedassignedresource_' . $resourcestatic->id . '" name="removedassignedresource_' . $resourcestatic->id . '">';
2574 }
2575 // Show my availability
2576 if ($showproperties) {
2577 if (is_array($listofresourceid) && count($listofresourceid)) {
2578 $out .= '<div class="myavailability inline-block">';
2579 $out .= '<span class="hideonsmartphone">&nbsp;-&nbsp;<span class="opacitymedium">' . $langs->trans("Availability") . ':</span> </span><input id="transparencyresource" class="paddingrightonly" ' . ($action == 'view' ? 'disabled' : '') . ' type="checkbox" name="transparency"' . ($listofresourceid[$value['id']]['transparency'] ? ' checked' : '') . '><label for="transparency">' . $langs->trans("Busy") . '</label>';
2580 $out .= '</div>';
2581 }
2582 }
2583 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2584 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2585
2586 $out .= '</li>';
2587 $i++;
2588 }
2589 if ($nbassignetoresource) {
2590 $out .= '</ul>';
2591 }
2592
2593 // Method with no ajax
2594 if ($action != 'view') {
2595 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassignedresource" value="">';
2596 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2597 $out .= 'jQuery(".removedassignedresource").click(function() { jQuery(".removedassignedresourcehidden").val(jQuery(this).val()); });';
2598 $out .= 'jQuery(".assignedtoresource").change(function() { console.log(jQuery(".assignedtoresource option:selected").val());';
2599 $out .= ' if (jQuery(".assignedtoresource option:selected").val() > 0) { jQuery("#' . $action . 'assignedtoresource").attr("disabled", false); }';
2600 $out .= ' else { jQuery("#' . $action . 'assignedtoresource").attr("disabled", true); }';
2601 $out .= '});';
2602 $out .= '})</script>';
2603
2604 $events = array();
2605 $out .= img_picto('', 'resource', 'class="pictofixedwidth"');
2606 $out .= $formresources->select_resource_list(0, $htmlname, [], 1, 1, 0, $events, array(), 2, 0);
2607 //$out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2608 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtoresource" name="' . $action . 'assignedtoresource" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2609 $out .= '<br>';
2610 }
2611
2612 return $out;
2613 }
2614
2615 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2616
2645 public function select_produits($selected = 0, $htmlname = 'productid', $filtertype = '', $limit = 0, $price_level = 0, $status = 1, $finished = 2, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $selected_combinations = null, $nooutput = 0, $status_purchase = -1)
2646 {
2647 // phpcs:enable
2648 global $langs, $conf;
2649
2650 $out = '';
2651
2652 // check parameters
2653 $price_level = (!empty($price_level) ? $price_level : 0);
2654 if (is_null($ajaxoptions)) {
2655 $ajaxoptions = array();
2656 }
2657
2658 if (strval($filtertype) === '' && (isModEnabled("product") || isModEnabled("service"))) {
2659 if (isModEnabled("product") && !isModEnabled('service')) {
2660 $filtertype = '0';
2661 } elseif (!isModEnabled('product') && isModEnabled("service")) {
2662 $filtertype = '1';
2663 }
2664 }
2665
2666 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
2667 $placeholder = '';
2668
2669 if ($selected && empty($selected_input_value)) {
2670 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2671 $producttmpselect = new Product($this->db);
2672 $producttmpselect->fetch($selected);
2673 $selected_input_value = $producttmpselect->ref;
2674 unset($producttmpselect);
2675 }
2676 // handle case where product or service module is disabled + no filter specified
2677 if ($filtertype == '') {
2678 if (!isModEnabled('product')) { // when product module is disabled, show services only
2679 $filtertype = 1;
2680 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
2681 $filtertype = 0;
2682 }
2683 }
2684 // mode=1 means customers products
2685 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=1&status=' . $status . '&status_purchase=' . $status_purchase . '&finished=' . $finished . '&hidepriceinlabel=' . $hidepriceinlabel . '&warehousestatus=' . $warehouseStatus;
2686 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
2687
2688 if (isModEnabled('variants') && is_array($selected_combinations)) {
2689 // Code to automatically insert with javascript the select of attributes under the select of product
2690 // when a parent of variant has been selected.
2691 $out .= '
2692 <!-- script to auto show attributes select tags if a variant was selected -->
2693 <script nonce="' . getNonce() . '">
2694 // auto show attributes fields
2695 selected = ' . json_encode($selected_combinations) . ';
2696 combvalues = {};
2697
2698 jQuery(document).ready(function () {
2699
2700 jQuery("input[name=\'prod_entry_mode\']").change(function () {
2701 if (jQuery(this).val() == \'free\') {
2702 jQuery(\'div#attributes_box\').empty();
2703 }
2704 });
2705
2706 jQuery("input#' . $htmlname . '").change(function () {
2707
2708 if (!jQuery(this).val()) {
2709 jQuery(\'div#attributes_box\').empty();
2710 return;
2711 }
2712
2713 console.log("A change has started. We get variants fields to inject html select");
2714
2715 jQuery.getJSON("' . DOL_URL_ROOT . '/variants/ajax/getCombinations.php", {
2716 id: jQuery(this).val()
2717 }, function (data) {
2718 jQuery(\'div#attributes_box\').empty();
2719
2720 jQuery.each(data, function (key, val) {
2721
2722 combvalues[val.id] = val.values;
2723
2724 var span = jQuery(document.createElement(\'div\')).css({
2725 \'display\': \'table-row\'
2726 });
2727
2728 span.append(
2729 jQuery(document.createElement(\'div\')).text(val.label).css({
2730 \'font-weight\': \'bold\',
2731 \'display\': \'table-cell\'
2732 })
2733 );
2734
2735 var html = jQuery(document.createElement(\'select\')).attr(\'name\', \'combinations[\' + val.id + \']\').css({
2736 \'margin-left\': \'15px\',
2737 \'white-space\': \'pre\'
2738 }).append(
2739 jQuery(document.createElement(\'option\')).val(\'\')
2740 );
2741
2742 jQuery.each(combvalues[val.id], function (key, val) {
2743 var tag = jQuery(document.createElement(\'option\')).val(val.id).html(val.value);
2744
2745 if (selected[val.fk_product_attribute] == val.id) {
2746 tag.attr(\'selected\', \'selected\');
2747 }
2748
2749 html.append(tag);
2750 });
2751
2752 span.append(html);
2753 jQuery(\'div#attributes_box\').append(span);
2754 });
2755 })
2756 });
2757
2758 ' . ($selected ? 'jQuery("input#' . $htmlname . '").change();' : '') . '
2759 });
2760 </script>
2761 ';
2762 }
2763
2764 if (empty($hidelabel)) {
2765 $out .= $langs->trans("RefOrLabel") . ' : ';
2766 } elseif ($hidelabel > 1) {
2767 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
2768 if ($hidelabel == 2) {
2769 $out .= img_picto($langs->trans("Search"), 'search');
2770 }
2771 }
2772 $out .= '<input type="text" class="minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
2773 if ($hidelabel == 3) {
2774 $out .= img_picto($langs->trans("Search"), 'search');
2775 }
2776 } else {
2777 $out .= $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus, $status_purchase);
2778 }
2779
2780 if (empty($nooutput)) {
2781 print $out;
2782 } else {
2783 return $out;
2784 }
2785 }
2786
2787 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2788
2804 public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 0, $showempty = '1', $morecss = '', $nooutput = '', $forcecombo = 0, $TProducts = [])
2805 {
2806 // phpcs:enable
2807 global $db;
2808
2809 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2810
2811 $error = 0;
2812 $out = '';
2813
2814 if (!$forcecombo) {
2815 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2816 $events = array();
2817 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
2818 }
2819
2820 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
2821
2822 $sql = 'SELECT b.rowid, b.ref, b.label, b.fk_product';
2823 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'bom_bom as b';
2824 $sql .= ' WHERE b.entity IN (' . getEntity('bom') . ')';
2825 if (!empty($status)) {
2826 $sql .= ' AND status = ' . (int) $status;
2827 }
2828 if (!empty($type)) {
2829 $sql .= ' AND bomtype = ' . (int) $type;
2830 }
2831 if (!empty($TProducts)) {
2832 $sql .= ' AND fk_product IN (' . $this->db->sanitize(implode(',', $TProducts)) . ')';
2833 }
2834 if (!empty($limit)) {
2835 $sql .= ' LIMIT ' . (int) $limit;
2836 }
2837 $resql = $db->query($sql);
2838 if ($resql) {
2839 if ($showempty) {
2840 $out .= '<option value="-1"';
2841 if (empty($selected)) {
2842 $out .= ' selected';
2843 }
2844 $out .= '>&nbsp;</option>';
2845 }
2846 while ($obj = $db->fetch_object($resql)) {
2847 $product = new Product($db);
2848 $res = $product->fetch($obj->fk_product);
2849 $out .= '<option value="' . $obj->rowid . '"';
2850 if ($obj->rowid == $selected) {
2851 $out .= 'selected';
2852 }
2853 $out .= '>' . $obj->ref . ' - ' . $product->label . ' - ' . $obj->label . '</option>';
2854 }
2855 } else {
2856 $error++;
2857 dol_print_error($db);
2858 }
2859 $out .= '</select>';
2860 if (empty($nooutput)) {
2861 print $out;
2862 } else {
2863 return $out;
2864 }
2865 }
2866
2867 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2868
2894 public function select_produits_list($selected = 0, $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = 'maxwidth500', $hidepriceinlabel = 0, $warehouseStatus = '', $status_purchase = -1)
2895 {
2896 // phpcs:enable
2897 global $langs;
2898 global $hookmanager;
2899
2900 $out = '';
2901 $outarray = array();
2902
2903 // Units
2904 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2905 $langs->load('other');
2906 }
2907
2908 $warehouseStatusArray = array();
2909 if (!empty($warehouseStatus)) {
2910 require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
2911 if (preg_match('/warehouseclosed/', $warehouseStatus)) {
2912 $warehouseStatusArray[] = Entrepot::STATUS_CLOSED;
2913 }
2914 if (preg_match('/warehouseopen/', $warehouseStatus)) {
2915 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL;
2916 }
2917 if (preg_match('/warehouseinternal/', $warehouseStatus)) {
2918 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL;
2919 }
2920 }
2921
2922 $selectFields = " p.rowid, p.ref, p.label, p.description, p.barcode, p.fk_country, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.default_vat_code, p.duration, p.fk_price_expression";
2923 if (count($warehouseStatusArray)) {
2924 $selectFieldsGrouped = ", sum(" . $this->db->ifsql("e.statut IS NULL", "0", "ps.reel") . ") as stock"; // e.statut is null if there is no record in stock
2925 } else {
2926 $selectFieldsGrouped = ", " . $this->db->ifsql("p.stock IS NULL", 0, "p.stock") . " AS stock";
2927 }
2928
2929 $sql = "SELECT ";
2930
2931 // Add select from hooks
2932 $parameters = array();
2933 $reshook = $hookmanager->executeHooks('selectProductsListSelect', $parameters); // Note that $action and $object may have been modified by hook
2934 if (empty($reshook)) {
2935 $sql .= $selectFields.$selectFieldsGrouped.$hookmanager->resPrint;
2936 } else {
2937 $sql .= $hookmanager->resPrint;
2938 }
2939
2940 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
2941 //Product category
2942 $sql .= ", (SELECT " . $this->db->prefix() . "categorie_product.fk_categorie
2943 FROM " . $this->db->prefix() . "categorie_product
2944 WHERE " . $this->db->prefix() . "categorie_product.fk_product=p.rowid
2945 LIMIT 1
2946 ) AS categorie_product_id ";
2947 }
2948
2949 //Price by customer
2950 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2951 $sql .= ', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
2952 $sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx, pcp.default_vat_code as custdefault_vat_code, pcp.ref_customer as custref';
2953 $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custdefault_vat_code, custref";
2954 }
2955 // Units
2956 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2957 $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units";
2958 $selectFields .= ', unit_long, unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units';
2959 }
2960
2961 // Multilang : we add translation
2962 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2963 $sql .= ", pl.label as label_translated";
2964 $sql .= ", pl.description as description_translated";
2965 $selectFields .= ", label_translated";
2966 $selectFields .= ", description_translated";
2967 }
2968 // Price by quantity
2969 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2970 $sql .= ", (SELECT pp.rowid FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid";
2971 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2972 $sql .= " AND price_level = " . ((int) $price_level);
2973 }
2974 $sql .= " ORDER BY date_price";
2975 $sql .= " DESC LIMIT 1) as price_rowid";
2976 $sql .= ", (SELECT pp.price_by_qty FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid"; // price_by_qty is 1 if some prices by qty exists in subtable
2977 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2978 $sql .= " AND price_level = " . ((int) $price_level);
2979 }
2980 $sql .= " ORDER BY date_price";
2981 $sql .= " DESC LIMIT 1) as price_by_qty";
2982 $selectFields .= ", price_rowid, price_by_qty";
2983 }
2984
2985 $sql .= " FROM ".$this->db->prefix()."product as p";
2986
2987 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_FORCE_INDEX')) {
2988 $sql .= " USE INDEX (" . $this->db->sanitize(getDolGlobalString('MAIN_PRODUCT_FORCE_INDEX')) . ")";
2989 }
2990
2991 // Add from (left join) from hooks
2992 $parameters = array();
2993 $reshook = $hookmanager->executeHooks('selectProductsListFrom', $parameters); // Note that $action and $object may have been modified by hook
2994 $sql .= $hookmanager->resPrint;
2995
2996 if (count($warehouseStatusArray)) {
2997 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_stock as ps on ps.fk_product = p.rowid";
2998 $sql .= " LEFT JOIN " . $this->db->prefix() . "entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (" . getEntity('stock') . ")";
2999 $sql .= ' AND e.statut IN (' . $this->db->sanitize($this->db->escape(implode(',', $warehouseStatusArray))) . ')'; // Return line if product is inside the selected stock. If not, an empty line will be returned so we will count 0.
3000 }
3001
3002 //Price by customer
3003 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
3004 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_customer_price as pcp ON pcp.fk_soc=" . ((int) $socid) . " AND pcp.fk_product=p.rowid";
3005 }
3006 // Units
3007 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3008 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3009 }
3010 // Multilang : we add translation
3011 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3012 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_lang as pl ON pl.fk_product = p.rowid ";
3013 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE') && !empty($socid)) {
3014 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
3015 $soc = new Societe($this->db);
3016 $result = $soc->fetch($socid);
3017 if ($result > 0 && !empty($soc->default_lang)) {
3018 $sql .= " AND pl.lang = '" . $this->db->escape($soc->default_lang) . "'";
3019 } else {
3020 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
3021 }
3022 } else {
3023 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
3024 }
3025 }
3026
3027 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
3028 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_attribute_combination pac ON pac.fk_product_child = p.rowid";
3029 }
3030
3031 $sql .= ' WHERE p.entity IN (' . getEntity('product') . ')';
3032
3033 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
3034 $sql .= " AND pac.rowid IS NULL";
3035 }
3036
3037 if ($finished == 0) {
3038 $sql .= " AND p.finished = " . ((int) $finished);
3039 } elseif ($finished == 1) {
3040 $sql .= " AND p.finished = ".((int) $finished);
3041 }
3042 if ($status >= 0) {
3043 $sql .= " AND p.tosell = ".((int) $status);
3044 }
3045 if ($status_purchase >= 0) {
3046 $sql .= " AND p.tobuy = " . ((int) $status_purchase);
3047 }
3048 // Filter by product type
3049 if (strval($filtertype) != '') {
3050 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3051 } elseif (!isModEnabled('product')) { // when product module is disabled, show services only
3052 $sql .= " AND p.fk_product_type = 1";
3053 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
3054 $sql .= " AND p.fk_product_type = 0";
3055 }
3056 // Add where from hooks
3057 $parameters = array();
3058 $reshook = $hookmanager->executeHooks('selectProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3059 $sql .= $hookmanager->resPrint;
3060 // Add criteria on ref/label
3061 if ($filterkey != '') {
3062 $sqlSupplierSearch= '';
3063
3064 $sql .= ' AND (';
3065 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3066 // For natural search
3067 $search_crit = explode(' ', $filterkey);
3068 $i = 0;
3069 if (count($search_crit) > 1) {
3070 $sql .= "(";
3071 }
3072 foreach ($search_crit as $crit) {
3073 if ($i > 0) {
3074 $sql .= " AND ";
3075 }
3076 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3077 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3078 $sql .= " OR pl.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3079 }
3080 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
3081 $sql .= " OR pcp.ref_customer LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3082 }
3083 if (getDolGlobalString('PRODUCT_AJAX_SEARCH_ON_DESCRIPTION')) {
3084 $sql .= " OR p.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3085 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3086 $sql .= " OR pl.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3087 }
3088 }
3089
3090 // include search in supplier ref
3091 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
3092 $sqlSupplierSearch .= !empty($sqlSupplierSearch) ? ' OR ':'';
3093 $sqlSupplierSearch .= " pfp.ref_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3094 }
3095 $sql .= ")";
3096 $i++;
3097 }
3098 if (count($search_crit) > 1) {
3099 $sql .= ")";
3100 }
3101 if (isModEnabled('barcode')) {
3102 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3103 }
3104
3105 // include search in supplier ref
3106 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
3107 $sql .= " OR EXISTS (SELECT pfp.fk_product FROM " . $this->db->prefix() . "product_fournisseur_price as pfp WHERE p.rowid = pfp.fk_product";
3108 $sql .= " AND (";
3109 $sql .= $sqlSupplierSearch;
3110 $sql .= "))";
3111 }
3112
3113 $sql .= ')';
3114 }
3115 if (count($warehouseStatusArray)) {
3116 $sql .= " GROUP BY " . $selectFields;
3117 }
3118
3119 //Sort by category
3120 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
3121 $sql .= " ORDER BY categorie_product_id ";
3122 //ASC OR DESC order
3123 (getDolGlobalInt('PRODUCT_SORT_BY_CATEGORY') == 1) ? $sql .= "ASC" : $sql .= "DESC";
3124 } else {
3125 $sql .= $this->db->order("p.ref");
3126 }
3127
3128 $sql .= $this->db->plimit($limit, 0);
3129
3130 // Build output string
3131 dol_syslog(get_class($this) . "::select_produits_list search products", LOG_DEBUG);
3132 $result = $this->db->query($sql);
3133 if ($result) {
3134 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3135 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3136 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3137
3138 $num = $this->db->num_rows($result);
3139
3140 $events = array();
3141
3142 if (!$forcecombo) {
3143 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
3144 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
3145 }
3146
3147 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
3148
3149 $textifempty = '';
3150 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
3151 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
3152 if (getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3153 if ($showempty && !is_numeric($showempty)) {
3154 $textifempty = $langs->trans($showempty);
3155 } else {
3156 $textifempty .= $langs->trans("All");
3157 }
3158 } else {
3159 if ($showempty && !is_numeric($showempty)) {
3160 $textifempty = $langs->trans($showempty);
3161 }
3162 }
3163 if ($showempty) {
3164 $out .= '<option value="-1" selected>' . ($textifempty ? $textifempty : '&nbsp;') . '</option>';
3165 }
3166
3167 $i = 0;
3168 while ($num && $i < $num) {
3169 $opt = '';
3170 $optJson = array();
3171 $objp = $this->db->fetch_object($result);
3172
3173 if ((getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) && !empty($objp->price_by_qty) && $objp->price_by_qty == 1) { // Price by quantity will return many prices for the same product
3174 $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type";
3175 $sql .= " FROM " . $this->db->prefix() . "product_price_by_qty";
3176 $sql .= " WHERE fk_product_price = " . ((int) $objp->price_rowid);
3177 $sql .= " ORDER BY quantity ASC";
3178
3179 dol_syslog(get_class($this) . "::select_produits_list search prices by qty", LOG_DEBUG);
3180 $result2 = $this->db->query($sql);
3181 if ($result2) {
3182 $nb_prices = $this->db->num_rows($result2);
3183 $j = 0;
3184 while ($nb_prices && $j < $nb_prices) {
3185 $objp2 = $this->db->fetch_object($result2);
3186
3187 $objp->price_by_qty_rowid = $objp2->rowid;
3188 $objp->price_by_qty_price_base_type = $objp2->price_base_type;
3189 $objp->price_by_qty_quantity = $objp2->quantity;
3190 $objp->price_by_qty_unitprice = $objp2->unitprice;
3191 $objp->price_by_qty_remise_percent = $objp2->remise_percent;
3192 // For backward compatibility
3193 $objp->quantity = $objp2->quantity;
3194 $objp->price = $objp2->price;
3195 $objp->unitprice = $objp2->unitprice;
3196 $objp->remise_percent = $objp2->remise_percent;
3197
3198 //$objp->tva_tx is not overwritten by $objp2 value
3199 //$objp->default_vat_code is not overwritten by $objp2 value
3200
3201 $this->constructProductListOption($objp, $opt, $optJson, 0, $selected, $hidepriceinlabel, $filterkey);
3202
3203 $j++;
3204
3205 // Add new entry
3206 // "key" value of json key array is used by jQuery automatically as selected value
3207 // "label" value of json key array is used by jQuery automatically as text for combo box
3208 $out .= $opt;
3209 array_push($outarray, $optJson);
3210 }
3211 }
3212 } else {
3213 if (isModEnabled('dynamicprices') && !empty($objp->fk_price_expression)) {
3214 $price_product = new Product($this->db);
3215 $price_product->fetch($objp->rowid, '', '', 1);
3216
3217 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3218 $priceparser = new PriceParser($this->db);
3219 $price_result = $priceparser->parseProduct($price_product);
3220 if ($price_result >= 0) {
3221 $objp->price = $price_result;
3222 $objp->unitprice = $price_result;
3223 //Calculate the VAT
3224 $objp->price_ttc = (float) price2num($objp->price) * (1 + ($objp->tva_tx / 100));
3225 $objp->price_ttc = price2num($objp->price_ttc, 'MU');
3226 }
3227 }
3228
3229 $this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected, $hidepriceinlabel, $filterkey);
3230 // Add new entry
3231 // "key" value of json key array is used by jQuery automatically as selected value
3232 // "label" value of json key array is used by jQuery automatically as text for combo box
3233 $out .= $opt;
3234 array_push($outarray, $optJson);
3235 }
3236
3237 $i++;
3238 }
3239
3240 $out .= '</select>';
3241
3242 $this->db->free($result);
3243
3244 if (empty($outputmode)) {
3245 return $out;
3246 }
3247
3248 return $outarray;
3249 } else {
3250 dol_print_error($this->db);
3251 }
3252
3253 return '';
3254 }
3255
3271 protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0)
3272 {
3273 global $langs, $conf, $user;
3274 global $hookmanager;
3275
3276 $outkey = '';
3277 $outval = '';
3278 $outref = '';
3279 $outlabel = '';
3280 $outlabel_translated = '';
3281 $outdesc = '';
3282 $outdesc_translated = '';
3283 $outbarcode = '';
3284 $outorigin = '';
3285 $outtype = '';
3286 $outprice_ht = '';
3287 $outprice_ttc = '';
3288 $outpricebasetype = '';
3289 $outtva_tx = '';
3290 $outdefault_vat_code = '';
3291 $outqty = 1;
3292 $outdiscount = 0;
3293
3294 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3295
3296 $label = $objp->label;
3297 if (!empty($objp->label_translated)) {
3298 $label = $objp->label_translated;
3299 }
3300 if (!empty($filterkey) && $filterkey != '') {
3301 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3302 }
3303
3304 $outkey = $objp->rowid;
3305 $outref = $objp->ref;
3306 $outrefcust = empty($objp->custref) ? '' : $objp->custref;
3307 $outlabel = $objp->label;
3308 $outdesc = $objp->description;
3309 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3310 $outlabel_translated = $objp->label_translated;
3311 $outdesc_translated = $objp->description_translated;
3312 }
3313 $outbarcode = $objp->barcode;
3314 $outorigin = $objp->fk_country;
3315 $outpbq = empty($objp->price_by_qty_rowid) ? '' : $objp->price_by_qty_rowid;
3316
3317 $outtype = $objp->fk_product_type;
3318 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3319 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3320
3321 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3322 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
3323 }
3324
3325 // Units
3326 $outvalUnits = '';
3327 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3328 if (!empty($objp->unit_short)) {
3329 $outvalUnits .= ' - ' . $objp->unit_short;
3330 }
3331 }
3332 if (getDolGlobalString('PRODUCT_SHOW_DIMENSIONS_IN_COMBO')) {
3333 if (!empty($objp->weight) && $objp->weight_units !== null) {
3334 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3335 $outvalUnits .= ' - ' . $unitToShow;
3336 }
3337 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3338 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3339 $outvalUnits .= ' - ' . $unitToShow;
3340 }
3341 if (!empty($objp->surface) && $objp->surface_units !== null) {
3342 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3343 $outvalUnits .= ' - ' . $unitToShow;
3344 }
3345 if (!empty($objp->volume) && $objp->volume_units !== null) {
3346 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3347 $outvalUnits .= ' - ' . $unitToShow;
3348 }
3349 }
3350 if ($outdurationvalue && $outdurationunit) {
3351 $da = array(
3352 'h' => $langs->trans('Hour'),
3353 'd' => $langs->trans('Day'),
3354 'w' => $langs->trans('Week'),
3355 'm' => $langs->trans('Month'),
3356 'y' => $langs->trans('Year')
3357 );
3358 if (isset($da[$outdurationunit])) {
3359 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3360 }
3361 }
3362
3363 $opt = '<option value="' . $objp->rowid . '"';
3364 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
3365 if (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0) {
3366 $opt .= ' pbq="' . $objp->price_by_qty_rowid . '" data-pbq="' . $objp->price_by_qty_rowid . '" data-pbqup="' . $objp->price_by_qty_unitprice . '" data-pbqbase="' . $objp->price_by_qty_price_base_type . '" data-pbqqty="' . $objp->price_by_qty_quantity . '" data-pbqpercent="' . $objp->price_by_qty_remise_percent . '"';
3367 }
3368 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3369 if ($user->hasRight('stock', 'lire')) {
3370 if ($objp->stock > 0) {
3371 $opt .= ' class="product_line_stock_ok"';
3372 } elseif ($objp->stock <= 0) {
3373 $opt .= ' class="product_line_stock_too_low"';
3374 }
3375 }
3376 }
3377 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
3378 $opt .= ' data-labeltrans="' . $outlabel_translated . '"';
3379 $opt .= ' data-desctrans="' . dol_escape_htmltag($outdesc_translated) . '"';
3380 }
3381 $opt .= '>';
3382 $opt .= $objp->ref;
3383 if (!empty($objp->custref)) {
3384 $opt .= ' (' . $objp->custref . ')';
3385 }
3386 if ($outbarcode) {
3387 $opt .= ' (' . $outbarcode . ')';
3388 }
3389 $opt .= ' - ' . dol_trunc($label, $maxlengtharticle);
3390 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3391 $opt .= ' (' . getCountry($outorigin, 1) . ')';
3392 }
3393
3394 $objRef = $objp->ref;
3395 if (!empty($objp->custref)) {
3396 $objRef .= ' (' . $objp->custref . ')';
3397 }
3398 if (!empty($filterkey) && $filterkey != '') {
3399 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3400 }
3401 $outval .= $objRef;
3402 if ($outbarcode) {
3403 $outval .= ' (' . $outbarcode . ')';
3404 }
3405 $outval .= ' - ' . dol_trunc($label, $maxlengtharticle);
3406 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3407 $outval .= ' (' . getCountry($outorigin, 1) . ')';
3408 }
3409
3410 // Units
3411 $opt .= $outvalUnits;
3412 $outval .= $outvalUnits;
3413
3414 $found = 0;
3415
3416 // Multiprice
3417 // If we need a particular price level (from 1 to n)
3418 if (empty($hidepriceinlabel) && $price_level >= 1 && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3419 $sql = "SELECT price, price_ttc, price_base_type, tva_tx, default_vat_code";
3420 $sql .= " FROM " . $this->db->prefix() . "product_price";
3421 $sql .= " WHERE fk_product = " . ((int) $objp->rowid);
3422 $sql .= " AND entity IN (" . getEntity('productprice') . ")";
3423 $sql .= " AND price_level = " . ((int) $price_level);
3424 $sql .= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid.
3425 $sql .= " LIMIT 1";
3426
3427 dol_syslog(get_class($this) . '::constructProductListOption search price for product ' . $objp->rowid . ' AND level ' . $price_level, LOG_DEBUG);
3428 $result2 = $this->db->query($sql);
3429 if ($result2) {
3430 $objp2 = $this->db->fetch_object($result2);
3431 if ($objp2) {
3432 $found = 1;
3433 if ($objp2->price_base_type == 'HT') {
3434 $opt .= ' - ' . price($objp2->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3435 $outval .= ' - ' . price($objp2->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3436 } else {
3437 $opt .= ' - ' . price($objp2->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3438 $outval .= ' - ' . price($objp2->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3439 }
3440 $outprice_ht = price($objp2->price);
3441 $outprice_ttc = price($objp2->price_ttc);
3442 $outpricebasetype = $objp2->price_base_type;
3443 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
3444 $outtva_tx = $objp2->tva_tx; // We use the vat rate on line of multiprice
3445 $outdefault_vat_code = $objp2->default_vat_code; // We use the vat code on line of multiprice
3446 } else {
3447 $outtva_tx = $objp->tva_tx; // We use the vat rate of product, not the one on line of multiprice
3448 $outdefault_vat_code = $objp->default_vat_code; // We use the vat code or product, not the one on line of multiprice
3449 }
3450 }
3451 } else {
3452 dol_print_error($this->db);
3453 }
3454 }
3455
3456 // Price by quantity
3457 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1 && (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3458 $found = 1;
3459 $outqty = $objp->quantity;
3460 $outdiscount = $objp->remise_percent;
3461 if ($objp->quantity == 1) {
3462 $opt .= ' - ' . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/";
3463 $outval .= ' - ' . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/";
3464 $opt .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3465 $outval .= $langs->transnoentities("Unit");
3466 } else {
3467 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3468 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3469 $opt .= $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3470 $outval .= $langs->transnoentities("Units");
3471 }
3472
3473 $outprice_ht = price($objp->unitprice);
3474 $outprice_ttc = price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
3475 $outpricebasetype = $objp->price_base_type;
3476 $outtva_tx = $objp->tva_tx; // This value is the value on product when constructProductListOption is called by select_produits_list even if other field $objp-> are from table price_by_qty
3477 $outdefault_vat_code = $objp->default_vat_code; // This value is the value on product when constructProductListOption is called by select_produits_list even if other field $objp-> are from table price_by_qty
3478 }
3479 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1) {
3480 $opt .= " (" . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3481 $outval .= " (" . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3482 }
3483 if (empty($hidepriceinlabel) && !empty($objp->remise_percent) && $objp->remise_percent >= 1) {
3484 $opt .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3485 $outval .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3486 }
3487
3488 // Price by customer
3489 if (empty($hidepriceinlabel) && getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
3490 if (!empty($objp->idprodcustprice)) {
3491 $found = 1;
3492
3493 if ($objp->custprice_base_type == 'HT') {
3494 $opt .= ' - ' . price($objp->custprice, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3495 $outval .= ' - ' . price($objp->custprice, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3496 } else {
3497 $opt .= ' - ' . price($objp->custprice_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3498 $outval .= ' - ' . price($objp->custprice_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3499 }
3500
3501 $outprice_ht = price($objp->custprice);
3502 $outprice_ttc = price($objp->custprice_ttc);
3503 $outpricebasetype = $objp->custprice_base_type;
3504 $outtva_tx = $objp->custtva_tx;
3505 $outdefault_vat_code = $objp->custdefault_vat_code;
3506 }
3507 }
3508
3509 // If level no defined or multiprice not found, we used the default price
3510 if (empty($hidepriceinlabel) && !$found) {
3511 if ($objp->price_base_type == 'HT') {
3512 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3513 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3514 } else {
3515 $opt .= ' - ' . price($objp->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3516 $outval .= ' - ' . price($objp->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3517 }
3518 $outprice_ht = price($objp->price);
3519 $outprice_ttc = price($objp->price_ttc);
3520 $outpricebasetype = $objp->price_base_type;
3521 $outtva_tx = $objp->tva_tx;
3522 $outdefault_vat_code = $objp->default_vat_code;
3523 }
3524
3525 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3526 if ($user->hasRight('stock', 'lire')) {
3527 $opt .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'), 0, $langs, 0, 0);
3528
3529 if ($objp->stock > 0) {
3530 $outval .= ' - <span class="product_line_stock_ok">';
3531 } elseif ($objp->stock <= 0) {
3532 $outval .= ' - <span class="product_line_stock_too_low">';
3533 }
3534 $outval .= $langs->transnoentities("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3535 $outval .= '</span>';
3536 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3537 $langs->load("stocks");
3538
3539 $tmpproduct = new Product($this->db);
3540 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3541 $tmpproduct->load_virtual_stock();
3542 $virtualstock = $tmpproduct->stock_theorique;
3543
3544 $opt .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3545
3546 $outval .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3547 if ($virtualstock > 0) {
3548 $outval .= '<span class="product_line_stock_ok">';
3549 } elseif ($virtualstock <= 0) {
3550 $outval .= '<span class="product_line_stock_too_low">';
3551 }
3552 $outval .= $virtualstock;
3553 $outval .= '</span>';
3554
3555 unset($tmpproduct);
3556 }
3557 }
3558 }
3559
3560 $parameters = array('objp' => $objp);
3561 $reshook = $hookmanager->executeHooks('constructProductListOption', $parameters); // Note that $action and $object may have been modified by hook
3562 if (empty($reshook)) {
3563 $opt .= $hookmanager->resPrint;
3564 } else {
3565 $opt = $hookmanager->resPrint;
3566 }
3567
3568 $opt .= "</option>\n";
3569 $optJson = array(
3570 'key' => $outkey,
3571 'value' => $outref,
3572 'label' => $outval,
3573 'label2' => $outlabel,
3574 'desc' => $outdesc,
3575 'type' => $outtype,
3576 'price_ht' => price2num($outprice_ht),
3577 'price_ttc' => price2num($outprice_ttc),
3578 'price_ht_locale' => price(price2num($outprice_ht)),
3579 'price_ttc_locale' => price(price2num($outprice_ttc)),
3580 'pricebasetype' => $outpricebasetype,
3581 'tva_tx' => $outtva_tx,
3582 'default_vat_code' => $outdefault_vat_code,
3583 'qty' => $outqty,
3584 'discount' => $outdiscount,
3585 'duration_value' => $outdurationvalue,
3586 'duration_unit' => $outdurationunit,
3587 'pbq' => $outpbq,
3588 'labeltrans' => $outlabel_translated,
3589 'desctrans' => $outdesc_translated,
3590 'ref_customer' => $outrefcust
3591 );
3592 }
3593
3594 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3595
3611 public function select_produits_fournisseurs($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $ajaxoptions = array(), $hidelabel = 0, $alsoproductwithnosupplierprice = 0, $morecss = '', $placeholder = '')
3612 {
3613 // phpcs:enable
3614 global $langs, $conf;
3615 global $price_level, $status, $finished;
3616
3617 if (!isset($status)) {
3618 $status = 1;
3619 }
3620
3621 $selected_input_value = '';
3622 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3623 if ($selected > 0) {
3624 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3625 $producttmpselect = new Product($this->db);
3626 $producttmpselect->fetch($selected);
3627 $selected_input_value = $producttmpselect->ref;
3628 unset($producttmpselect);
3629 }
3630
3631 // mode=2 means suppliers products
3632 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=2&status=' . $status . '&finished=' . $finished . '&alsoproductwithnosupplierprice=' . $alsoproductwithnosupplierprice;
3633 print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT'), 0, $ajaxoptions);
3634
3635 print($hidelabel ? '' : $langs->trans("RefOrLabel") . ' : ') . '<input type="text" class="'.$morecss.'" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . $placeholder . '"' : '') . '>';
3636 } else {
3637 print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', $status, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder);
3638 }
3639 }
3640
3641 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3642
3661 public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '', $showstockinlist = 0, $placeholder = '')
3662 {
3663 // phpcs:enable
3664 global $langs, $conf, $user;
3665 global $hookmanager;
3666
3667 $out = '';
3668 $outarray = array();
3669
3670 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3671
3672 $langs->load('stocks');
3673 // Units
3674 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3675 $langs->load('other');
3676 }
3677
3678 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, p.fk_product_type, p.stock, p.tva_tx as tva_tx_sale, p.default_vat_code as default_vat_code_sale,";
3679 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice, pfp.barcode";
3680 $sql .= ", pfp.multicurrency_code, pfp.multicurrency_unitprice";
3681 $sql .= ", pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.default_vat_code, pfp.fk_soc, s.nom as name";
3682 $sql .= ", pfp.supplier_reputation";
3683 // if we use supplier description of the products
3684 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3685 $sql .= ", pfp.desc_fourn as description";
3686 } else {
3687 $sql .= ", p.description";
3688 }
3689 // Units
3690 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3691 $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units";
3692 }
3693 $sql .= " FROM " . $this->db->prefix() . "product as p";
3694 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (" . getEntity('product') . ") )";
3695 if ($socid > 0) {
3696 $sql .= " AND pfp.fk_soc = " . ((int) $socid);
3697 }
3698 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3699 // Units
3700 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3701 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3702 }
3703 $sql .= " WHERE p.entity IN (" . getEntity('product') . ")";
3704 if ($statut != -1) {
3705 $sql .= " AND p.tobuy = " . ((int) $statut);
3706 }
3707 if (strval($filtertype) != '') {
3708 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3709 }
3710 if (!empty($filtre)) {
3711 $sql .= " " . $filtre;
3712 }
3713 // Add where from hooks
3714 $parameters = array();
3715 $reshook = $hookmanager->executeHooks('selectSuppliersProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3716 $sql .= $hookmanager->resPrint;
3717 // Add criteria on ref/label
3718 if ($filterkey != '') {
3719 $sql .= ' AND (';
3720 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3721 // For natural search
3722 $search_crit = explode(' ', $filterkey);
3723 $i = 0;
3724 if (count($search_crit) > 1) {
3725 $sql .= "(";
3726 }
3727 foreach ($search_crit as $crit) {
3728 if ($i > 0) {
3729 $sql .= " AND ";
3730 }
3731 $sql .= "(pfp.ref_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3732 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3733 $sql .= " OR pfp.desc_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3734 }
3735 $sql .= ")";
3736 $i++;
3737 }
3738 if (count($search_crit) > 1) {
3739 $sql .= ")";
3740 }
3741 if (isModEnabled('barcode')) {
3742 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3743 $sql .= " OR pfp.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3744 }
3745 $sql .= ')';
3746 }
3747 $sql .= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC";
3748 $sql .= $this->db->plimit($limit, 0);
3749
3750 // Build output string
3751
3752 dol_syslog(get_class($this) . "::select_produits_fournisseurs_list", LOG_DEBUG);
3753 $result = $this->db->query($sql);
3754 if ($result) {
3755 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3756 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3757
3758 $num = $this->db->num_rows($result);
3759
3760 //$out.='<select class="flat" id="select'.$htmlname.'" name="'.$htmlname.'">'; // remove select to have id same with combo and ajax
3761 $out .= '<select class="flat ' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '">';
3762 if (!$selected) {
3763 $out .= '<option value="-1" selected>' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3764 } else {
3765 $out .= '<option value="-1">' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3766 }
3767
3768 $i = 0;
3769 while ($i < $num) {
3770 $objp = $this->db->fetch_object($result);
3771
3772 if (is_null($objp->idprodfournprice)) {
3773 // There is no supplier price found, we will use the vat rate for sale
3774 $objp->tva_tx = $objp->tva_tx_sale;
3775 $objp->default_vat_code = $objp->default_vat_code_sale;
3776 }
3777
3778 $outkey = $objp->idprodfournprice; // id in table of price
3779 if (!$outkey && $alsoproductwithnosupplierprice) {
3780 $outkey = 'idprod_' . $objp->rowid; // id of product
3781 }
3782
3783 $outref = $objp->ref;
3784 $outbarcode = $objp->barcode;
3785 $outqty = 1;
3786 $outdiscount = 0;
3787 $outtype = $objp->fk_product_type;
3788 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3789 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3790
3791 // Units
3792 $outvalUnits = '';
3793 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3794 if (!empty($objp->unit_short)) {
3795 $outvalUnits .= ' - ' . $objp->unit_short;
3796 }
3797 if (!empty($objp->weight) && $objp->weight_units !== null) {
3798 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3799 $outvalUnits .= ' - ' . $unitToShow;
3800 }
3801 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3802 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3803 $outvalUnits .= ' - ' . $unitToShow;
3804 }
3805 if (!empty($objp->surface) && $objp->surface_units !== null) {
3806 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3807 $outvalUnits .= ' - ' . $unitToShow;
3808 }
3809 if (!empty($objp->volume) && $objp->volume_units !== null) {
3810 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3811 $outvalUnits .= ' - ' . $unitToShow;
3812 }
3813 if ($outdurationvalue && $outdurationunit) {
3814 $da = array(
3815 'h' => $langs->trans('Hour'),
3816 'd' => $langs->trans('Day'),
3817 'w' => $langs->trans('Week'),
3818 'm' => $langs->trans('Month'),
3819 'y' => $langs->trans('Year')
3820 );
3821 if (isset($da[$outdurationunit])) {
3822 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3823 }
3824 }
3825 }
3826
3827 $objRef = $objp->ref;
3828 if ($filterkey && $filterkey != '') {
3829 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3830 }
3831 $objRefFourn = $objp->ref_fourn;
3832 if ($filterkey && $filterkey != '') {
3833 $objRefFourn = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRefFourn, 1);
3834 }
3835 $label = $objp->label;
3836 if ($filterkey && $filterkey != '') {
3837 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3838 }
3839
3840 switch ($objp->fk_product_type) {
3842 $picto = 'product';
3843 break;
3845 $picto = 'service';
3846 break;
3847 default:
3848 $picto = '';
3849 break;
3850 }
3851
3852 if (empty($picto)) {
3853 $optlabel = '';
3854 } else {
3855 $optlabel = img_object('', $picto, 'class="paddingright classfortooltip"', 0, 0, 1);
3856 }
3857
3858 $optlabel .= $objp->ref;
3859 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3860 $optlabel .= ' <span class="opacitymedium">(' . $objp->ref_fourn . ')</span>';
3861 }
3862 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3863 $optlabel .= ' (' . $outbarcode . ')';
3864 }
3865 $optlabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3866
3867 $outvallabel = $objRef;
3868 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3869 $outvallabel .= ' (' . $objRefFourn . ')';
3870 }
3871 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3872 $outvallabel .= ' (' . $outbarcode . ')';
3873 }
3874 $outvallabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3875
3876 // Units
3877 $optlabel .= $outvalUnits;
3878 $outvallabel .= $outvalUnits;
3879
3880 if (!empty($objp->idprodfournprice)) {
3881 $outqty = $objp->quantity;
3882 $outdiscount = $objp->remise_percent;
3883 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3884 $prod_supplier = new ProductFournisseur($this->db);
3885 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3886 $prod_supplier->id = $objp->fk_product;
3887 $prod_supplier->fourn_qty = $objp->quantity;
3888 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3889 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3890
3891 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3892 $priceparser = new PriceParser($this->db);
3893 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3894 if ($price_result >= 0) {
3895 $objp->fprice = $price_result;
3896 if ($objp->quantity >= 1) {
3897 $objp->unitprice = $objp->fprice / $objp->quantity; // Replace dynamically unitprice
3898 }
3899 }
3900 }
3901 if ($objp->quantity == 1) {
3902 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3903 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/";
3904 $optlabel .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3905 $outvallabel .= $langs->transnoentities("Unit");
3906 } else {
3907 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3908 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3909 $optlabel .= ' ' . $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3910 $outvallabel .= ' ' . $langs->transnoentities("Units");
3911 }
3912
3913 if ($objp->quantity > 1) {
3914 $optlabel .= " (" . price($objp->unitprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3915 $outvallabel .= " (" . price($objp->unitprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3916 }
3917 if ($objp->remise_percent >= 1) {
3918 $optlabel .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3919 $outvallabel .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3920 }
3921 if ($objp->duration) {
3922 $optlabel .= " - " . $objp->duration;
3923 $outvallabel .= " - " . $objp->duration;
3924 }
3925 if (!$socid) {
3926 $optlabel .= " - " . dol_trunc($objp->name, 8);
3927 $outvallabel .= " - " . dol_trunc($objp->name, 8);
3928 }
3929 if ($objp->supplier_reputation) {
3930 //TODO dictionary
3931 $reputations = array('' => $langs->trans('Standard'), 'FAVORITE' => $langs->trans('Favorite'), 'NOTTHGOOD' => $langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER' => $langs->trans('DoNotOrderThisProductToThisSupplier'));
3932
3933 $optlabel .= " - " . $reputations[$objp->supplier_reputation];
3934 $outvallabel .= " - " . $reputations[$objp->supplier_reputation];
3935 }
3936 } else {
3937 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3938 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3939 }
3940
3941 if (isModEnabled('stock') && $showstockinlist && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3942 $novirtualstock = ($showstockinlist == 2);
3943
3944 if ($user->hasRight('stock', 'lire')) {
3945 $outvallabel .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3946
3947 if ($objp->stock > 0) {
3948 $optlabel .= ' - <span class="product_line_stock_ok">';
3949 } elseif ($objp->stock <= 0) {
3950 $optlabel .= ' - <span class="product_line_stock_too_low">';
3951 }
3952 $optlabel .= $langs->transnoentities("Stock") . ':' . price(price2num($objp->stock, 'MS'));
3953 $optlabel .= '</span>';
3954 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3955 $langs->load("stocks");
3956
3957 $tmpproduct = new Product($this->db);
3958 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3959 $tmpproduct->load_virtual_stock();
3960 $virtualstock = $tmpproduct->stock_theorique;
3961
3962 $outvallabel .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3963
3964 $optlabel .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3965 if ($virtualstock > 0) {
3966 $optlabel .= '<span class="product_line_stock_ok">';
3967 } elseif ($virtualstock <= 0) {
3968 $optlabel .= '<span class="product_line_stock_too_low">';
3969 }
3970 $optlabel .= $virtualstock;
3971 $optlabel .= '</span>';
3972
3973 unset($tmpproduct);
3974 }
3975 }
3976 }
3977
3978 $optstart = '<option value="' . $outkey . '"';
3979 if ($selected && $selected == $objp->idprodfournprice) {
3980 $optstart .= ' selected';
3981 }
3982 if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) {
3983 $optstart .= ' disabled';
3984 }
3985
3986 if (!empty($objp->idprodfournprice) && $objp->idprodfournprice > 0) {
3987 $optstart .= ' data-product-id="' . dol_escape_htmltag($objp->rowid) . '"';
3988 $optstart .= ' data-price-id="' . dol_escape_htmltag($objp->idprodfournprice) . '"';
3989 $optstart .= ' data-qty="' . dol_escape_htmltag($objp->quantity) . '"';
3990 $optstart .= ' data-up="' . dol_escape_htmltag(price2num($objp->unitprice)) . '"'; // the price with numeric international format
3991 $optstart .= ' data-up-locale="' . dol_escape_htmltag(price($objp->unitprice)) . '"'; // the price formatted in user language
3992 $optstart .= ' data-discount="' . dol_escape_htmltag($outdiscount) . '"';
3993 $optstart .= ' data-tvatx="' . dol_escape_htmltag(price2num($objp->tva_tx)) . '"'; // the rate with numeric international format
3994 $optstart .= ' data-tvatx-formated="' . dol_escape_htmltag(price($objp->tva_tx, 0, $langs, 1, -1, 2)) . '"'; // the rate formatted in user language
3995 $optstart .= ' data-default-vat-code="' . dol_escape_htmltag($objp->default_vat_code) . '"';
3996 $optstart .= ' data-supplier-ref="' . dol_escape_htmltag($objp->ref_fourn) . '"';
3997 if (isModEnabled('multicurrency')) {
3998 $optstart .= ' data-multicurrency-code="' . dol_escape_htmltag($objp->multicurrency_code) . '"';
3999 $optstart .= ' data-multicurrency-unitprice="' . dol_escape_htmltag(price2num($objp->multicurrency_unitprice)) . '"'; // the price with numeric international format
4000 }
4001 }
4002 $optstart .= ' data-description="' . dol_escape_htmltag($objp->description, 0, 1) . '"';
4003
4004 $outarrayentry = array(
4005 'key' => $outkey,
4006 'value' => $outref,
4007 'label' => $outvallabel,
4008 'qty' => $outqty,
4009 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
4010 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
4011 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
4012 'tva_tx_formated' => price($objp->tva_tx, 0, $langs, 1, -1, 2),
4013 'tva_tx' => price2num($objp->tva_tx),
4014 'default_vat_code' => $objp->default_vat_code,
4015 'supplier_ref' => $objp->ref_fourn,
4016 'discount' => $outdiscount,
4017 'type' => $outtype,
4018 'duration_value' => $outdurationvalue,
4019 'duration_unit' => $outdurationunit,
4020 'disabled' => empty($objp->idprodfournprice),
4021 'description' => $objp->description
4022 );
4023 if (isModEnabled('multicurrency')) {
4024 $outarrayentry['multicurrency_code'] = $objp->multicurrency_code;
4025 $outarrayentry['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
4026 }
4027
4028 $parameters = array(
4029 'objp' => &$objp,
4030 'optstart' => &$optstart,
4031 'optlabel' => &$optlabel,
4032 'outvallabel' => &$outvallabel,
4033 'outarrayentry' => &$outarrayentry
4034 );
4035 $reshook = $hookmanager->executeHooks('selectProduitsFournisseurListOption', $parameters, $this);
4036
4037
4038 // Add new entry
4039 // "key" value of json key array is used by jQuery automatically as selected value. Example: 'type' = product or service, 'price_ht' = unit price without tax
4040 // "label" value of json key array is used by jQuery automatically as text for combo box
4041 $out .= $optstart . ' data-html="' . dol_escape_htmltag($optlabel) . '">' . $optlabel . "</option>\n";
4042 $outarraypush = array(
4043 'key' => $outkey,
4044 'value' => $outref,
4045 'label' => $outvallabel,
4046 'qty' => $outqty,
4047 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
4048 'price_qty_ht_locale' => price($objp->fprice),
4049 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
4050 'price_unit_ht_locale' => price($objp->unitprice),
4051 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
4052 'tva_tx_formated' => price($objp->tva_tx),
4053 'tva_tx' => price2num($objp->tva_tx),
4054 'default_vat_code' => $objp->default_vat_code,
4055 'supplier_ref' => $objp->ref_fourn,
4056 'discount' => $outdiscount,
4057 'type' => $outtype,
4058 'duration_value' => $outdurationvalue,
4059 'duration_unit' => $outdurationunit,
4060 'disabled' => (empty($objp->idprodfournprice) ? true : false),
4061 'description' => $objp->description
4062 );
4063 if (isModEnabled('multicurrency')) {
4064 $outarraypush['multicurrency_code'] = $objp->multicurrency_code;
4065 $outarraypush['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
4066 }
4067 array_push($outarray, $outarraypush);
4068
4069 // Example of var_dump $outarray
4070 // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
4071 // ["label"]=>string(76) "ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
4072 // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false)
4073 //}
4074 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
4075 //$outval=array('label'=>'ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)');
4076 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
4077
4078 $i++;
4079 }
4080 $out .= '</select>';
4081
4082 $this->db->free($result);
4083
4084 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
4085 $out .= ajax_combobox($htmlname);
4086 } else {
4087 dol_print_error($this->db);
4088 }
4089
4090 if (empty($outputmode)) {
4091 return $out;
4092 }
4093 return $outarray;
4094 }
4095
4096 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4097
4106 public function select_product_fourn_price($productid, $htmlname = 'productfournpriceid', $selected_supplier = 0)
4107 {
4108 // phpcs:enable
4109 global $langs, $conf;
4110
4111 $langs->load('stocks');
4112
4113 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, pfp.fk_soc,";
4114 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,";
4115 $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name";
4116 $sql .= " FROM " . $this->db->prefix() . "product as p";
4117 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
4118 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
4119 $sql .= " WHERE pfp.entity IN (" . getEntity('productsupplierprice') . ")";
4120 $sql .= " AND p.tobuy = 1";
4121 $sql .= " AND s.fournisseur = 1";
4122 $sql .= " AND p.rowid = " . ((int) $productid);
4123 if (!getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED')) {
4124 $sql .= " ORDER BY s.nom, pfp.ref_fourn DESC";
4125 } else {
4126 $sql .= " ORDER BY pfp.unitprice ASC";
4127 }
4128
4129 dol_syslog(get_class($this) . "::select_product_fourn_price", LOG_DEBUG);
4130 $result = $this->db->query($sql);
4131
4132 if ($result) {
4133 $num = $this->db->num_rows($result);
4134
4135 $form = '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4136
4137 if (!$num) {
4138 $form .= '<option value="0">-- ' . $langs->trans("NoSupplierPriceDefinedForThisProduct") . ' --</option>';
4139 } else {
4140 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
4141 $form .= '<option value="0">&nbsp;</option>';
4142
4143 $i = 0;
4144 while ($i < $num) {
4145 $objp = $this->db->fetch_object($result);
4146
4147 $opt = '<option value="' . $objp->idprodfournprice . '"';
4148 //if there is only one supplier, preselect it
4149 if ($num == 1 || ($selected_supplier > 0 && $objp->fk_soc == $selected_supplier) || ($i == 0 && getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED'))) {
4150 $opt .= ' selected';
4151 }
4152 $opt .= '>' . $objp->name . ' - ' . $objp->ref_fourn . ' - ';
4153
4154 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
4155 $prod_supplier = new ProductFournisseur($this->db);
4156 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
4157 $prod_supplier->id = $productid;
4158 $prod_supplier->fourn_qty = $objp->quantity;
4159 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
4160 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
4161
4162 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
4163 $priceparser = new PriceParser($this->db);
4164 $price_result = $priceparser->parseProductSupplier($prod_supplier);
4165 if ($price_result >= 0) {
4166 $objp->fprice = $price_result;
4167 if ($objp->quantity >= 1) {
4168 $objp->unitprice = $objp->fprice / $objp->quantity;
4169 }
4170 }
4171 }
4172 if ($objp->quantity == 1) {
4173 $opt .= price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
4174 }
4175
4176 $opt .= $objp->quantity . ' ';
4177
4178 if ($objp->quantity == 1) {
4179 $opt .= $langs->trans("Unit");
4180 } else {
4181 $opt .= $langs->trans("Units");
4182 }
4183 if ($objp->quantity > 1) {
4184 $opt .= " - ";
4185 $opt .= price($objp->unitprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit");
4186 }
4187 if ($objp->duration) {
4188 $opt .= " - " . $objp->duration;
4189 }
4190 $opt .= "</option>\n";
4191
4192 $form .= $opt;
4193 $i++;
4194 }
4195 }
4196
4197 $form .= '</select>';
4198 $this->db->free($result);
4199 return $form;
4200 } else {
4201 dol_print_error($this->db);
4202 return '';
4203 }
4204 }
4205
4206
4207 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4214 {
4215 // phpcs:enable
4216 global $langs;
4217
4218 $num = count($this->cache_conditions_paiements);
4219 if ($num > 0) {
4220 return 0; // Cache already loaded
4221 }
4222
4223 dol_syslog(__METHOD__, LOG_DEBUG);
4224
4225 $sql = "SELECT rowid, code, libelle as label, deposit_percent";
4226 $sql .= " FROM " . $this->db->prefix() . 'c_payment_term';
4227 $sql .= " WHERE entity IN (" . getEntity('c_payment_term') . ")";
4228 $sql .= " AND active > 0";
4229 $sql .= " ORDER BY sortorder";
4230
4231 $resql = $this->db->query($sql);
4232 if ($resql) {
4233 $num = $this->db->num_rows($resql);
4234 $i = 0;
4235 while ($i < $num) {
4236 $obj = $this->db->fetch_object($resql);
4237
4238 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4239 $label = ($langs->trans("PaymentConditionShort" . $obj->code) != "PaymentConditionShort" . $obj->code ? $langs->trans("PaymentConditionShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4240 $this->cache_conditions_paiements[$obj->rowid]['code'] = $obj->code;
4241 $this->cache_conditions_paiements[$obj->rowid]['label'] = $label;
4242 $this->cache_conditions_paiements[$obj->rowid]['deposit_percent'] = $obj->deposit_percent;
4243 $i++;
4244 }
4245
4246 //$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1); // We use the field sortorder of table
4247
4248 return $num;
4249 } else {
4250 dol_print_error($this->db);
4251 return -1;
4252 }
4253 }
4254
4255 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4256
4262 public function load_cache_availability()
4263 {
4264 // phpcs:enable
4265 global $langs;
4266
4267 $num = count($this->cache_availability); // TODO Use $conf->cache['availability'] instead of $this->cache_availability
4268 if ($num > 0) {
4269 return 0; // Cache already loaded
4270 }
4271
4272 dol_syslog(__METHOD__, LOG_DEBUG);
4273
4274 $langs->load('propal');
4275
4276 $sql = "SELECT rowid, code, label, position";
4277 $sql .= " FROM " . $this->db->prefix() . 'c_availability';
4278 $sql .= " WHERE active > 0";
4279
4280 $resql = $this->db->query($sql);
4281 if ($resql) {
4282 $num = $this->db->num_rows($resql);
4283 $i = 0;
4284 while ($i < $num) {
4285 $obj = $this->db->fetch_object($resql);
4286
4287 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4288 $label = ($langs->trans("AvailabilityType" . $obj->code) != "AvailabilityType" . $obj->code ? $langs->trans("AvailabilityType" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4289 $this->cache_availability[$obj->rowid]['code'] = $obj->code;
4290 $this->cache_availability[$obj->rowid]['label'] = $label;
4291 $this->cache_availability[$obj->rowid]['position'] = $obj->position;
4292 $i++;
4293 }
4294
4295 $this->cache_availability = dol_sort_array($this->cache_availability, 'position', 'asc', 0, 0, 1);
4296
4297 return $num;
4298 } else {
4299 dol_print_error($this->db);
4300 return -1;
4301 }
4302 }
4303
4314 public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0, $morecss = '')
4315 {
4316 global $langs, $user;
4317
4318 $this->load_cache_availability();
4319
4320 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4321
4322 print '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4323 if ($addempty) {
4324 print '<option value="0">&nbsp;</option>';
4325 }
4326 foreach ($this->cache_availability as $id => $arrayavailability) {
4327 if ($selected == $id) {
4328 print '<option value="' . $id . '" selected>';
4329 } else {
4330 print '<option value="' . $id . '">';
4331 }
4332 print dol_escape_htmltag($arrayavailability['label']);
4333 print '</option>';
4334 }
4335 print '</select>';
4336 if ($user->admin) {
4337 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4338 }
4339 print ajax_combobox($htmlname);
4340 }
4341
4347 public function loadCacheInputReason()
4348 {
4349 global $langs;
4350
4351 $num = count($this->cache_demand_reason); // TODO Use $conf->cache['input_reason'] instead of $this->cache_demand_reason
4352 if ($num > 0) {
4353 return 0; // Cache already loaded
4354 }
4355
4356 $sql = "SELECT rowid, code, label";
4357 $sql .= " FROM " . $this->db->prefix() . 'c_input_reason';
4358 $sql .= " WHERE active > 0";
4359
4360 $resql = $this->db->query($sql);
4361 if ($resql) {
4362 $num = $this->db->num_rows($resql);
4363 $i = 0;
4364 $tmparray = array();
4365 while ($i < $num) {
4366 $obj = $this->db->fetch_object($resql);
4367
4368 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4369 $label = ($obj->label != '-' ? $obj->label : '');
4370 if ($langs->trans("DemandReasonType" . $obj->code) != "DemandReasonType" . $obj->code) {
4371 $label = $langs->trans("DemandReasonType" . $obj->code); // So translation key DemandReasonTypeSRC_XXX will work
4372 }
4373 if ($langs->trans($obj->code) != $obj->code) {
4374 $label = $langs->trans($obj->code); // So translation key SRC_XXX will work
4375 }
4376
4377 $tmparray[$obj->rowid]['id'] = $obj->rowid;
4378 $tmparray[$obj->rowid]['code'] = $obj->code;
4379 $tmparray[$obj->rowid]['label'] = $label;
4380 $i++;
4381 }
4382
4383 $this->cache_demand_reason = dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1);
4384
4385 unset($tmparray);
4386 return $num;
4387 } else {
4388 dol_print_error($this->db);
4389 return -1;
4390 }
4391 }
4392
4405 public function selectInputReason($selected = '', $htmlname = 'demandreasonid', $exclude = '', $addempty = 0, $morecss = '', $notooltip = 0)
4406 {
4407 global $langs, $user;
4408
4409 $this->loadCacheInputReason();
4410
4411 print '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4412 if ($addempty) {
4413 print '<option value="0"' . (empty($selected) ? ' selected' : '') . '>&nbsp;</option>';
4414 }
4415 foreach ($this->cache_demand_reason as $id => $arraydemandreason) {
4416 if ($arraydemandreason['code'] == $exclude) {
4417 continue;
4418 }
4419
4420 if ($selected && ($selected == $arraydemandreason['id'] || $selected == $arraydemandreason['code'])) {
4421 print '<option value="' . $arraydemandreason['id'] . '" selected>';
4422 } else {
4423 print '<option value="' . $arraydemandreason['id'] . '">';
4424 }
4425 $label = $arraydemandreason['label']; // Translation of label was already done into the ->loadCacheInputReason
4426 print $langs->trans($label);
4427 print '</option>';
4428 }
4429 print '</select>';
4430 if ($user->admin && empty($notooltip)) {
4431 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4432 }
4433 print ajax_combobox('select_' . $htmlname);
4434 }
4435
4436 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4437
4444 {
4445 // phpcs:enable
4446 global $langs;
4447
4448 $num = count($this->cache_types_paiements); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_types_paiements
4449 if ($num > 0) {
4450 return $num; // Cache already loaded
4451 }
4452
4453 dol_syslog(__METHOD__, LOG_DEBUG);
4454
4455 $this->cache_types_paiements = array();
4456
4457 $sql = "SELECT id, code, libelle as label, type, active";
4458 $sql .= " FROM " . $this->db->prefix() . "c_paiement";
4459 $sql .= " WHERE entity IN (" . getEntity('c_paiement') . ")";
4460
4461 $resql = $this->db->query($sql);
4462 if ($resql) {
4463 $num = $this->db->num_rows($resql);
4464 $i = 0;
4465 while ($i < $num) {
4466 $obj = $this->db->fetch_object($resql);
4467
4468 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4469 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4470 $this->cache_types_paiements[$obj->id]['id'] = $obj->id;
4471 $this->cache_types_paiements[$obj->id]['code'] = $obj->code;
4472 $this->cache_types_paiements[$obj->id]['label'] = $label;
4473 $this->cache_types_paiements[$obj->id]['type'] = $obj->type;
4474 $this->cache_types_paiements[$obj->id]['active'] = $obj->active;
4475 $i++;
4476 }
4477
4478 $this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1);
4479
4480 return $num;
4481 } else {
4482 dol_print_error($this->db);
4483 return -1;
4484 }
4485 }
4486
4487
4488 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4489
4508 public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1, $noprint = 0)
4509 {
4510 // phpcs:enable
4511 $out = $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, $noinfoadmin, $morecss, $deposit_percent);
4512 if (empty($noprint)) {
4513 print $out;
4514 } else {
4515 return $out;
4516 }
4517 }
4518
4519
4536 public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4537 {
4538 global $langs, $user, $conf;
4539
4540 $out = '';
4541 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4542
4544
4545 // Set default value if not already set by caller
4546 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID')) {
4547 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TERM_ID", LOG_NOTICE);
4548 $selected = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID');
4549 }
4550
4551 $out .= '<select id="' . $htmlname . '" class="flat selectpaymentterms' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4552 if ($addempty) {
4553 $out .= '<option value="0">&nbsp;</option>';
4554 }
4555
4556 $selectedDepositPercent = null;
4557
4558 foreach ($this->cache_conditions_paiements as $id => $arrayconditions) {
4559 if ($filtertype <= 0 && !empty($arrayconditions['deposit_percent'])) {
4560 continue;
4561 }
4562
4563 if ($selected == $id) {
4564 $selectedDepositPercent = $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'];
4565 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '" selected>';
4566 } else {
4567 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '">';
4568 }
4569 $label = $arrayconditions['label'];
4570
4571 if (!empty($arrayconditions['deposit_percent'])) {
4572 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'], $label);
4573 }
4574
4575 $out .= $label;
4576 $out .= '</option>';
4577 }
4578 $out .= '</select>';
4579 if ($user->admin && empty($noinfoadmin)) {
4580 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4581 }
4582 $out .= ajax_combobox($htmlname);
4583
4584 if ($deposit_percent >= 0) {
4585 $out .= ' <span id="' . $htmlname . '_deposit_percent_container"' . (empty($selectedDepositPercent) ? ' style="display: none"' : '') . '>';
4586 $out .= $langs->trans('DepositPercent') . ' : ';
4587 $out .= '<input id="' . $htmlname . '_deposit_percent" name="' . $htmlname . '_deposit_percent" class="maxwidth50" value="' . $deposit_percent . '" />';
4588 $out .= '</span>';
4589 $out .= '
4590 <script nonce="' . getNonce() . '">
4591 $(document).ready(function () {
4592 $("#' . $htmlname . '").change(function () {
4593 let $selected = $(this).find("option:selected");
4594 let depositPercent = $selected.attr("data-deposit_percent");
4595
4596 if (depositPercent.length > 0) {
4597 $("#' . $htmlname . '_deposit_percent_container").show().find("#' . $htmlname . '_deposit_percent").val(depositPercent);
4598 } else {
4599 $("#' . $htmlname . '_deposit_percent_container").hide().find("#' . $htmlname . '_deposit_percent").val(0);
4600 }
4601
4602 return true;
4603 });
4604 });
4605 </script>';
4606 }
4607
4608 return $out;
4609 }
4610
4611
4612 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4613
4630 public function select_types_paiements($selected = '', $htmlname = 'paiementtype', $filtertype = '', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '', $nooutput = 0)
4631 {
4632 // phpcs:enable
4633 global $langs, $user, $conf;
4634
4635 $out = '';
4636
4637 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
4638
4639 $filterarray = array();
4640 if ($filtertype == 'CRDT') {
4641 $filterarray = array(0, 2, 3);
4642 } elseif ($filtertype == 'DBIT') {
4643 $filterarray = array(1, 2, 3);
4644 } elseif ($filtertype != '' && $filtertype != '-1') {
4645 $filterarray = explode(',', $filtertype);
4646 }
4647
4649
4650 // Set default value if not already set by caller
4651 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID')) {
4652 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TYPE_ID", LOG_NOTICE);
4653 $selected = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID');
4654 }
4655
4656 $out .= '<select id="select' . $htmlname . '" class="flat selectpaymenttypes' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4657 if ($empty) {
4658 $out .= '<option value="">&nbsp;</option>';
4659 }
4660 foreach ($this->cache_types_paiements as $id => $arraytypes) {
4661 // If not good status
4662 if ($active >= 0 && $arraytypes['active'] != $active) {
4663 continue;
4664 }
4665
4666 // We skip of the user requested to filter on specific payment methods
4667 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
4668 continue;
4669 }
4670
4671 // We discard empty lines if showempty is on because an empty line has already been output.
4672 if ($empty && empty($arraytypes['code'])) {
4673 continue;
4674 }
4675
4676 if ($format == 0) {
4677 $out .= '<option value="' . $id . '"';
4678 } elseif ($format == 1) {
4679 $out .= '<option value="' . $arraytypes['code'] . '"';
4680 } elseif ($format == 2) {
4681 $out .= '<option value="' . $arraytypes['code'] . '"';
4682 } elseif ($format == 3) {
4683 $out .= '<option value="' . $id . '"';
4684 }
4685 // Print attribute selected or not
4686 if ($format == 1 || $format == 2) {
4687 if ($selected == $arraytypes['code']) {
4688 $out .= ' selected';
4689 }
4690 } else {
4691 if ($selected == $id) {
4692 $out .= ' selected';
4693 }
4694 }
4695 $out .= '>';
4696 $value = '';
4697 if ($format == 0) {
4698 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4699 } elseif ($format == 1) {
4700 $value = $arraytypes['code'];
4701 } elseif ($format == 2) {
4702 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4703 } elseif ($format == 3) {
4704 $value = $arraytypes['code'];
4705 }
4706 $out .= $value ? $value : '&nbsp;';
4707 $out .= '</option>';
4708 }
4709 $out .= '</select>';
4710 if ($user->admin && !$noadmininfo) {
4711 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4712 }
4713 $out .= ajax_combobox('select' . $htmlname);
4714
4715 if (empty($nooutput)) {
4716 print $out;
4717 } else {
4718 return $out;
4719 }
4720 }
4721
4722
4731 public function selectPriceBaseType($selected = '', $htmlname = 'price_base_type', $addjscombo = 0)
4732 {
4733 global $langs;
4734
4735 $return = '<select class="flat maxwidth100" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4736 $options = array(
4737 'HT' => $langs->trans("HT"),
4738 'TTC' => $langs->trans("TTC")
4739 );
4740 foreach ($options as $id => $value) {
4741 if ($selected == $id) {
4742 $return .= '<option value="' . $id . '" selected>' . $value;
4743 } else {
4744 $return .= '<option value="' . $id . '">' . $value;
4745 }
4746 $return .= '</option>';
4747 }
4748 $return .= '</select>';
4749 if ($addjscombo) {
4750 $return .= ajax_combobox('select_' . $htmlname);
4751 }
4752
4753 return $return;
4754 }
4755
4756 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4757
4764 {
4765 // phpcs:enable
4766 global $langs;
4767
4768 $num = count($this->cache_transport_mode); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_transport_mode
4769 if ($num > 0) {
4770 return $num; // Cache already loaded
4771 }
4772
4773 dol_syslog(__METHOD__, LOG_DEBUG);
4774
4775 $this->cache_transport_mode = array();
4776
4777 $sql = "SELECT rowid, code, label, active";
4778 $sql .= " FROM " . $this->db->prefix() . "c_transport_mode";
4779 $sql .= " WHERE entity IN (" . getEntity('c_transport_mode') . ")";
4780
4781 $resql = $this->db->query($sql);
4782 if ($resql) {
4783 $num = $this->db->num_rows($resql);
4784 $i = 0;
4785 while ($i < $num) {
4786 $obj = $this->db->fetch_object($resql);
4787
4788 // If traduction exist, we use it else we take the default label
4789 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4790 $this->cache_transport_mode[$obj->rowid]['rowid'] = $obj->rowid;
4791 $this->cache_transport_mode[$obj->rowid]['code'] = $obj->code;
4792 $this->cache_transport_mode[$obj->rowid]['label'] = $label;
4793 $this->cache_transport_mode[$obj->rowid]['active'] = $obj->active;
4794 $i++;
4795 }
4796
4797 $this->cache_transport_mode = dol_sort_array($this->cache_transport_mode, 'label', 'asc', 0, 0, 1);
4798
4799 return $num;
4800 } else {
4801 dol_print_error($this->db);
4802 return -1;
4803 }
4804 }
4805
4819 public function selectTransportMode($selected = '', $htmlname = 'transportmode', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '')
4820 {
4821 global $langs, $user;
4822
4823 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $format, LOG_DEBUG);
4824
4826
4827 print '<select id="select' . $htmlname . '" class="flat selectmodetransport' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4828 if ($empty) {
4829 print '<option value="">&nbsp;</option>';
4830 }
4831 foreach ($this->cache_transport_mode as $id => $arraytypes) {
4832 // If not good status
4833 if ($active >= 0 && $arraytypes['active'] != $active) {
4834 continue;
4835 }
4836
4837 // We discard empty line if showempty is on because an empty line has already been output.
4838 if ($empty && empty($arraytypes['code'])) {
4839 continue;
4840 }
4841
4842 if ($format == 0) {
4843 print '<option value="' . $id . '"';
4844 } elseif ($format == 1) {
4845 print '<option value="' . $arraytypes['code'] . '"';
4846 } elseif ($format == 2) {
4847 print '<option value="' . $arraytypes['code'] . '"';
4848 } elseif ($format == 3) {
4849 print '<option value="' . $id . '"';
4850 }
4851 // If text is selected, we compare with code, else with id
4852 if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) {
4853 print ' selected';
4854 } elseif ($selected == $id) {
4855 print ' selected';
4856 }
4857 print '>';
4858 $value = '';
4859 if ($format == 0) {
4860 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4861 } elseif ($format == 1) {
4862 $value = $arraytypes['code'];
4863 } elseif ($format == 2) {
4864 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4865 } elseif ($format == 3) {
4866 $value = $arraytypes['code'];
4867 }
4868 print $value ? $value : '&nbsp;';
4869 print '</option>';
4870 }
4871 print '</select>';
4872 if ($user->admin && !$noadmininfo) {
4873 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4874 }
4875 }
4876
4889 public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '', $noinfoadmin = 0, $morecss = '')
4890 {
4891 global $langs, $user;
4892
4893 $langs->load("admin");
4894 $langs->load("deliveries");
4895
4896 $sql = "SELECT rowid, code, libelle as label";
4897 $sql .= " FROM " . $this->db->prefix() . "c_shipment_mode";
4898 $sql .= " WHERE active > 0";
4899 if ($filtre) {
4900 $sql .= " AND " . $filtre;
4901 }
4902 $sql .= " ORDER BY libelle ASC";
4903
4904 dol_syslog(get_class($this) . "::selectShippingMode", LOG_DEBUG);
4905 $result = $this->db->query($sql);
4906 if ($result) {
4907 $num = $this->db->num_rows($result);
4908 $i = 0;
4909 if ($num) {
4910 print '<select id="select' . $htmlname . '" class="flat selectshippingmethod' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4911 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4912 print '<option value="-1">&nbsp;</option>';
4913 }
4914 while ($i < $num) {
4915 $obj = $this->db->fetch_object($result);
4916 if ($selected == $obj->rowid) {
4917 print '<option value="' . $obj->rowid . '" selected>';
4918 } else {
4919 print '<option value="' . $obj->rowid . '">';
4920 }
4921 print ($langs->trans("SendingMethod" . strtoupper($obj->code)) != "SendingMethod" . strtoupper($obj->code)) ? $langs->trans("SendingMethod" . strtoupper($obj->code)) : $obj->label;
4922 print '</option>';
4923 $i++;
4924 }
4925 print "</select>";
4926 if ($user->admin && empty($noinfoadmin)) {
4927 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4928 }
4929
4930 print ajax_combobox('select' . $htmlname);
4931 } else {
4932 print $langs->trans("NoShippingMethodDefined");
4933 }
4934 } else {
4935 dol_print_error($this->db);
4936 }
4937 }
4938
4948 public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0)
4949 {
4950 global $langs;
4951
4952 $langs->load("deliveries");
4953
4954 if ($htmlname != "none") {
4955 print '<form method="POST" action="' . $page . '">';
4956 print '<input type="hidden" name="action" value="setshippingmethod">';
4957 print '<input type="hidden" name="token" value="' . newToken() . '">';
4958 $this->selectShippingMethod($selected, $htmlname, '', $addempty);
4959 print '<input type="submit" class="button valignmiddle" value="' . $langs->trans("Modify") . '">';
4960 print '</form>';
4961 } else {
4962 if ($selected) {
4963 $code = $langs->getLabelFromKey($this->db, $selected, 'c_shipment_mode', 'rowid', 'code');
4964 print $langs->trans("SendingMethod" . strtoupper($code));
4965 } else {
4966 print "&nbsp;";
4967 }
4968 }
4969 }
4970
4979 public function selectSituationInvoices($selected = '', $socid = 0)
4980 {
4981 global $langs;
4982
4983 $langs->load('bills');
4984
4985 $opt = '<option value="" selected></option>';
4986 $sql = "SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc";
4987 $sql .= ' FROM ' . $this->db->prefix() . 'facture';
4988 $sql .= ' WHERE entity IN (' . getEntity('invoice') . ')';
4989 $sql .= ' AND situation_counter >= 1';
4990 $sql .= ' AND fk_soc = ' . (int) $socid;
4991 $sql .= ' AND type <> 2';
4992 $sql .= ' ORDER by situation_cycle_ref, situation_counter desc';
4993 $resql = $this->db->query($sql);
4994
4995 if ($resql && $this->db->num_rows($resql) > 0) {
4996 // Last seen cycle
4997 $ref = 0;
4998 while ($obj = $this->db->fetch_object($resql)) {
4999 //Same cycle ?
5000 if ($obj->situation_cycle_ref != $ref) {
5001 // Just seen this cycle
5002 $ref = $obj->situation_cycle_ref;
5003 //not final ?
5004 if ($obj->situation_final != 1) {
5005 //Not prov?
5006 if (substr($obj->ref, 1, 4) != 'PROV') {
5007 if ($selected == $obj->rowid) {
5008 $opt .= '<option value="' . $obj->rowid . '" selected>' . $obj->ref . '</option>';
5009 } else {
5010 $opt .= '<option value="' . $obj->rowid . '">' . $obj->ref . '</option>';
5011 }
5012 }
5013 }
5014 }
5015 }
5016 } else {
5017 dol_syslog("Error sql=" . $sql . ", error=" . $this->error, LOG_ERR);
5018 }
5019 if ($opt == '<option value ="" selected></option>') {
5020 $opt = '<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>';
5021 }
5022 return $opt;
5023 }
5024
5034 public function selectUnits($selected = '', $htmlname = 'units', $showempty = 0, $unit_type = '')
5035 {
5036 global $langs;
5037
5038 $langs->load('products');
5039
5040 $return = '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
5041
5042 $sql = "SELECT rowid, label, code FROM " . $this->db->prefix() . "c_units";
5043 $sql .= ' WHERE active > 0';
5044 if (!empty($unit_type)) {
5045 $sql .= " AND unit_type = '" . $this->db->escape($unit_type) . "'";
5046 }
5047 $sql .= " ORDER BY sortorder";
5048
5049 $resql = $this->db->query($sql);
5050 if ($resql && $this->db->num_rows($resql) > 0) {
5051 if ($showempty) {
5052 $return .= '<option value="none"></option>';
5053 }
5054
5055 while ($res = $this->db->fetch_object($resql)) {
5056 $unitLabel = $res->label;
5057 if (!empty($langs->tab_translate['unit' . $res->code])) { // check if Translation is available before
5058 $unitLabel = $langs->trans('unit' . $res->code) != $res->label ? $langs->trans('unit' . $res->code) : $res->label;
5059 }
5060
5061 if ($selected == $res->rowid) {
5062 $return .= '<option value="' . $res->rowid . '" selected>' . $unitLabel . '</option>';
5063 } else {
5064 $return .= '<option value="' . $res->rowid . '">' . $unitLabel . '</option>';
5065 }
5066 }
5067 $return .= '</select>';
5068 }
5069 return $return;
5070 }
5071
5072 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5073
5088 public function select_comptes($selected = '', $htmlname = 'accountid', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '', $showcurrency = 0, $morecss = '', $nooutput = 0)
5089 {
5090 // phpcs:enable
5091 global $langs;
5092
5093 $out = '';
5094
5095 $langs->load("admin");
5096 $num = 0;
5097
5098 $sql = "SELECT rowid, label, bank, clos as status, currency_code";
5099 $sql .= " FROM " . $this->db->prefix() . "bank_account";
5100 $sql .= " WHERE entity IN (" . getEntity('bank_account') . ")";
5101 if ($status != 2) {
5102 $sql .= " AND clos = " . (int) $status;
5103 }
5104 if ($filtre) { // TODO Support USF
5105 $sql .= " AND " . $filtre;
5106 }
5107 $sql .= " ORDER BY label";
5108
5109 dol_syslog(get_class($this) . "::select_comptes", LOG_DEBUG);
5110 $result = $this->db->query($sql);
5111 if ($result) {
5112 $num = $this->db->num_rows($result);
5113 $i = 0;
5114 if ($num) {
5115 $out .= '<select id="select' . $htmlname . '" class="flat selectbankaccount' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5116
5117 if (!empty($useempty) && !is_numeric($useempty)) {
5118 $out .= '<option value="-1">'.$langs->trans($useempty).'</option>';
5119 } elseif ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5120 $out .= '<option value="-1">&nbsp;</option>';
5121 }
5122
5123 while ($i < $num) {
5124 $obj = $this->db->fetch_object($result);
5125 if ($selected == $obj->rowid || ($useempty == 2 && $num == 1 && empty($selected))) {
5126 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '" selected>';
5127 } else {
5128 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '">';
5129 }
5130 $out .= trim($obj->label);
5131 if ($showcurrency) {
5132 $out .= ' (' . $obj->currency_code . ')';
5133 }
5134 if ($status == 2 && $obj->status == 1) {
5135 $out .= ' (' . $langs->trans("Closed") . ')';
5136 }
5137 $out .= '</option>';
5138 $i++;
5139 }
5140 $out .= "</select>";
5141 $out .= ajax_combobox('select' . $htmlname);
5142 } else {
5143 if ($status == 0) {
5144 $out .= '<span class="opacitymedium">' . $langs->trans("NoActiveBankAccountDefined") . '</span>';
5145 } else {
5146 $out .= '<span class="opacitymedium">' . $langs->trans("NoBankAccountFound") . '</span>';
5147 }
5148 }
5149 } else {
5150 dol_print_error($this->db);
5151 }
5152
5153 // Output or return
5154 if (empty($nooutput)) {
5155 print $out;
5156 } else {
5157 return $out;
5158 }
5159
5160 return $num;
5161 }
5162
5174 public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '')
5175 {
5176 global $langs;
5177
5178 $langs->load("admin");
5179 $num = 0;
5180
5181 $sql = "SELECT rowid, name, fk_country, status, entity";
5182 $sql .= " FROM " . $this->db->prefix() . "establishment";
5183 $sql .= " WHERE 1=1";
5184 if ($status != 2) {
5185 $sql .= " AND status = " . (int) $status;
5186 }
5187 if ($filtre) { // TODO Support USF
5188 $sql .= " AND " . $filtre;
5189 }
5190 $sql .= " ORDER BY name";
5191
5192 dol_syslog(get_class($this) . "::select_establishment", LOG_DEBUG);
5193 $result = $this->db->query($sql);
5194 if ($result) {
5195 $num = $this->db->num_rows($result);
5196 $i = 0;
5197 if ($num) {
5198 print '<select id="select' . $htmlname . '" class="flat selectestablishment" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5199 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5200 print '<option value="-1">&nbsp;</option>';
5201 }
5202
5203 while ($i < $num) {
5204 $obj = $this->db->fetch_object($result);
5205 if ($selected == $obj->rowid) {
5206 print '<option value="' . $obj->rowid . '" selected>';
5207 } else {
5208 print '<option value="' . $obj->rowid . '">';
5209 }
5210 print trim($obj->name);
5211 if ($status == 2 && $obj->status == 1) {
5212 print ' (' . $langs->trans("Closed") . ')';
5213 }
5214 print '</option>';
5215 $i++;
5216 }
5217 print "</select>";
5218 } else {
5219 if ($status == 0) {
5220 print '<span class="opacitymedium">' . $langs->trans("NoActiveEstablishmentDefined") . '</span>';
5221 } else {
5222 print '<span class="opacitymedium">' . $langs->trans("NoEstablishmentFound") . '</span>';
5223 }
5224 }
5225
5226 return $num;
5227 } else {
5228 dol_print_error($this->db);
5229 return -1;
5230 }
5231 }
5232
5242 public function formSelectAccount($page, $selected = '', $htmlname = 'fk_account', $addempty = 0)
5243 {
5244 global $langs;
5245 if ($htmlname != "none") {
5246 print '<form method="POST" action="' . $page . '">';
5247 print '<input type="hidden" name="action" value="setbankaccount">';
5248 print '<input type="hidden" name="token" value="' . newToken() . '">';
5249 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
5250 $nbaccountfound = $this->select_comptes($selected, $htmlname, 0, '', $addempty);
5251 if ($nbaccountfound > 0) {
5252 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5253 }
5254 print '</form>';
5255 } else {
5256 $langs->load('banks');
5257
5258 if ($selected) {
5259 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
5260 $bankstatic = new Account($this->db);
5261 $result = $bankstatic->fetch($selected);
5262 if ($result) {
5263 print $bankstatic->getNomUrl(1);
5264 }
5265 } else {
5266 print "&nbsp;";
5267 }
5268 }
5269 }
5270
5271 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5272
5292 public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $fromid = 0, $outputmode = 0, $include = 0, $morecss = '', $useempty = 1)
5293 {
5294 // phpcs:enable
5295 global $conf, $langs;
5296 $langs->load("categories");
5297
5298 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
5299
5300 // For backward compatibility
5301 if (is_numeric($type)) {
5302 dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING);
5303 }
5304
5305 if ($type === Categorie::TYPE_BANK_LINE) {
5306 // TODO Move this into common category feature
5307 $cate_arbo = array();
5308 $sql = "SELECT c.label, c.rowid";
5309 $sql .= " FROM " . $this->db->prefix() . "bank_categ as c";
5310 $sql .= " WHERE entity = " . $conf->entity;
5311 $sql .= " ORDER BY c.label";
5312 $result = $this->db->query($sql);
5313 if ($result) {
5314 $num = $this->db->num_rows($result);
5315 $i = 0;
5316 while ($i < $num) {
5317 $objp = $this->db->fetch_object($result);
5318 if ($objp) {
5319 $cate_arbo[$objp->rowid] = array('id' => $objp->rowid, 'fulllabel' => $objp->label, 'color' => '', 'picto' => 'category');
5320 }
5321 $i++;
5322 }
5323 $this->db->free($result);
5324 } else {
5325 dol_print_error($this->db);
5326 }
5327 } else {
5328 $cat = new Categorie($this->db);
5329 $cate_arbo = $cat->get_full_arbo($type, $fromid, $include);
5330 }
5331
5332 $outarray = array();
5333 $outarrayrichhtml = array();
5334
5335
5336 $output = '<select class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
5337 if (is_array($cate_arbo)) {
5338 $num = count($cate_arbo);
5339
5340 if (!$num) {
5341 $output .= '<option value="-1" disabled>' . $langs->trans("NoCategoriesDefined") . '</option>';
5342 } else {
5343 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5344 $output .= '<option value="-1">&nbsp;</option>';
5345 }
5346 foreach ($cate_arbo as $key => $value) {
5347 if ($cate_arbo[$key]['id'] == $selected || ($selected === 'auto' && count($cate_arbo) == 1)) {
5348 $add = 'selected ';
5349 } else {
5350 $add = '';
5351 }
5352
5353 $labeltoshow = img_picto('', 'category', 'class="pictofixedwidth" style="color: #' . $cate_arbo[$key]['color'] . '"');
5354 $labeltoshow .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5355
5356 $outarray[$cate_arbo[$key]['id']] = $cate_arbo[$key]['fulllabel'];
5357
5358 $outarrayrichhtml[$cate_arbo[$key]['id']] = $labeltoshow;
5359
5360 $output .= '<option ' . $add . 'value="' . $cate_arbo[$key]['id'] . '"';
5361 $output .= ' data-html="' . dol_escape_htmltag($labeltoshow) . '"';
5362 $output .= '>';
5363 $output .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5364 $output .= '</option>';
5365
5366 $cate_arbo[$key]['data-html'] = $labeltoshow;
5367 }
5368 }
5369 }
5370 $output .= '</select>';
5371 $output .= "\n";
5372
5373 if ($outputmode == 2) {
5374 // TODO: handle error when $cate_arbo is not an array
5375 return $cate_arbo;
5376 } elseif ($outputmode == 1) {
5377 return $outarray;
5378 } elseif ($outputmode == 3) {
5379 return $outarrayrichhtml;
5380 }
5381 return $output;
5382 }
5383
5384 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5385
5402 public function form_confirm($page, $title, $question, $action, $formquestion = array(), $selectedchoice = "", $useajax = 0, $height = 170, $width = 500)
5403 {
5404 // phpcs:enable
5405 dol_syslog(__METHOD__ . ': using form_confirm is deprecated. Use formconfim instead.', LOG_WARNING);
5406 print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width);
5407 }
5408
5436 public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No')
5437 {
5438 global $langs, $conf;
5439
5440 $more = '<!-- formconfirm - before call, page=' . dol_escape_htmltag($page) . ' -->';
5441 $formconfirm = '';
5442 $inputok = array();
5443 $inputko = array();
5444
5445 // Clean parameters
5446 $newselectedchoice = empty($selectedchoice) ? "no" : $selectedchoice;
5447 if ($conf->browser->layout == 'phone') {
5448 $width = '95%';
5449 }
5450
5451 // Set height automatically if not defined
5452 if (empty($height)) {
5453 $height = 220;
5454 if (is_array($formquestion) && count($formquestion) > 2) {
5455 $height += ((count($formquestion) - 2) * 24);
5456 }
5457 }
5458
5459 if (is_array($formquestion) && !empty($formquestion)) {
5460 // First add hidden fields and value
5461 foreach ($formquestion as $key => $input) {
5462 if (is_array($input) && !empty($input)) {
5463 if ($input['type'] == 'hidden') {
5464 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5465 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5466
5467 $more .= '<input type="hidden" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '" value="' . dol_escape_htmltag($input['value']) . '" class="' . $morecss . '"' . $moreattr . '>' . "\n";
5468 }
5469 }
5470 }
5471
5472 // Now add questions
5473 $moreonecolumn = '';
5474 $more .= '<div class="tagtable paddingtopbottomonly centpercent noborderspacing">' . "\n";
5475 foreach ($formquestion as $key => $input) {
5476 if (is_array($input) && !empty($input)) {
5477 $size = (!empty($input['size']) ? ' size="' . $input['size'] . '"' : ''); // deprecated. Use morecss instead.
5478 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5479 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5480
5481 if ($input['type'] == 'text') {
5482 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div><div class="tagtd"><input type="text" class="flat' . $morecss . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $size . ' value="' . (empty($input['value']) ? '' : $input['value']) . '"' . $moreattr . ' /></div></div>' . "\n";
5483 } elseif ($input['type'] == 'password') {
5484 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div><div class="tagtd"><input type="password" class="flat' . $morecss . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $size . ' value="' . (empty($input['value']) ? '' : $input['value']) . '"' . $moreattr . ' /></div></div>' . "\n";
5485 } elseif ($input['type'] == 'textarea') {
5486 /*$more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">'.$input['label'].'</div><div class="tagtd">';
5487 $more .= '<textarea name="'.$input['name'].'" class="'.$morecss.'"'.$moreattr.'>';
5488 $more .= $input['value'];
5489 $more .= '</textarea>';
5490 $more .= '</div></div>'."\n";*/
5491 $moreonecolumn .= '<div class="margintoponly">';
5492 $moreonecolumn .= $input['label'] . '<br>';
5493 $moreonecolumn .= '<textarea name="' . dol_escape_htmltag($input['name']) . '" id="' . dol_escape_htmltag($input['name']) . '" class="' . $morecss . '"' . $moreattr . '>';
5494 $moreonecolumn .= $input['value'];
5495 $moreonecolumn .= '</textarea>';
5496 $moreonecolumn .= '</div>';
5497 } elseif (in_array($input['type'], ['select', 'multiselect'])) {
5498 if (empty($morecss)) {
5499 $morecss = 'minwidth100';
5500 }
5501
5502 $show_empty = isset($input['select_show_empty']) ? $input['select_show_empty'] : 1;
5503 $key_in_label = isset($input['select_key_in_label']) ? $input['select_key_in_label'] : 0;
5504 $value_as_key = isset($input['select_value_as_key']) ? $input['select_value_as_key'] : 0;
5505 $translate = isset($input['select_translate']) ? $input['select_translate'] : 0;
5506 $maxlen = isset($input['select_maxlen']) ? $input['select_maxlen'] : 0;
5507 $disabled = isset($input['select_disabled']) ? $input['select_disabled'] : 0;
5508 $sort = isset($input['select_sort']) ? $input['select_sort'] : '';
5509
5510 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">';
5511 if (!empty($input['label'])) {
5512 $more .= $input['label'] . '</div><div class="tagtd left">';
5513 }
5514 if ($input['type'] == 'select') {
5515 $more .= $this->selectarray($input['name'], $input['values'], isset($input['default']) ? $input['default'] : '-1', $show_empty, $key_in_label, $value_as_key, $moreattr, $translate, $maxlen, $disabled, $sort, $morecss);
5516 } else {
5517 $more .= $this->multiselectarray($input['name'], $input['values'], is_array($input['default']) ? $input['default'] : [$input['default']], $key_in_label, $value_as_key, $morecss, $translate, $maxlen, $moreattr);
5518 }
5519 $more .= '</div></div>' . "\n";
5520 } elseif ($input['type'] == 'checkbox') {
5521 $more .= '<div class="tagtr">';
5522 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '"><label for="' . dol_escape_htmltag($input['name']) . '">' . $input['label'] . '</label></div><div class="tagtd">';
5523 $more .= '<input type="checkbox" class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $moreattr;
5524 if (!is_bool($input['value']) && $input['value'] != 'false' && $input['value'] != '0' && $input['value'] != '') {
5525 $more .= ' checked';
5526 }
5527 if (is_bool($input['value']) && $input['value']) {
5528 $more .= ' checked';
5529 }
5530 if (isset($input['disabled'])) {
5531 $more .= ' disabled';
5532 }
5533 $more .= ' /></div>';
5534 $more .= '</div>' . "\n";
5535 } elseif ($input['type'] == 'radio') {
5536 $i = 0;
5537 foreach ($input['values'] as $selkey => $selval) {
5538 $more .= '<div class="tagtr">';
5539 if (isset($input['label'])) {
5540 if ($i == 0) {
5541 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? ' tdtop' : (' tdtop ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5542 } else {
5543 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' "' . $input['tdclass'])) . '">&nbsp;</div>';
5544 }
5545 }
5546 $more .= '<div class="tagtd' . ($i == 0 ? ' tdtop' : '') . '"><input type="radio" class="flat' . $morecss . '" id="' . dol_escape_htmltag($input['name'] . $selkey) . '" name="' . dol_escape_htmltag($input['name']) . '" value="' . $selkey . '"' . $moreattr;
5547 if (!empty($input['disabled'])) {
5548 $more .= ' disabled';
5549 }
5550 if (isset($input['default']) && $input['default'] === $selkey) {
5551 $more .= ' checked="checked"';
5552 }
5553 $more .= ' /> ';
5554 $more .= '<label for="' . dol_escape_htmltag($input['name'] . $selkey) . '" class="valignmiddle">' . $selval . '</label>';
5555 $more .= '</div></div>' . "\n";
5556 $i++;
5557 }
5558 } elseif ($input['type'] == 'date' || $input['type'] == 'datetime') {
5559 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5560 $more .= '<div class="tagtd">';
5561 $addnowlink = (empty($input['datenow']) ? 0 : 1);
5562 $h = $m = 0;
5563 if ($input['type'] == 'datetime') {
5564 $h = isset($input['hours']) ? $input['hours'] : 1;
5565 $m = isset($input['minutes']) ? $input['minutes'] : 1;
5566 }
5567 $more .= $this->selectDate(isset($input['value']) ? $input['value'] : -1, $input['name'], $h, $m, 0, '', 1, $addnowlink);
5568 $more .= '</div></div>'."\n";
5569 $formquestion[] = array('name' => $input['name'].'day');
5570 $formquestion[] = array('name' => $input['name'].'month');
5571 $formquestion[] = array('name' => $input['name'].'year');
5572 $formquestion[] = array('name' => $input['name'].'hour');
5573 $formquestion[] = array('name' => $input['name'].'min');
5574 } elseif ($input['type'] == 'other') { // can be 1 column or 2 depending if label is set or not
5575 $more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">';
5576 if (!empty($input['label'])) {
5577 $more .= $input['label'] . '</div><div class="tagtd">';
5578 }
5579 $more .= $input['value'];
5580 $more .= '</div></div>' . "\n";
5581 } elseif ($input['type'] == 'onecolumn') {
5582 $moreonecolumn .= '<div class="margintoponly">';
5583 $moreonecolumn .= $input['value'];
5584 $moreonecolumn .= '</div>' . "\n";
5585 } elseif ($input['type'] == 'hidden') {
5586 // Do nothing more, already added by a previous loop
5587 } elseif ($input['type'] == 'separator') {
5588 $more .= '<br>';
5589 } else {
5590 $more .= 'Error type ' . $input['type'] . ' for the confirm box is not a supported type';
5591 }
5592 }
5593 }
5594 $more .= '</div>' . "\n";
5595 $more .= $moreonecolumn;
5596 }
5597
5598 // JQUERY method dialog is broken with smartphone, we use standard HTML.
5599 // Note: When using dol_use_jmobile or no js, you must also check code for button use a GET url with action=xxx and check that you also output the confirm code when action=xxx
5600 // See page product/card.php for example
5601 if (!empty($conf->dol_use_jmobile)) {
5602 $useajax = 0;
5603 }
5604 if (empty($conf->use_javascript_ajax)) {
5605 $useajax = 0;
5606 }
5607
5608 if ($useajax) {
5609 $autoOpen = true;
5610 $dialogconfirm = 'dialog-confirm';
5611 $button = '';
5612 if (!is_numeric($useajax)) {
5613 $button = $useajax;
5614 $useajax = 1;
5615 $autoOpen = false;
5616 $dialogconfirm .= '-' . $button;
5617 }
5618 $pageyes = $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=yes';
5619 $pageno = ($useajax == 2 ? $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=no' : '');
5620
5621 // Add input fields into list of fields to read during submit (inputok and inputko)
5622 if (is_array($formquestion)) {
5623 foreach ($formquestion as $key => $input) {
5624 //print "xx ".$key." rr ".is_array($input)."<br>\n";
5625 // Add name of fields to propagate with the GET when submitting the form with button OK.
5626 if (is_array($input) && isset($input['name'])) {
5627 if (strpos($input['name'], ',') > 0) {
5628 $inputok = array_merge($inputok, explode(',', $input['name']));
5629 } else {
5630 array_push($inputok, $input['name']);
5631 }
5632 }
5633 // Add name of fields to propagate with the GET when submitting the form with button KO.
5634 // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset
5635 if (is_array($input) && isset($input['inputko']) && $input['inputko'] == 1 && isset($input['name'])) {
5636 array_push($inputko, $input['name']);
5637 }
5638 }
5639 }
5640
5641 // Show JQuery confirm box.
5642 $formconfirm .= '<div id="' . $dialogconfirm . '" title="' . dol_escape_htmltag($title) . '" style="display: none;">';
5643 if (is_array($formquestion) && array_key_exists('text', $formquestion) && !empty($formquestion['text'])) {
5644 $formconfirm .= '<div class="confirmtext">' . $formquestion['text'] . '</div>' . "\n";
5645 }
5646 if (!empty($more)) {
5647 $formconfirm .= '<div class="confirmquestions">' . $more . '</div>' . "\n";
5648 }
5649 $formconfirm .= ($question ? '<div class="confirmmessage">' . img_help(0, '') . ' ' . $question . '</div>' : '');
5650 $formconfirm .= '</div>' . "\n";
5651
5652 $formconfirm .= "\n<!-- begin code of popup for formconfirm page=" . $page . " -->\n";
5653 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5654 $formconfirm .= "/* Code for the jQuery('#dialogforpopup').dialog() */\n";
5655 $formconfirm .= 'jQuery(document).ready(function() {
5656 $(function() {
5657 $( "#' . $dialogconfirm . '" ).dialog(
5658 {
5659 autoOpen: ' . ($autoOpen ? "true" : "false") . ',';
5660 if ($newselectedchoice == 'no') {
5661 $formconfirm .= '
5662 open: function() {
5663 $(this).parent().find("button.ui-button:eq(2)").focus();
5664 },';
5665 }
5666
5667 $jsforcursor = '';
5668 if ($useajax == 1) {
5669 $jsforcursor = '// The call to urljump can be slow, so we set the wait cursor' . "\n";
5670 $jsforcursor .= 'jQuery("html,body,#id-container").addClass("cursorwait");' . "\n";
5671 }
5672
5673 $postconfirmas = 'GET';
5674
5675 $formconfirm .= '
5676 resizable: false,
5677 height: "' . $height . '",
5678 width: "' . $width . '",
5679 modal: true,
5680 closeOnEscape: false,
5681 buttons: {
5682 "' . dol_escape_js($langs->transnoentities($labelbuttonyes)) . '": function() {
5683 var options = "token=' . urlencode(newToken()) . '";
5684 var inputok = ' . json_encode($inputok) . '; /* List of fields into form */
5685 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5686 var pageyes = "' . dol_escape_js(!empty($pageyes) ? $pageyes : '') . '";
5687
5688 if (inputok.length > 0) {
5689 $.each(inputok, function(i, inputname) {
5690 var more = "";
5691 var inputvalue;
5692 if ($("input[name=\'" + inputname + "\']").attr("type") == "radio") {
5693 inputvalue = $("input[name=\'" + inputname + "\']:checked").val();
5694 } else {
5695 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5696 inputvalue = $("#" + inputname + more).val();
5697 }
5698 if (typeof inputvalue == "undefined") { inputvalue=""; }
5699 console.log("formconfirm check inputname="+inputname+" inputvalue="+inputvalue);
5700 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5701 });
5702 }
5703 var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "&") + options;
5704 if (pageyes.length > 0) {';
5705 if ($postconfirmas == 'GET') {
5706 $formconfirm .= 'location.href = urljump;';
5707 } else {
5708 $formconfirm .= $jsforcursor;
5709 $formconfirm .= 'var post = $.post(
5710 pageyes,
5711 options,
5712 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5713 );';
5714 }
5715 $formconfirm .= '
5716 console.log("after post ok");
5717 }
5718 $(this).dialog("close");
5719 },
5720 "' . dol_escape_js($langs->transnoentities($labelbuttonno)) . '": function() {
5721 var options = "token=' . urlencode(newToken()) . '";
5722 var inputko = ' . json_encode($inputko) . '; /* List of fields into form */
5723 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5724 var pageno="' . dol_escape_js(!empty($pageno) ? $pageno : '') . '";
5725 if (inputko.length > 0) {
5726 $.each(inputko, function(i, inputname) {
5727 var more = "";
5728 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5729 var inputvalue = $("#" + inputname + more).val();
5730 if (typeof inputvalue == "undefined") { inputvalue=""; }
5731 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5732 });
5733 }
5734 var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "&") + options;
5735 //alert(urljump);
5736 if (pageno.length > 0) {';
5737 if ($postconfirmas == 'GET') {
5738 $formconfirm .= 'location.href = urljump;';
5739 } else {
5740 $formconfirm .= $jsforcursor;
5741 $formconfirm .= 'var post = $.post(
5742 pageno,
5743 options,
5744 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5745 );';
5746 }
5747 $formconfirm .= '
5748 console.log("after post ko");
5749 }
5750 $(this).dialog("close");
5751 }
5752 }
5753 }
5754 );
5755
5756 var button = "' . $button . '";
5757 if (button.length > 0) {
5758 $( "#" + button ).click(function() {
5759 $("#' . $dialogconfirm . '").dialog("open");
5760 });
5761 }
5762 });
5763 });
5764 </script>';
5765 $formconfirm .= "<!-- end ajax formconfirm -->\n";
5766 } else {
5767 $formconfirm .= "\n<!-- begin formconfirm page=" . dol_escape_htmltag($page) . " -->\n";
5768
5769 if (empty($disableformtag)) {
5770 $formconfirm .= '<form method="POST" action="' . $page . '" class="notoptoleftroright">' . "\n";
5771 }
5772
5773 $formconfirm .= '<input type="hidden" name="action" value="' . $action . '">' . "\n";
5774 $formconfirm .= '<input type="hidden" name="token" value="' . newToken() . '">' . "\n";
5775
5776 $formconfirm .= '<table class="valid centpercent">' . "\n";
5777
5778 // Line title
5779 $formconfirm .= '<tr class="validtitre"><td class="validtitre" colspan="2">';
5780 $formconfirm .= img_picto('', 'pictoconfirm') . ' ' . $title;
5781 $formconfirm .= '</td></tr>' . "\n";
5782
5783 // Line text
5784 if (is_array($formquestion) && array_key_exists('text', $formquestion) && !empty($formquestion['text'])) {
5785 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . $formquestion['text'] . '</td></tr>' . "\n";
5786 }
5787
5788 // Line form fields
5789 if ($more) {
5790 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . "\n";
5791 $formconfirm .= $more;
5792 $formconfirm .= '</td></tr>' . "\n";
5793 }
5794
5795 // Line with question
5796 $formconfirm .= '<tr class="valid">';
5797 $formconfirm .= '<td class="valid">' . $question . '</td>';
5798 $formconfirm .= '<td class="valid center">';
5799 $formconfirm .= $this->selectyesno("confirm", $newselectedchoice, 0, false, 0, 0, 'marginleftonly marginrightonly', $labelbuttonyes, $labelbuttonno);
5800 $formconfirm .= '<input class="button valignmiddle confirmvalidatebutton small" type="submit" value="' . $langs->trans("Validate") . '">';
5801 $formconfirm .= '</td>';
5802 $formconfirm .= '</tr>' . "\n";
5803
5804 $formconfirm .= '</table>' . "\n";
5805
5806 if (empty($disableformtag)) {
5807 $formconfirm .= "</form>\n";
5808 }
5809 $formconfirm .= '<br>';
5810
5811 if (!empty($conf->use_javascript_ajax)) {
5812 $formconfirm .= '<!-- code to disable button to avoid double clic -->';
5813 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5814 $formconfirm .= '
5815 $(document).ready(function () {
5816 $(".confirmvalidatebutton").on("click", function() {
5817 console.log("We click on button confirmvalidatebutton");
5818 $(this).attr("disabled", "disabled");
5819 setTimeout(\'$(".confirmvalidatebutton").removeAttr("disabled")\', 3000);
5820 //console.log($(this).closest("form"));
5821 $(this).closest("form").submit();
5822 });
5823 });
5824 ';
5825 $formconfirm .= '</script>' . "\n";
5826 }
5827
5828 $formconfirm .= "<!-- end formconfirm -->\n";
5829 }
5830
5831 return $formconfirm;
5832 }
5833
5834
5835 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5836
5852 public function form_project($page, $socid, $selected = '', $htmlname = 'projectid', $discard_closed = 0, $maxlength = 20, $forcefocus = 0, $nooutput = 0, $textifnoproject = '', $morecss = '')
5853 {
5854 // phpcs:enable
5855 global $langs;
5856
5857 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
5858 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
5859
5860 $out = '';
5861
5862 $formproject = new FormProjets($this->db);
5863
5864 $langs->load("project");
5865 if ($htmlname != "none") {
5866 $out .= '<form method="post" action="' . $page . '">';
5867 $out .= '<input type="hidden" name="action" value="classin">';
5868 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5869 $out .= $formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1, 0, $morecss);
5870 $out .= '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5871 $out .= '</form>';
5872 } else {
5873 $out .= '<span class="project_head_block">';
5874 if ($selected) {
5875 $projet = new Project($this->db);
5876 $projet->fetch($selected);
5877 $out .= $projet->getNomUrl(0, '', 1);
5878 } else {
5879 $out .= '<span class="opacitymedium">' . $textifnoproject . '</span>';
5880 }
5881 $out .= '</span>';
5882 }
5883
5884 if (empty($nooutput)) {
5885 print $out;
5886 return '';
5887 }
5888 return $out;
5889 }
5890
5891 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5892
5908 public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0, $type = '', $filtertype = -1, $deposit_percent = -1, $nooutput = 0)
5909 {
5910 // phpcs:enable
5911 global $langs;
5912
5913 $out = '';
5914
5915 if ($htmlname != "none") {
5916 $out .= '<form method="POST" action="' . $page . '">';
5917 $out .= '<input type="hidden" name="action" value="setconditions">';
5918 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5919 if ($type) {
5920 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5921 }
5922 $out .= $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, 0, '', $deposit_percent);
5923 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5924 $out .= '</form>';
5925 } else {
5926 if ($selected) {
5928 if (isset($this->cache_conditions_paiements[$selected])) {
5929 $label = $this->cache_conditions_paiements[$selected]['label'];
5930
5931 if (!empty($this->cache_conditions_paiements[$selected]['deposit_percent'])) {
5932 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $this->cache_conditions_paiements[$selected]['deposit_percent'], $label);
5933 }
5934
5935 $out .= $label;
5936 } else {
5937 $langs->load('errors');
5938 $out .= $langs->trans('ErrorNotInDictionaryPaymentConditions');
5939 }
5940 } else {
5941 $out .= '&nbsp;';
5942 }
5943 }
5944
5945 if (empty($nooutput)) {
5946 print $out;
5947 return '';
5948 }
5949 return $out;
5950 }
5951
5952 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5953
5963 public function form_availability($page, $selected = '', $htmlname = 'availability', $addempty = 0)
5964 {
5965 // phpcs:enable
5966 global $langs;
5967 if ($htmlname != "none") {
5968 print '<form method="post" action="' . $page . '">';
5969 print '<input type="hidden" name="action" value="setavailability">';
5970 print '<input type="hidden" name="token" value="' . newToken() . '">';
5971 $this->selectAvailabilityDelay($selected, $htmlname, -1, $addempty);
5972 print '<input type="submit" name="modify" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5973 print '<input type="submit" name="cancel" class="button smallpaddingimp" value="' . $langs->trans("Cancel") . '">';
5974 print '</form>';
5975 } else {
5976 if ($selected) {
5977 $this->load_cache_availability();
5978 print $this->cache_availability[$selected]['label'];
5979 } else {
5980 print "&nbsp;";
5981 }
5982 }
5983 }
5984
5995 public function formInputReason($page, $selected = '', $htmlname = 'demandreason', $addempty = 0)
5996 {
5997 global $langs;
5998 if ($htmlname != "none") {
5999 print '<form method="post" action="' . $page . '">';
6000 print '<input type="hidden" name="action" value="setdemandreason">';
6001 print '<input type="hidden" name="token" value="' . newToken() . '">';
6002 $this->selectInputReason($selected, $htmlname, -1, $addempty);
6003 print '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
6004 print '</form>';
6005 } else {
6006 if ($selected) {
6007 $this->loadCacheInputReason();
6008 foreach ($this->cache_demand_reason as $key => $val) {
6009 if ($val['id'] == $selected) {
6010 print $val['label'];
6011 break;
6012 }
6013 }
6014 } else {
6015 print "&nbsp;";
6016 }
6017 }
6018 }
6019
6020 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6021
6035 public function form_date($page, $selected, $htmlname, $displayhour = 0, $displaymin = 0, $nooutput = 0, $type = '')
6036 {
6037 // phpcs:enable
6038 global $langs;
6039
6040 $ret = '';
6041
6042 if ($htmlname != "none") {
6043 $ret .= '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
6044 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
6045 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
6046 if ($type) {
6047 $ret .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
6048 }
6049 $ret .= '<table class="nobordernopadding">';
6050 $ret .= '<tr><td>';
6051 $ret .= $this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form' . $htmlname, 1, 0);
6052 $ret .= '</td>';
6053 $ret .= '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6054 $ret .= '</tr></table></form>';
6055 } else {
6056 if ($displayhour) {
6057 $ret .= dol_print_date($selected, 'dayhour');
6058 } else {
6059 $ret .= dol_print_date($selected, 'day');
6060 }
6061 }
6062
6063 if (empty($nooutput)) {
6064 print $ret;
6065 }
6066 return $ret;
6067 }
6068
6069
6070 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6071
6082 public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = array(), $include = array())
6083 {
6084 // phpcs:enable
6085 global $langs;
6086
6087 if ($htmlname != "none") {
6088 print '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
6089 print '<input type="hidden" name="action" value="set' . $htmlname . '">';
6090 print '<input type="hidden" name="token" value="' . newToken() . '">';
6091 print $this->select_dolusers($selected, $htmlname, 1, $exclude, 0, $include);
6092 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6093 print '</form>';
6094 } else {
6095 if ($selected) {
6096 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
6097 $theuser = new User($this->db);
6098 $theuser->fetch($selected);
6099 print $theuser->getNomUrl(1);
6100 } else {
6101 print "&nbsp;";
6102 }
6103 }
6104 }
6105
6106
6107 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6108
6122 public function form_modes_reglement($page, $selected = '', $htmlname = 'mode_reglement_id', $filtertype = '', $active = 1, $addempty = 0, $type = '', $nooutput = 0)
6123 {
6124 // phpcs:enable
6125 global $langs;
6126
6127 $out = '';
6128 if ($htmlname != "none") {
6129 $out .= '<form method="POST" action="' . $page . '">';
6130 $out .= '<input type="hidden" name="action" value="setmode">';
6131 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6132 if ($type) {
6133 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
6134 }
6135 $out .= $this->select_types_paiements($selected, $htmlname, $filtertype, 0, $addempty, 0, 0, $active, '', 1);
6136 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6137 $out .= '</form>';
6138 } else {
6139 if ($selected) {
6141 $out .= $this->cache_types_paiements[$selected]['label'];
6142 } else {
6143 $out .= "&nbsp;";
6144 }
6145 }
6146
6147 if ($nooutput) {
6148 return $out;
6149 } else {
6150 print $out;
6151 }
6152 return '';
6153 }
6154
6165 public function formSelectTransportMode($page, $selected = '', $htmlname = 'transport_mode_id', $active = 1, $addempty = 0)
6166 {
6167 global $langs;
6168 if ($htmlname != "none") {
6169 print '<form method="POST" action="' . $page . '">';
6170 print '<input type="hidden" name="action" value="settransportmode">';
6171 print '<input type="hidden" name="token" value="' . newToken() . '">';
6172 $this->selectTransportMode($selected, $htmlname, 0, $addempty, 0, 0, $active);
6173 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6174 print '</form>';
6175 } else {
6176 if ($selected) {
6178 print $this->cache_transport_mode[$selected]['label'];
6179 } else {
6180 print "&nbsp;";
6181 }
6182 }
6183 }
6184
6185 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6186
6195 public function form_multicurrency_code($page, $selected = '', $htmlname = 'multicurrency_code')
6196 {
6197 // phpcs:enable
6198 global $langs;
6199 if ($htmlname != "none") {
6200 print '<form method="POST" action="' . $page . '">';
6201 print '<input type="hidden" name="action" value="setmulticurrencycode">';
6202 print '<input type="hidden" name="token" value="' . newToken() . '">';
6203 print $this->selectMultiCurrency($selected, $htmlname, 0);
6204 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6205 print '</form>';
6206 } else {
6207 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6208 print !empty($selected) ? currency_name($selected, 1) : '&nbsp;';
6209 }
6210 }
6211
6212 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6213
6223 public function form_multicurrency_rate($page, $rate = 0.0, $htmlname = 'multicurrency_tx', $currency = '')
6224 {
6225 // phpcs:enable
6226 global $langs, $mysoc, $conf;
6227
6228 if ($htmlname != "none") {
6229 print '<form method="POST" action="' . $page . '">';
6230 print '<input type="hidden" name="action" value="setmulticurrencyrate">';
6231 print '<input type="hidden" name="token" value="' . newToken() . '">';
6232 print '<input type="text" class="maxwidth100" name="' . $htmlname . '" value="' . (!empty($rate) ? price(price2num($rate, 'CU')) : 1) . '" /> ';
6233 print '<select name="calculation_mode">';
6234 print '<option value="1">Change ' . $langs->trans("PriceUHT") . ' of lines</option>';
6235 print '<option value="2">Change ' . $langs->trans("PriceUHTCurrency") . ' of lines</option>';
6236 print '</select> ';
6237 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6238 print '</form>';
6239 } else {
6240 if (!empty($rate)) {
6241 print price($rate, 1, $langs, 0, 0);
6242 if ($currency && $rate != 1) {
6243 print ' &nbsp; (' . price($rate, 1, $langs, 0, 0) . ' ' . $currency . ' = 1 ' . $conf->currency . ')';
6244 }
6245 } else {
6246 print 1;
6247 }
6248 }
6249 }
6250
6251
6252 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6253
6269 public function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter = '', $maxvalue = 0, $more = '', $hidelist = 0, $discount_type = 0)
6270 {
6271 // phpcs:enable
6272 global $conf, $langs;
6273 if ($htmlname != "none") {
6274 print '<form method="post" action="' . $page . '">';
6275 print '<input type="hidden" name="action" value="setabsolutediscount">';
6276 print '<input type="hidden" name="token" value="' . newToken() . '">';
6277 print '<div class="inline-block">';
6278 if (!empty($discount_type)) {
6279 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
6280 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL") {
6281 $translationKey = 'HasAbsoluteDiscountFromSupplier'; // If we want deposit to be subtracted to payments only and not to total of final invoice
6282 } else {
6283 $translationKey = 'HasCreditNoteFromSupplier';
6284 }
6285 } else {
6286 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6287 $translationKey = 'HasAbsoluteDiscountFromSupplier';
6288 } else {
6289 $translationKey = 'HasCreditNoteFromSupplier';
6290 }
6291 }
6292 } else {
6293 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
6294 if (!$filter || $filter == "fk_facture_source IS NULL") {
6295 $translationKey = 'CompanyHasAbsoluteDiscount'; // If we want deposit to be subtracted to payments only and not to total of final invoice
6296 } else {
6297 $translationKey = 'CompanyHasCreditNote';
6298 }
6299 } else {
6300 if (!$filter || $filter == "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6301 $translationKey = 'CompanyHasAbsoluteDiscount';
6302 } else {
6303 $translationKey = 'CompanyHasCreditNote';
6304 }
6305 }
6306 }
6307 print $langs->trans($translationKey, price($amount, 0, $langs, 0, 0, -1, $conf->currency));
6308 if (empty($hidelist)) {
6309 print ' ';
6310 }
6311 print '</div>';
6312 if (empty($hidelist)) {
6313 print '<div class="inline-block" style="padding-right: 10px">';
6314 $newfilter = 'discount_type=' . intval($discount_type);
6315 if (!empty($discount_type)) {
6316 $newfilter .= ' AND fk_invoice_supplier IS NULL AND fk_invoice_supplier_line IS NULL'; // Supplier discounts available
6317 } else {
6318 $newfilter .= ' AND fk_facture IS NULL AND fk_facture_line IS NULL'; // Customer discounts available
6319 }
6320 if ($filter) {
6321 $newfilter .= ' AND (' . $filter . ')';
6322 }
6323 // output the combo of discounts
6324 $nbqualifiedlines = $this->select_remises($selected, $htmlname, $newfilter, $socid, $maxvalue);
6325 if ($nbqualifiedlines > 0) {
6326 print ' &nbsp; <input type="submit" class="button smallpaddingimp" value="' . dol_escape_htmltag($langs->trans("UseLine")) . '"';
6327 if (!empty($discount_type) && $filter && $filter != "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6328 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6329 }
6330 if (empty($discount_type) && $filter && $filter != "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6331 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6332 }
6333
6334 print '>';
6335 }
6336 print '</div>';
6337 }
6338 if ($more) {
6339 print '<div class="inline-block">';
6340 print $more;
6341 print '</div>';
6342 }
6343 print '</form>';
6344 } else {
6345 if ($selected) {
6346 print $selected;
6347 } else {
6348 print "0";
6349 }
6350 }
6351 }
6352
6353
6354 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6355
6365 public function form_contacts($page, $societe, $selected = '', $htmlname = 'contactid')
6366 {
6367 // phpcs:enable
6368 global $langs;
6369
6370 if ($htmlname != "none") {
6371 print '<form method="post" action="' . $page . '">';
6372 print '<input type="hidden" name="action" value="set_contact">';
6373 print '<input type="hidden" name="token" value="' . newToken() . '">';
6374 print '<table class="nobordernopadding">';
6375 print '<tr><td>';
6376 print $this->selectcontacts($societe->id, $selected, $htmlname);
6377 $num = $this->num;
6378 if ($num == 0) {
6379 $addcontact = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("AddContact") : $langs->trans("AddContactAddress"));
6380 print '<a href="' . DOL_URL_ROOT . '/contact/card.php?socid=' . $societe->id . '&amp;action=create&amp;backtoreferer=1">' . $addcontact . '</a>';
6381 }
6382 print '</td>';
6383 print '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6384 print '</tr></table></form>';
6385 } else {
6386 if ($selected) {
6387 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
6388 $contact = new Contact($this->db);
6389 $contact->fetch($selected);
6390 print $contact->getFullName($langs);
6391 } else {
6392 print "&nbsp;";
6393 }
6394 }
6395 }
6396
6397 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6398
6415 public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0, $excludeids = array(), $textifnothirdparty = '')
6416 {
6417 // phpcs:enable
6418 global $langs;
6419
6420 $out = '';
6421 if ($htmlname != "none") {
6422 $out .= '<form method="post" action="' . $page . '">';
6423 $out .= '<input type="hidden" name="action" value="set_thirdparty">';
6424 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6425 $out .= $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, 0, 'minwidth100', '', '', 1, array(), false, $excludeids);
6426 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6427 $out .= '</form>';
6428 } else {
6429 if ($selected) {
6430 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
6431 $soc = new Societe($this->db);
6432 $soc->fetch($selected);
6433 $out .= $soc->getNomUrl(0, '');
6434 } else {
6435 $out .= '<span class="opacitymedium">' . $textifnothirdparty . '</span>';
6436 }
6437 }
6438
6439 if ($nooutput) {
6440 return $out;
6441 } else {
6442 print $out;
6443 }
6444
6445 return '';
6446 }
6447
6448 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6449
6458 public function select_currency($selected = '', $htmlname = 'currency_id')
6459 {
6460 // phpcs:enable
6461 print $this->selectCurrency($selected, $htmlname);
6462 }
6463
6473 public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0, $useempty = '')
6474 {
6475 global $langs, $user;
6476
6477 $langs->loadCacheCurrencies('');
6478
6479 $out = '';
6480
6481 if ($selected == 'euro' || $selected == 'euros') {
6482 $selected = 'EUR'; // Pour compatibilite
6483 }
6484
6485 $out .= '<select class="flat maxwidth200onsmartphone minwidth300" name="' . $htmlname . '" id="' . $htmlname . '">';
6486 if ($useempty) {
6487 $out .= '<option value="-1" selected></option>';
6488 }
6489 foreach ($langs->cache_currencies as $code_iso => $currency) {
6490 $labeltoshow = $currency['label'];
6491 if ($mode == 1) {
6492 $labeltoshow .= ' <span class="opacitymedium">(' . $code_iso . ')</span>';
6493 } else {
6494 $labeltoshow .= ' <span class="opacitymedium">(' . $langs->getCurrencySymbol($code_iso) . ')</span>';
6495 }
6496
6497 if ($selected && $selected == $code_iso) {
6498 $out .= '<option value="' . $code_iso . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6499 } else {
6500 $out .= '<option value="' . $code_iso . '" data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6501 }
6502 $out .= $labeltoshow;
6503 $out .= '</option>';
6504 }
6505 $out .= '</select>';
6506 if ($user->admin) {
6507 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
6508 }
6509
6510 // Make select dynamic
6511 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6512 $out .= ajax_combobox($htmlname);
6513
6514 return $out;
6515 }
6516
6529 public function selectMultiCurrency($selected = '', $htmlname = 'multicurrency_code', $useempty = 0, $filter = '', $excludeConfCurrency = false, $morecss = '')
6530 {
6531 global $conf, $langs;
6532
6533 $langs->loadCacheCurrencies(''); // Load ->cache_currencies
6534
6535 $TCurrency = array();
6536
6537 $sql = "SELECT code FROM " . $this->db->prefix() . "multicurrency";
6538 $sql .= " WHERE entity IN ('" . getEntity('mutlicurrency') . "')";
6539 if ($filter) {
6540 $sql .= " AND " . $filter;
6541 }
6542 $resql = $this->db->query($sql);
6543 if ($resql) {
6544 while ($obj = $this->db->fetch_object($resql)) {
6545 $TCurrency[$obj->code] = $obj->code;
6546 }
6547 }
6548
6549 $out = '';
6550 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
6551 if ($useempty) {
6552 $out .= '<option value="">&nbsp;</option>';
6553 }
6554 // If company current currency not in table, we add it into list. Should always be available.
6555 if (!in_array($conf->currency, $TCurrency) && !$excludeConfCurrency) {
6556 $TCurrency[$conf->currency] = $conf->currency;
6557 }
6558 if (count($TCurrency) > 0) {
6559 foreach ($langs->cache_currencies as $code_iso => $currency) {
6560 if (isset($TCurrency[$code_iso])) {
6561 if (!empty($selected) && $selected == $code_iso) {
6562 $out .= '<option value="' . $code_iso . '" selected="selected">';
6563 } else {
6564 $out .= '<option value="' . $code_iso . '">';
6565 }
6566
6567 $out .= $currency['label'];
6568 $out .= ' (' . $langs->getCurrencySymbol($code_iso) . ')';
6569 $out .= '</option>';
6570 }
6571 }
6572 }
6573
6574 $out .= '</select>';
6575
6576 // Make select dynamic
6577 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6578 $out .= ajax_combobox($htmlname);
6579
6580 return $out;
6581 }
6582
6583 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6584
6591 public function load_cache_vatrates($country_code)
6592 {
6593 // phpcs:enable
6594 global $langs, $user;
6595
6596 $num = count($this->cache_vatrates);
6597 if ($num > 0) {
6598 return $num; // Cache already loaded
6599 }
6600
6601 dol_syslog(__METHOD__, LOG_DEBUG);
6602
6603 $sql = "SELECT t.rowid, t.type_vat, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
6604 $sql .= " FROM ".$this->db->prefix()."c_tva as t, ".$this->db->prefix()."c_country as c";
6605 $sql .= " WHERE t.fk_pays = c.rowid";
6606 $sql .= " AND t.active > 0";
6607 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
6608 $sql .= " AND c.code IN (" . $this->db->sanitize($country_code, 1) . ")";
6609 $sql .= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC";
6610
6611 $resql = $this->db->query($sql);
6612 if ($resql) {
6613 $num = $this->db->num_rows($resql);
6614 if ($num) {
6615 for ($i = 0; $i < $num; $i++) {
6616 $obj = $this->db->fetch_object($resql);
6617
6618 $tmparray = array();
6619 $tmparray['rowid'] = $obj->rowid;
6620 $tmparray['type_vat'] = $obj->type_vat;
6621 $tmparray['code'] = $obj->code;
6622 $tmparray['txtva'] = $obj->taux;
6623 $tmparray['nprtva'] = $obj->recuperableonly;
6624 $tmparray['localtax1'] = $obj->localtax1;
6625 $tmparray['localtax1_type'] = $obj->localtax1_type;
6626 $tmparray['localtax2'] = $obj->localtax2;
6627 $tmparray['localtax2_type'] = $obj->localtax1_type;
6628 $tmparray['label'] = $obj->taux . '%' . ($obj->code ? ' (' . $obj->code . ')' : ''); // Label must contains only 0-9 , . % or *
6629 $tmparray['labelallrates'] = $obj->taux . '/' . ($obj->localtax1 ? $obj->localtax1 : '0') . '/' . ($obj->localtax2 ? $obj->localtax2 : '0') . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
6630 $positiverates = '';
6631 if ($obj->taux) {
6632 $positiverates .= ($positiverates ? '/' : '') . $obj->taux;
6633 }
6634 if ($obj->localtax1) {
6635 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax1;
6636 }
6637 if ($obj->localtax2) {
6638 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax2;
6639 }
6640 if (empty($positiverates)) {
6641 $positiverates = '0';
6642 }
6643 $tmparray['labelpositiverates'] = $positiverates . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
6644
6645 $this->cache_vatrates[$obj->rowid] = $tmparray;
6646 }
6647
6648 return $num;
6649 } else {
6650 $this->error = '<span class="error">';
6651 $this->error .= $langs->trans("ErrorNoVATRateDefinedForSellerCountry", $country_code);
6652 $reg = array();
6653 if (!empty($user) && $user->admin && preg_match('/\'(..)\'/', $country_code, $reg)) {
6654 $langs->load("errors");
6655 $new_country_code = $reg[1];
6656 $country_id = dol_getIdFromCode($this->db, $new_country_code, 'c_pays', 'code', 'rowid');
6657 $this->error .= '<br>'.$langs->trans("ErrorFixThisHere", DOL_URL_ROOT.'/admin/dict.php?id=10'.($country_id > 0 ? '&countryidforinsert='.$country_id : ''));
6658 }
6659 $this->error .= '</span>';
6660 return -1;
6661 }
6662 } else {
6663 $this->error = '<span class="error">' . $this->db->error() . '</span>';
6664 return -2;
6665 }
6666 }
6667
6668 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6669
6692 public function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = null, $societe_acheteuse = null, $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0, $type_vat = 0)
6693 {
6694 // phpcs:enable
6695 global $langs, $mysoc;
6696
6697 $langs->load('errors');
6698
6699 $return = '';
6700
6701 // Define defaultnpr, defaultttx and defaultcode
6702 $defaultnpr = ($info_bits & 0x01);
6703 $defaultnpr = (preg_match('/\*/', $selectedrate) ? 1 : $defaultnpr);
6704 $defaulttx = str_replace('*', '', $selectedrate);
6705 $defaultcode = '';
6706 $reg = array();
6707 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6708 $defaultcode = $reg[1];
6709 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6710 }
6711 //var_dump($selectedrate.'-'.$defaulttx.'-'.$defaultnpr.'-'.$defaultcode);
6712
6713 // Check parameters
6714 if (is_object($societe_vendeuse) && !$societe_vendeuse->country_code) {
6715 if ($societe_vendeuse->id == $mysoc->id) {
6716 $return .= '<span class="error">' . $langs->trans("ErrorYourCountryIsNotDefined") . '</span>';
6717 } else {
6718 $return .= '<span class="error">' . $langs->trans("ErrorSupplierCountryIsNotDefined") . '</span>';
6719 }
6720 return $return;
6721 }
6722
6723 //var_dump($societe_acheteuse);
6724 //print "name=$name, selectedrate=$selectedrate, seller=".$societe_vendeuse->country_code." buyer=".$societe_acheteuse->country_code." buyer is company=".$societe_acheteuse->isACompany()." idprod=$idprod, info_bits=$info_bits type=$type";
6725 //exit;
6726
6727 // Define list of countries to use to search VAT rates to show
6728 // First we defined code_country to use to find list
6729 if (is_object($societe_vendeuse)) {
6730 $code_country = "'" . $societe_vendeuse->country_code . "'";
6731 } else {
6732 $code_country = "'" . $mysoc->country_code . "'"; // Pour compatibilite ascendente
6733 }
6734 if (getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC')) { // If option to have vat for end customer for services is on
6735 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6736 // If SERVICE_ARE_ECOMMERCE_200238EC=1 combo list vat rate of purchaser and seller countries
6737 // If SERVICE_ARE_ECOMMERCE_200238EC=2 combo list only the vat rate of the purchaser country
6738 $selectVatComboMode = getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC');
6739 if (isInEEC($societe_vendeuse) && isInEEC($societe_acheteuse) && !$societe_acheteuse->isACompany()) {
6740 // We also add the buyer country code
6741 if (is_numeric($type)) {
6742 if ($type == 1) { // We know product is a service
6743 switch ($selectVatComboMode) {
6744 case '1':
6745 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6746 break;
6747 case '2':
6748 $code_country = "'" . $societe_acheteuse->country_code . "'";
6749 break;
6750 }
6751 }
6752 } elseif (!$idprod) { // We don't know type of product
6753 switch ($selectVatComboMode) {
6754 case '1':
6755 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6756 break;
6757 case '2':
6758 $code_country = "'" . $societe_acheteuse->country_code . "'";
6759 break;
6760 }
6761 } else {
6762 $prodstatic = new Product($this->db);
6763 $prodstatic->fetch($idprod);
6764 if ($prodstatic->type == Product::TYPE_SERVICE) { // We know product is a service
6765 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6766 }
6767 }
6768 }
6769 }
6770
6771 // Now we load the list of VAT
6772 $this->load_cache_vatrates($code_country); // If no vat defined, return -1 with message into this->error
6773
6774 // Keep only the VAT qualified for $type_vat
6775 $arrayofvatrates = array();
6776 foreach ($this->cache_vatrates as $cachevalue) {
6777 if (empty($cachevalue['type_vat']) || $cachevalue['type_vat'] == $type_vat) {
6778 $arrayofvatrates[] = $cachevalue;
6779 }
6780 }
6781
6782 $num = count($arrayofvatrates);
6783
6784 if ($num > 0) {
6785 // Define the rate to pre-select (if defaulttx not forced so is -1 or '')
6786 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6787 // Define a default thirdparty to use if the seller or buyer is not defined
6788 $tmpthirdparty = new Societe($this->db);
6789 $tmpthirdparty->country_code = $mysoc->country_code;
6790
6791 $defaulttx = get_default_tva(is_object($societe_vendeuse) ? $societe_vendeuse : $tmpthirdparty, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6792 $defaultnpr = get_default_npr(is_object($societe_vendeuse) ? $societe_vendeuse : $tmpthirdparty, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6793
6794 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6795 $defaultcode = $reg[1];
6796 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6797 }
6798 if (empty($defaulttx)) {
6799 $defaultnpr = 0;
6800 }
6801 }
6802
6803 // If we fails to find a default vat rate, we take the last one in list
6804 // Because they are sorted in ascending order, the last one will be the higher one (we suppose the higher one is the current rate)
6805 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6806 if (!getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS')) {
6807 // We take the last one found in list
6808 $defaulttx = $arrayofvatrates[$num - 1]['txtva'];
6809 } else {
6810 // We will use the rate defined into MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS
6811 $defaulttx = '';
6812 if (getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS') != 'none') {
6813 $defaulttx = getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS');
6814 }
6815 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6816 $defaultcode = $reg[1];
6817 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6818 }
6819 }
6820 }
6821
6822 // Disabled if seller is not subject to VAT
6823 $disabled = false;
6824 $title = '';
6825 if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0") {
6826 // Override/enable VAT for expense report regardless of global setting - needed if expense report used for business expenses instead
6827 // of using supplier invoices (this is a very bad idea !)
6828 if (!getDolGlobalString('EXPENSEREPORT_OVERRIDE_VAT')) {
6829 $title = ' title="' . dol_escape_htmltag($langs->trans('VATIsNotUsed')) . '"';
6830 $disabled = true;
6831 }
6832 }
6833
6834 if (!$options_only) {
6835 $return .= '<select class="flat minwidth75imp maxwidth100 right" id="' . $htmlname . '" name="' . $htmlname . '"' . ($disabled ? ' disabled' : '') . $title . '>';
6836 }
6837
6838 $selectedfound = false;
6839 foreach ($arrayofvatrates as $rate) {
6840 // Keep only 0 if seller is not subject to VAT
6841 if ($disabled && $rate['txtva'] != 0) {
6842 continue;
6843 }
6844
6845 // Define key to use into select list
6846 $key = $rate['txtva'];
6847 $key .= $rate['nprtva'] ? '*' : '';
6848 if ($mode > 0 && $rate['code']) {
6849 $key .= ' (' . $rate['code'] . ')';
6850 }
6851 if ($mode < 0) {
6852 $key = $rate['rowid'];
6853 }
6854
6855 $return .= '<option value="' . $key . '"';
6856 if (!$selectedfound) {
6857 if ($defaultcode) { // If defaultcode is defined, we used it in priority to select combo option instead of using rate+npr flag
6858 if ($defaultcode == $rate['code']) {
6859 $return .= ' selected';
6860 $selectedfound = true;
6861 }
6862 } elseif ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr) {
6863 $return .= ' selected';
6864 $selectedfound = true;
6865 }
6866 }
6867 $return .= '>';
6868
6869 // Show label of VAT
6870 if ($mysoc->country_code == 'IN' || getDolGlobalString('MAIN_VAT_LABEL_IS_POSITIVE_RATES')) {
6871 // Label with all localtax and code. For example: x.y / a.b / c.d (CODE)'
6872 $return .= $rate['labelpositiverates'];
6873 } else {
6874 // Simple label
6875 $return .= vatrate($rate['label']);
6876 }
6877
6878 //$return.=($rate['code']?' '.$rate['code']:'');
6879 $return .= (empty($rate['code']) && $rate['nprtva']) ? ' *' : ''; // We show the * (old behaviour only if new vat code is not used)
6880
6881 $return .= '</option>';
6882 }
6883
6884 if (!$options_only) {
6885 $return .= '</select>';
6886 //$return .= ajax_combobox($htmlname); // This break for the moment the dynamic autoselection of a value when selecting a product in object lines
6887 }
6888 } else {
6889 $return .= $this->error;
6890 }
6891
6892 $this->num = $num;
6893 return $return;
6894 }
6895
6896
6897 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6898
6923 public function select_date($set_time = '', $prefix = 're', $h = 0, $m = 0, $empty = 0, $form_name = "", $d = 1, $addnowlink = 0, $nooutput = 0, $disabled = 0, $fullday = 0, $addplusone = '', $adddateof = '')
6924 {
6925 // phpcs:enable
6926 dol_syslog(__METHOD__ . ': using select_date is deprecated. Use selectDate instead.', LOG_WARNING);
6927 $retstring = $this->selectDate($set_time, $prefix, $h, $m, $empty, $form_name, $d, $addnowlink, $disabled, $fullday, $addplusone, $adddateof);
6928 if (!empty($nooutput)) {
6929 return $retstring;
6930 }
6931 print $retstring;
6932
6933 return '';
6934 }
6935
6951 public function selectDateToDate($set_time = '', $set_time_end = '', $prefix = 're', $empty = 0, $forcenewline = 0)
6952 {
6953 global $langs;
6954
6955 $ret = $this->selectDate($set_time, $prefix . '_start', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("from"), 'tzuserrel');
6956 if ($forcenewline) {
6957 $ret .= '<br>';
6958 }
6959 $ret .= $this->selectDate($set_time_end, $prefix . '_end', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"), 'tzuserrel');
6960 return $ret;
6961 }
6962
6990 public function selectDate($set_time = '', $prefix = 're', $h = 0, $m = 0, $empty = 0, $form_name = "", $d = 1, $addnowlink = 0, $disabled = 0, $fullday = '', $addplusone = '', $adddateof = '', $openinghours = '', $stepminutes = 1, $labeladddateof = '', $placeholder = '', $gm = 'auto')
6991 {
6992 global $conf, $langs;
6993
6994 if ($gm === 'auto') {
6995 $gm = (empty($conf) ? 'tzserver' : $conf->tzuserinputkey);
6996 }
6997
6998 $retstring = '';
6999
7000 if ($prefix == '') {
7001 $prefix = 're';
7002 }
7003 if ($h == '') {
7004 $h = 0;
7005 }
7006 if ($m == '') {
7007 $m = 0;
7008 }
7009 $emptydate = 0;
7010 $emptyhours = 0;
7011 if ($stepminutes <= 0 || $stepminutes > 30) {
7012 $stepminutes = 1;
7013 }
7014 if ($empty == 1) {
7015 $emptydate = 1;
7016 $emptyhours = 1;
7017 }
7018 if ($empty == 2) {
7019 $emptydate = 0;
7020 $emptyhours = 1;
7021 }
7022 $orig_set_time = $set_time;
7023
7024 if ($set_time === '' && $emptydate == 0) {
7025 include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7026 if ($gm == 'tzuser' || $gm == 'tzuserrel') {
7027 $set_time = dol_now($gm);
7028 } else {
7029 $set_time = dol_now('tzuser') - (getServerTimeZoneInt('now') * 3600); // set_time must be relative to PHP server timezone
7030 }
7031 }
7032
7033 // Analysis of the pre-selection date
7034 $reg = array();
7035 $shour = '';
7036 $smin = '';
7037 $ssec = '';
7038 if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', $set_time, $reg)) { // deprecated usage
7039 // Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'
7040 $syear = (!empty($reg[1]) ? $reg[1] : '');
7041 $smonth = (!empty($reg[2]) ? $reg[2] : '');
7042 $sday = (!empty($reg[3]) ? $reg[3] : '');
7043 $shour = (!empty($reg[4]) ? $reg[4] : '');
7044 $smin = (!empty($reg[5]) ? $reg[5] : '');
7045 } elseif (strval($set_time) != '' && $set_time != -1) {
7046 // set_time est un timestamps (0 possible)
7047 $syear = dol_print_date($set_time, "%Y", $gm);
7048 $smonth = dol_print_date($set_time, "%m", $gm);
7049 $sday = dol_print_date($set_time, "%d", $gm);
7050 if ($orig_set_time != '') {
7051 $shour = dol_print_date($set_time, "%H", $gm);
7052 $smin = dol_print_date($set_time, "%M", $gm);
7053 $ssec = dol_print_date($set_time, "%S", $gm);
7054 }
7055 } else {
7056 // Date est '' ou vaut -1
7057 $syear = '';
7058 $smonth = '';
7059 $sday = '';
7060 $shour = getDolGlobalString('MAIN_DEFAULT_DATE_HOUR', ($h == -1 ? '23' : ''));
7061 $smin = getDolGlobalString('MAIN_DEFAULT_DATE_MIN', ($h == -1 ? '59' : ''));
7062 $ssec = getDolGlobalString('MAIN_DEFAULT_DATE_SEC', ($h == -1 ? '59' : ''));
7063 }
7064 if ($h == 3 || $h == 4) {
7065 $shour = '';
7066 }
7067 if ($m == 3) {
7068 $smin = '';
7069 }
7070
7071 $nowgmt = dol_now('gmt');
7072 //var_dump(dol_print_date($nowgmt, 'dayhourinputnoreduce', 'tzuserrel'));
7073
7074 // You can set MAIN_POPUP_CALENDAR to 'eldy' or 'jquery'
7075 $usecalendar = 'combo';
7076 if (!empty($conf->use_javascript_ajax) && (!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') != "none")) {
7077 $usecalendar = ((!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') == 'eldy') ? 'jquery' : $conf->global->MAIN_POPUP_CALENDAR);
7078 }
7079 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7080 // If we use a text browser or screen reader, we use the 'combo' date selector
7081 $usecalendar = 'html';
7082 }
7083
7084 if ($d) {
7085 // Show date with popup
7086 if ($usecalendar != 'combo') {
7087 $formatted_date = '';
7088 //print "e".$set_time." t ".$conf->format_date_short;
7089 if (strval($set_time) != '' && $set_time != -1) {
7090 //$formatted_date=dol_print_date($set_time,$conf->format_date_short);
7091 $formatted_date = dol_print_date($set_time, $langs->trans("FormatDateShortInput"), $gm); // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7092 }
7093
7094 // Calendrier popup version eldy
7095 if ($usecalendar == "eldy") {
7096 // Input area to enter date manually
7097 $retstring .= '<input id="' . $prefix . '" name="' . $prefix . '" type="text" class="maxwidthdate center" maxlength="11" value="' . $formatted_date . '"';
7098 $retstring .= ($disabled ? ' disabled' : '');
7099 $retstring .= ' onChange="dpChangeDay(\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7100 $retstring .= ' autocomplete="off">';
7101
7102 // Icon calendar
7103 $retstringbuttom = '';
7104 if (!$disabled) {
7105 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons"';
7106 $base = DOL_URL_ROOT . '/core/';
7107 $retstringbuttom .= ' onClick="showDP(\'' . $base . '\',\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\',\'' . $langs->defaultlang . '\');"';
7108 $retstringbuttom .= '>' . img_object($langs->trans("SelectDate"), 'calendarday', 'class="datecallink"') . '</button>';
7109 } else {
7110 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
7111 }
7112 $retstring = $retstringbuttom . $retstring;
7113
7114 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
7115 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
7116 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
7117 } elseif ($usecalendar == 'jquery' || $usecalendar == 'html') {
7118 if (!$disabled && $usecalendar != 'html') {
7119 // Output javascript for datepicker
7120 $minYear = getDolGlobalInt('MIN_YEAR_SELECT_DATE', (idate('Y') - 100));
7121 $maxYear = getDolGlobalInt('MAX_YEAR_SELECT_DATE', (idate('Y') + 100));
7122
7123 $retstring .= '<script nonce="' . getNonce() . '" type="text/javascript">';
7124 $retstring .= "$(function(){ $('#" . $prefix . "').datepicker({
7125 dateFormat: '" . $langs->trans("FormatDateShortJQueryInput") . "',
7126 autoclose: true,
7127 todayHighlight: true,
7128 yearRange: '" . $minYear . ":" . $maxYear . "',";
7129 if (!empty($conf->dol_use_jmobile)) {
7130 $retstring .= "
7131 beforeShow: function (input, datePicker) {
7132 input.disabled = true;
7133 },
7134 onClose: function (dateText, datePicker) {
7135 this.disabled = false;
7136 },
7137 ";
7138 }
7139 // Note: We don't need monthNames, monthNamesShort, dayNames, dayNamesShort, dayNamesMin, they are set globally on datepicker component in lib_head.js.php
7140 if (!getDolGlobalString('MAIN_POPUP_CALENDAR_ON_FOCUS')) {
7141 $retstring .= "
7142 showOn: 'button', /* both has problem with autocompletion */
7143 buttonImage: '" . DOL_URL_ROOT . "/theme/" . dol_escape_js($conf->theme) . "/img/object_calendarday.png',
7144 buttonImageOnly: true";
7145 }
7146 $retstring .= "
7147 }) });";
7148 $retstring .= "</script>";
7149 }
7150
7151 // Input area to enter date manually
7152 $retstring .= '<div class="nowraponall inline-block divfordateinput">';
7153 $retstring .= '<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidthdate center" maxlength="11" value="'.$formatted_date.'"';
7154 $retstring .= ($disabled ? ' disabled' : '');
7155 $retstring .= ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '');
7156 $retstring .= ' onChange="dpChangeDay(\'' . dol_escape_js($prefix) . '\',\'' . dol_escape_js($langs->trans("FormatDateShortJavaInput")) . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7157 $retstring .= ' autocomplete="off">';
7158
7159 // Icone calendrier
7160 if ($disabled) {
7161 $retstringbutton = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
7162 $retstring = $retstringbutton . $retstring;
7163 }
7164
7165 $retstring .= '</div>';
7166 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
7167 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
7168 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
7169 } else {
7170 $retstring .= "Bad value of MAIN_POPUP_CALENDAR";
7171 }
7172 } else {
7173 // Show date with combo selects
7174 // Day
7175 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50imp" id="' . $prefix . 'day" name="' . $prefix . 'day">';
7176
7177 if ($emptydate || $set_time == -1) {
7178 $retstring .= '<option value="0" selected>&nbsp;</option>';
7179 }
7180
7181 for ($day = 1; $day <= 31; $day++) {
7182 $retstring .= '<option value="' . $day . '"' . ($day == $sday ? ' selected' : '') . '>' . $day . '</option>';
7183 }
7184
7185 $retstring .= "</select>";
7186
7187 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'month" name="' . $prefix . 'month">';
7188 if ($emptydate || $set_time == -1) {
7189 $retstring .= '<option value="0" selected>&nbsp;</option>';
7190 }
7191
7192 // Month
7193 for ($month = 1; $month <= 12; $month++) {
7194 $retstring .= '<option value="' . $month . '"' . ($month == $smonth ? ' selected' : '') . '>';
7195 $retstring .= dol_print_date(mktime(12, 0, 0, $month, 1, 2000), "%b");
7196 $retstring .= "</option>";
7197 }
7198 $retstring .= "</select>";
7199
7200 // Year
7201 if ($emptydate || $set_time == -1) {
7202 $retstring .= '<input' . ($disabled ? ' disabled' : '') . ' placeholder="' . dol_escape_htmltag($langs->trans("Year")) . '" class="flat maxwidth50imp valignmiddle" type="number" min="0" max="3000" maxlength="4" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">';
7203 } else {
7204 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'year" name="' . $prefix . 'year">';
7205
7206 $syear = (int) $syear;
7207 for ($year = $syear - 10; $year < (int) $syear + 10; $year++) {
7208 $retstring .= '<option value="' . $year . '"' . ($year == $syear ? ' selected' : '') . '>' . $year . '</option>';
7209 }
7210 $retstring .= "</select>\n";
7211 }
7212 }
7213 }
7214
7215 if ($d && $h) {
7216 $retstring .= (($h == 2 || $h == 4) ? '<br>' : ' ');
7217 $retstring .= '<span class="nowraponall">';
7218 }
7219
7220 if ($h) {
7221 $hourstart = 0;
7222 $hourend = 24;
7223 if ($openinghours != '') {
7224 $openinghours = explode(',', $openinghours);
7225 $hourstart = $openinghours[0];
7226 $hourend = $openinghours[1];
7227 if ($hourend < $hourstart) {
7228 $hourend = $hourstart;
7229 }
7230 }
7231 // Show hour
7232 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'hour' : '') . '" id="' . $prefix . 'hour" name="' . $prefix . 'hour">';
7233 if ($emptyhours) {
7234 $retstring .= '<option value="-1">&nbsp;</option>';
7235 }
7236 for ($hour = $hourstart; $hour < $hourend; $hour++) {
7237 if (strlen($hour) < 2) {
7238 $hour = "0" . $hour;
7239 }
7240 $retstring .= '<option value="' . $hour . '"' . (($hour == $shour) ? ' selected' : '') . '>' . $hour;
7241 //$retstring .= (empty($conf->dol_optimize_smallscreen) ? '' : 'H');
7242 $retstring .= '</option>';
7243 }
7244 $retstring .= '</select>';
7245 //if ($m && empty($conf->dol_optimize_smallscreen)) $retstring .= ":";
7246 if ($m) {
7247 $retstring .= ":";
7248 }
7249 }
7250
7251 if ($m) {
7252 // Show minutes
7253 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'min' : '') . '" id="' . $prefix . 'min" name="' . $prefix . 'min">';
7254 if ($emptyhours) {
7255 $retstring .= '<option value="-1">&nbsp;</option>';
7256 }
7257 for ($min = 0; $min < 60; $min += $stepminutes) {
7258 $min_str = sprintf("%02d", $min);
7259 $retstring .= '<option value="' . $min_str . '"' . (($min_str == $smin) ? ' selected' : '') . '>' . $min_str . '</option>';
7260 }
7261 $retstring .= '</select>';
7262
7263 $retstring .= '<input type="hidden" name="' . $prefix . 'sec" value="' . $ssec . '">';
7264 }
7265
7266 if ($d && $h) {
7267 $retstring .= '</span>';
7268 }
7269
7270 // Add a "Now" link
7271 if (!empty($conf->use_javascript_ajax) && $addnowlink) {
7272 // Script which will be inserted in the onClick of the "Now" link
7273 $reset_scripts = "";
7274 if ($addnowlink == 2) { // local computer time
7275 // pad add leading 0 on numbers
7276 $reset_scripts .= "Number.prototype.pad = function(size) {
7277 var s = String(this);
7278 while (s.length < (size || 2)) {s = '0' + s;}
7279 return s;
7280 };
7281 var d = new Date();";
7282 }
7283
7284 // Generate the date part, depending on the use or not of the javascript calendar
7285 if ($addnowlink == 1) { // server time expressed in user time setup
7286 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7287 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7288 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7289 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7290 } elseif ($addnowlink == 2) {
7291 /* Disabled because the output does not use the string format defined by FormatDateShort key to forge the value into #prefix.
7292 * This break application for foreign languages.
7293 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(d.toLocaleDateString(\''.str_replace('_', '-', $langs->defaultlang).'\'));';
7294 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(d.getDate().pad());';
7295 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(parseInt(d.getMonth().pad()) + 1);';
7296 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(d.getFullYear());';
7297 */
7298 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7299 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7300 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7301 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7302 }
7303 /*if ($usecalendar == "eldy")
7304 {
7305 $base=DOL_URL_ROOT.'/core/';
7306 $reset_scripts .= 'resetDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');';
7307 }
7308 else
7309 {
7310 $reset_scripts .= 'this.form.elements[\''.$prefix.'day\'].value=formatDate(new Date(), \'d\'); ';
7311 $reset_scripts .= 'this.form.elements[\''.$prefix.'month\'].value=formatDate(new Date(), \'M\'); ';
7312 $reset_scripts .= 'this.form.elements[\''.$prefix.'year\'].value=formatDate(new Date(), \'yyyy\'); ';
7313 }*/
7314 // Update the hour part
7315 if ($h) {
7316 if ($fullday) {
7317 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7318 }
7319 //$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); ';
7320 if ($addnowlink == 1) {
7321 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7322 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7323 } elseif ($addnowlink == 2) {
7324 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(d.getHours().pad());';
7325 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7326 }
7327
7328 if ($fullday) {
7329 $reset_scripts .= ' } ';
7330 }
7331 }
7332 // Update the minute part
7333 if ($m) {
7334 if ($fullday) {
7335 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7336 }
7337 //$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); ';
7338 if ($addnowlink == 1) {
7339 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7340 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7341 } elseif ($addnowlink == 2) {
7342 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(d.getMinutes().pad());';
7343 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7344 }
7345 if ($fullday) {
7346 $reset_scripts .= ' } ';
7347 }
7348 }
7349 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7350 if ($reset_scripts && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7351 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonNow" type="button" name="_useless" value="now" onClick="' . $reset_scripts . '">';
7352 $retstring .= $langs->trans("Now");
7353 $retstring .= '</button> ';
7354 }
7355 }
7356
7357 // Add a "Plus one hour" link
7358 if ($conf->use_javascript_ajax && $addplusone) {
7359 // Script which will be inserted in the onClick of the "Add plusone" link
7360 $reset_scripts = "";
7361
7362 // Generate the date part, depending on the use or not of the javascript calendar
7363 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'dayinputnoreduce', 'tzuserrel') . '\');';
7364 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7365 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7366 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7367 // Update the hour part
7368 if ($h) {
7369 if ($fullday) {
7370 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7371 }
7372 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7373 if ($fullday) {
7374 $reset_scripts .= ' } ';
7375 }
7376 }
7377 // Update the minute part
7378 if ($m) {
7379 if ($fullday) {
7380 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7381 }
7382 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7383 if ($fullday) {
7384 $reset_scripts .= ' } ';
7385 }
7386 }
7387 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7388 if ($reset_scripts && empty($conf->dol_optimize_smallscreen)) {
7389 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonPlusOne" type="button" name="_useless2" value="plusone" onClick="' . $reset_scripts . '">';
7390 $retstring .= $langs->trans("DateStartPlusOne");
7391 $retstring .= '</button> ';
7392 }
7393 }
7394
7395 // Add a link to set data
7396 if ($conf->use_javascript_ajax && !empty($adddateof)) {
7397 if (!is_array($adddateof)) {
7398 $arrayofdateof = array(array('adddateof' => $adddateof, 'labeladddateof' => $labeladddateof));
7399 } else {
7400 $arrayofdateof = $adddateof;
7401 }
7402 foreach ($arrayofdateof as $valuedateof) {
7403 $tmpadddateof = empty($valuedateof['adddateof']) ? 0 : $valuedateof['adddateof'];
7404 $tmplabeladddateof = empty($valuedateof['labeladddateof']) ? '' : $valuedateof['labeladddateof'];
7405 $tmparray = dol_getdate($tmpadddateof);
7406 if (empty($tmplabeladddateof)) {
7407 $tmplabeladddateof = $langs->trans("DateInvoice");
7408 }
7409 $reset_scripts = 'console.log(\'Click on now link\'); ';
7410 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date($tmpadddateof, 'dayinputnoreduce').'\');';
7411 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.$tmparray['mday'].'\');';
7412 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.$tmparray['mon'].'\');';
7413 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.$tmparray['year'].'\');';
7414 $retstring .= ' - <button class="dpInvisibleButtons datenowlink" id="dateofinvoice" type="button" name="_dateofinvoice" value="now" onclick="'.$reset_scripts.'">'.$tmplabeladddateof.'</button>';
7415 }
7416 }
7417
7418 return $retstring;
7419 }
7420
7429 public function selectTypeDuration($prefix, $selected = 'i', $excludetypes = array())
7430 {
7431 global $langs;
7432
7433 $TDurationTypes = array(
7434 'y' => $langs->trans('Years'),
7435 'm' => $langs->trans('Month'),
7436 'w' => $langs->trans('Weeks'),
7437 'd' => $langs->trans('Days'),
7438 'h' => $langs->trans('Hours'),
7439 'i' => $langs->trans('Minutes')
7440 );
7441
7442 // Removed undesired duration types
7443 foreach ($excludetypes as $value) {
7444 unset($TDurationTypes[$value]);
7445 }
7446
7447 $retstring = '<select class="flat minwidth75 maxwidth100" id="select_' . $prefix . 'type_duration" name="' . $prefix . 'type_duration">';
7448 foreach ($TDurationTypes as $key => $typeduration) {
7449 $retstring .= '<option value="' . $key . '"';
7450 if ($key == $selected) {
7451 $retstring .= " selected";
7452 }
7453 $retstring .= ">" . $typeduration . "</option>";
7454 }
7455 $retstring .= "</select>";
7456
7457 $retstring .= ajax_combobox('select_' . $prefix . 'type_duration');
7458
7459 return $retstring;
7460 }
7461
7462 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
7463
7477 public function select_duration($prefix, $iSecond = '', $disabled = 0, $typehour = 'select', $minunderhours = 0, $nooutput = 0)
7478 {
7479 // phpcs:enable
7480 global $langs;
7481
7482 $retstring = '<span class="nowraponall">';
7483
7484 $hourSelected = '';
7485 $minSelected = '';
7486
7487 // Hours
7488 if ($iSecond != '') {
7489 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7490
7491 $hourSelected = convertSecondToTime($iSecond, 'allhour');
7492 $minSelected = convertSecondToTime($iSecond, 'min');
7493 }
7494
7495 if ($typehour == 'select') {
7496 $retstring .= '<select class="flat" id="select_' . $prefix . 'hour" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . '>';
7497 for ($hour = 0; $hour < 25; $hour++) { // For a duration, we allow 24 hours
7498 $retstring .= '<option value="' . $hour . '"';
7499 if (is_numeric($hourSelected) && $hourSelected == $hour) {
7500 $retstring .= " selected";
7501 }
7502 $retstring .= ">" . $hour . "</option>";
7503 }
7504 $retstring .= "</select>";
7505 } elseif ($typehour == 'text' || $typehour == 'textselect') {
7506 $retstring .= '<input placeholder="' . $langs->trans('HourShort') . '" type="number" min="0" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputhour right" value="' . (($hourSelected != '') ? ((int) $hourSelected) : '') . '">';
7507 } else {
7508 return 'BadValueForParameterTypeHour';
7509 }
7510
7511 if ($typehour != 'text') {
7512 $retstring .= ' ' . $langs->trans('HourShort');
7513 } else {
7514 $retstring .= '<span class="">:</span>';
7515 }
7516
7517 // Minutes
7518 if ($minunderhours) {
7519 $retstring .= '<br>';
7520 } else {
7521 if ($typehour != 'text') {
7522 $retstring .= '<span class="hideonsmartphone">&nbsp;</span>';
7523 }
7524 }
7525
7526 if ($typehour == 'select' || $typehour == 'textselect') {
7527 $retstring .= '<select class="flat" id="select_' . $prefix . 'min" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . '>';
7528 for ($min = 0; $min <= 55; $min += 5) {
7529 $retstring .= '<option value="' . $min . '"';
7530 if (is_numeric($minSelected) && $minSelected == $min) {
7531 $retstring .= ' selected';
7532 }
7533 $retstring .= '>' . $min . '</option>';
7534 }
7535 $retstring .= "</select>";
7536 } elseif ($typehour == 'text') {
7537 $retstring .= '<input placeholder="' . $langs->trans('MinuteShort') . '" type="number" min="0" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputminute right" value="' . (($minSelected != '') ? ((int) $minSelected) : '') . '">';
7538 }
7539
7540 if ($typehour != 'text') {
7541 $retstring .= ' ' . $langs->trans('MinuteShort');
7542 }
7543
7544 $retstring .= "</span>";
7545
7546 if (!empty($nooutput)) {
7547 return $retstring;
7548 }
7549
7550 print $retstring;
7551
7552 return '';
7553 }
7554
7574 public function selectTickets($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0)
7575 {
7576 global $langs, $conf;
7577
7578 $out = '';
7579
7580 // check parameters
7581 if (is_null($ajaxoptions)) {
7582 $ajaxoptions = array();
7583 }
7584
7585 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7586 $placeholder = '';
7587
7588 if ($selected && empty($selected_input_value)) {
7589 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7590 $tickettmpselect = new Ticket($this->db);
7591 $tickettmpselect->fetch($selected);
7592 $selected_input_value = $tickettmpselect->ref;
7593 unset($tickettmpselect);
7594 }
7595
7596 $urloption = '';
7597 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/ticket/ajax/tickets.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7598
7599 if (empty($hidelabel)) {
7600 $out .= $langs->trans("RefOrLabel") . ' : ';
7601 } elseif ($hidelabel > 1) {
7602 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7603 if ($hidelabel == 2) {
7604 $out .= img_picto($langs->trans("Search"), 'search');
7605 }
7606 }
7607 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7608 if ($hidelabel == 3) {
7609 $out .= img_picto($langs->trans("Search"), 'search');
7610 }
7611 } else {
7612 $out .= $this->selectTicketsList($selected, $htmlname, $filtertype, $limit, '', $status, 0, $showempty, $forcecombo, $morecss);
7613 }
7614
7615 if (empty($nooutput)) {
7616 print $out;
7617 } else {
7618 return $out;
7619 }
7620 return '';
7621 }
7622
7623
7640 public function selectTicketsList($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7641 {
7642 global $langs, $conf;
7643
7644 $out = '';
7645 $outarray = array();
7646
7647 $selectFields = " p.rowid, p.ref, p.message";
7648
7649 $sql = "SELECT ";
7650 $sql .= $selectFields;
7651 $sql .= " FROM " . $this->db->prefix() . "ticket as p";
7652 $sql .= ' WHERE p.entity IN (' . getEntity('ticket') . ')';
7653
7654 // Add criteria on ref/label
7655 if ($filterkey != '') {
7656 $sql .= ' AND (';
7657 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7658 // For natural search
7659 $search_crit = explode(' ', $filterkey);
7660 $i = 0;
7661 if (count($search_crit) > 1) {
7662 $sql .= "(";
7663 }
7664 foreach ($search_crit as $crit) {
7665 if ($i > 0) {
7666 $sql .= " AND ";
7667 }
7668 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.subject LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7669 $sql .= ")";
7670 $i++;
7671 }
7672 if (count($search_crit) > 1) {
7673 $sql .= ")";
7674 }
7675 $sql .= ')';
7676 }
7677
7678 $sql .= $this->db->plimit($limit, 0);
7679
7680 // Build output string
7681 dol_syslog(get_class($this) . "::selectTicketsList search tickets", LOG_DEBUG);
7682 $result = $this->db->query($sql);
7683 if ($result) {
7684 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7685 require_once DOL_DOCUMENT_ROOT . '/core/lib/ticket.lib.php';
7686
7687 $num = $this->db->num_rows($result);
7688
7689 $events = array();
7690
7691 if (!$forcecombo) {
7692 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7693 $out .= ajax_combobox($htmlname, $events, $conf->global->TICKET_USE_SEARCH_TO_SELECT);
7694 }
7695
7696 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7697
7698 $textifempty = '';
7699 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7700 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7701 if (getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7702 if ($showempty && !is_numeric($showempty)) {
7703 $textifempty = $langs->trans($showempty);
7704 } else {
7705 $textifempty .= $langs->trans("All");
7706 }
7707 } else {
7708 if ($showempty && !is_numeric($showempty)) {
7709 $textifempty = $langs->trans($showempty);
7710 }
7711 }
7712 if ($showempty) {
7713 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7714 }
7715
7716 $i = 0;
7717 while ($num && $i < $num) {
7718 $opt = '';
7719 $optJson = array();
7720 $objp = $this->db->fetch_object($result);
7721
7722 $this->constructTicketListOption($objp, $opt, $optJson, $selected, $filterkey);
7723 // Add new entry
7724 // "key" value of json key array is used by jQuery automatically as selected value
7725 // "label" value of json key array is used by jQuery automatically as text for combo box
7726 $out .= $opt;
7727 array_push($outarray, $optJson);
7728
7729 $i++;
7730 }
7731
7732 $out .= '</select>';
7733
7734 $this->db->free($result);
7735
7736 if (empty($outputmode)) {
7737 return $out;
7738 }
7739 return $outarray;
7740 } else {
7741 dol_print_error($this->db);
7742 }
7743
7744 return array();
7745 }
7746
7758 protected function constructTicketListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7759 {
7760 $outkey = '';
7761 $outref = '';
7762 $outtype = '';
7763
7764 $outkey = $objp->rowid;
7765 $outref = $objp->ref;
7766 $outtype = $objp->fk_product_type;
7767
7768 $opt = '<option value="' . $objp->rowid . '"';
7769 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7770 $opt .= '>';
7771 $opt .= $objp->ref;
7772 $objRef = $objp->ref;
7773 if (!empty($filterkey) && $filterkey != '') {
7774 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
7775 }
7776
7777 $opt .= "</option>\n";
7778 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
7779 }
7780
7800 public function selectProjects($selected = '', $htmlname = 'projectid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0)
7801 {
7802 global $langs, $conf;
7803
7804 $out = '';
7805
7806 // check parameters
7807 if (is_null($ajaxoptions)) {
7808 $ajaxoptions = array();
7809 }
7810
7811 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7812 $placeholder = '';
7813
7814 if ($selected && empty($selected_input_value)) {
7815 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7816 $projecttmpselect = new Project($this->db);
7817 $projecttmpselect->fetch($selected);
7818 $selected_input_value = $projecttmpselect->ref;
7819 unset($projecttmpselect);
7820 }
7821
7822 $urloption = '';
7823 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/projet/ajax/projects.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7824
7825 if (empty($hidelabel)) {
7826 $out .= $langs->trans("RefOrLabel") . ' : ';
7827 } elseif ($hidelabel > 1) {
7828 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7829 if ($hidelabel == 2) {
7830 $out .= img_picto($langs->trans("Search"), 'search');
7831 }
7832 }
7833 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7834 if ($hidelabel == 3) {
7835 $out .= img_picto($langs->trans("Search"), 'search');
7836 }
7837 } else {
7838 $out .= $this->selectProjectsList($selected, $htmlname, $filtertype, $limit, '', $status, 0, $showempty, $forcecombo, $morecss);
7839 }
7840
7841 if (empty($nooutput)) {
7842 print $out;
7843 } else {
7844 return $out;
7845 }
7846 return '';
7847 }
7848
7865 public function selectProjectsList($selected = '', $htmlname = 'projectid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7866 {
7867 global $langs, $conf;
7868
7869 $out = '';
7870 $outarray = array();
7871
7872 $selectFields = " p.rowid, p.ref";
7873
7874 $sql = "SELECT ";
7875 $sql .= $selectFields;
7876 $sql .= " FROM " . $this->db->prefix() . "projet as p";
7877 $sql .= ' WHERE p.entity IN (' . getEntity('project') . ')';
7878
7879 // Add criteria on ref/label
7880 if ($filterkey != '') {
7881 $sql .= ' AND (';
7882 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7883 // For natural search
7884 $search_crit = explode(' ', $filterkey);
7885 $i = 0;
7886 if (count($search_crit) > 1) {
7887 $sql .= "(";
7888 }
7889 foreach ($search_crit as $crit) {
7890 if ($i > 0) {
7891 $sql .= " AND ";
7892 }
7893 $sql .= "p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7894 $sql .= "";
7895 $i++;
7896 }
7897 if (count($search_crit) > 1) {
7898 $sql .= ")";
7899 }
7900 $sql .= ')';
7901 }
7902
7903 $sql .= $this->db->plimit($limit, 0);
7904
7905 // Build output string
7906 dol_syslog(get_class($this) . "::selectProjectsList search projects", LOG_DEBUG);
7907 $result = $this->db->query($sql);
7908 if ($result) {
7909 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7910 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
7911
7912 $num = $this->db->num_rows($result);
7913
7914 $events = array();
7915
7916 if (!$forcecombo) {
7917 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7918 $out .= ajax_combobox($htmlname, $events, $conf->global->PROJECT_USE_SEARCH_TO_SELECT);
7919 }
7920
7921 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7922
7923 $textifempty = '';
7924 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7925 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7926 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
7927 if ($showempty && !is_numeric($showempty)) {
7928 $textifempty = $langs->trans($showempty);
7929 } else {
7930 $textifempty .= $langs->trans("All");
7931 }
7932 } else {
7933 if ($showempty && !is_numeric($showempty)) {
7934 $textifempty = $langs->trans($showempty);
7935 }
7936 }
7937 if ($showempty) {
7938 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7939 }
7940
7941 $i = 0;
7942 while ($num && $i < $num) {
7943 $opt = '';
7944 $optJson = array();
7945 $objp = $this->db->fetch_object($result);
7946
7947 $this->constructProjectListOption($objp, $opt, $optJson, $selected, $filterkey);
7948 // Add new entry
7949 // "key" value of json key array is used by jQuery automatically as selected value
7950 // "label" value of json key array is used by jQuery automatically as text for combo box
7951 $out .= $opt;
7952 array_push($outarray, $optJson);
7953
7954 $i++;
7955 }
7956
7957 $out .= '</select>';
7958
7959 $this->db->free($result);
7960
7961 if (empty($outputmode)) {
7962 return $out;
7963 }
7964 return $outarray;
7965 } else {
7966 dol_print_error($this->db);
7967 }
7968
7969 return array();
7970 }
7971
7983 protected function constructProjectListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7984 {
7985 $outkey = '';
7986 $outref = '';
7987 $outtype = '';
7988
7989 $label = $objp->label;
7990
7991 $outkey = $objp->rowid;
7992 $outref = $objp->ref;
7993 $outlabel = $objp->label;
7994 $outtype = $objp->fk_product_type;
7995
7996 $opt = '<option value="' . $objp->rowid . '"';
7997 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7998 $opt .= '>';
7999 $opt .= $objp->ref;
8000 $objRef = $objp->ref;
8001 if (!empty($filterkey) && $filterkey != '') {
8002 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
8003 }
8004
8005 $opt .= "</option>\n";
8006 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
8007 }
8008
8009
8029 public function selectMembers($selected = '', $htmlname = 'adherentid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0)
8030 {
8031 global $langs, $conf;
8032
8033 $out = '';
8034
8035 // check parameters
8036 if (is_null($ajaxoptions)) {
8037 $ajaxoptions = array();
8038 }
8039
8040 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
8041 $placeholder = '';
8042
8043 if ($selected && empty($selected_input_value)) {
8044 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
8045 $adherenttmpselect = new Adherent($this->db);
8046 $adherenttmpselect->fetch($selected);
8047 $selected_input_value = $adherenttmpselect->ref;
8048 unset($adherenttmpselect);
8049 }
8050
8051 $urloption = '';
8052
8053 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/adherents/ajax/adherents.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
8054
8055 if (empty($hidelabel)) {
8056 $out .= $langs->trans("RefOrLabel") . ' : ';
8057 } elseif ($hidelabel > 1) {
8058 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
8059 if ($hidelabel == 2) {
8060 $out .= img_picto($langs->trans("Search"), 'search');
8061 }
8062 }
8063 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
8064 if ($hidelabel == 3) {
8065 $out .= img_picto($langs->trans("Search"), 'search');
8066 }
8067 } else {
8068 $filterkey = '';
8069
8070 $out .= $this->selectMembersList($selected, $htmlname, $filtertype, $limit, $filterkey, $status, 0, $showempty, $forcecombo, $morecss);
8071 }
8072
8073 if (empty($nooutput)) {
8074 print $out;
8075 } else {
8076 return $out;
8077 }
8078 return '';
8079 }
8080
8097 public function selectMembersList($selected = '', $htmlname = 'adherentid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
8098 {
8099 global $langs, $conf;
8100
8101 $out = '';
8102 $outarray = array();
8103
8104 $selectFields = " p.rowid, p.ref, p.firstname, p.lastname, p.fk_adherent_type";
8105
8106 $sql = "SELECT ";
8107 $sql .= $selectFields;
8108 $sql .= " FROM " . $this->db->prefix() . "adherent as p";
8109 $sql .= ' WHERE p.entity IN (' . getEntity('adherent') . ')';
8110
8111 // Add criteria on ref/label
8112 if ($filterkey != '') {
8113 $sql .= ' AND (';
8114 $prefix = !getDolGlobalString('MEMBER_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
8115 // For natural search
8116 $search_crit = explode(' ', $filterkey);
8117 $i = 0;
8118 if (count($search_crit) > 1) {
8119 $sql .= "(";
8120 }
8121 foreach ($search_crit as $crit) {
8122 if ($i > 0) {
8123 $sql .= " AND ";
8124 }
8125 $sql .= "(p.firstname LIKE '" . $this->db->escape($prefix . $crit) . "%'";
8126 $sql .= " OR p.lastname LIKE '" . $this->db->escape($prefix . $crit) . "%')";
8127 $i++;
8128 }
8129 if (count($search_crit) > 1) {
8130 $sql .= ")";
8131 }
8132 $sql .= ')';
8133 }
8134 if ($status != -1) {
8135 $sql .= ' AND statut = ' . ((int) $status);
8136 }
8137 $sql .= $this->db->plimit($limit, 0);
8138
8139 // Build output string
8140 dol_syslog(get_class($this) . "::selectMembersList search adherents", LOG_DEBUG);
8141 $result = $this->db->query($sql);
8142 if ($result) {
8143 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
8144 require_once DOL_DOCUMENT_ROOT . '/core/lib/member.lib.php';
8145
8146 $num = $this->db->num_rows($result);
8147
8148 $events = array();
8149
8150 if (!$forcecombo) {
8151 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8152 $out .= ajax_combobox($htmlname, $events, getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT') ? $conf->global->PROJECT_USE_SEARCH_TO_SELECT : '');
8153 }
8154
8155 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
8156
8157 $textifempty = '';
8158 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
8159 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8160 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
8161 if ($showempty && !is_numeric($showempty)) {
8162 $textifempty = $langs->trans($showempty);
8163 } else {
8164 $textifempty .= $langs->trans("All");
8165 }
8166 } else {
8167 if ($showempty && !is_numeric($showempty)) {
8168 $textifempty = $langs->trans($showempty);
8169 }
8170 }
8171 if ($showempty) {
8172 $out .= '<option value="-1" selected>' . $textifempty . '</option>';
8173 }
8174
8175 $i = 0;
8176 while ($num && $i < $num) {
8177 $opt = '';
8178 $optJson = array();
8179 $objp = $this->db->fetch_object($result);
8180
8181 $this->constructMemberListOption($objp, $opt, $optJson, $selected, $filterkey);
8182
8183 // Add new entry
8184 // "key" value of json key array is used by jQuery automatically as selected value
8185 // "label" value of json key array is used by jQuery automatically as text for combo box
8186 $out .= $opt;
8187 array_push($outarray, $optJson);
8188
8189 $i++;
8190 }
8191
8192 $out .= '</select>';
8193
8194 $this->db->free($result);
8195
8196 if (empty($outputmode)) {
8197 return $out;
8198 }
8199 return $outarray;
8200 } else {
8201 dol_print_error($this->db);
8202 }
8203
8204 return array();
8205 }
8206
8218 protected function constructMemberListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
8219 {
8220 $outkey = '';
8221 $outlabel = '';
8222 $outtype = '';
8223
8224 $outkey = $objp->rowid;
8225 $outlabel = dolGetFirstLastname($objp->firstname, $objp->lastname);
8226 $outtype = $objp->fk_adherent_type;
8227
8228 $opt = '<option value="' . $objp->rowid . '"';
8229 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
8230 $opt .= '>';
8231 if (!empty($filterkey) && $filterkey != '') {
8232 $outlabel = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $outlabel, 1);
8233 }
8234 $opt .= $outlabel;
8235 $opt .= "</option>\n";
8236
8237 $optJson = array('key' => $outkey, 'value' => $outlabel, 'type' => $outtype);
8238 }
8239
8260 public function selectForForms($objectdesc, $htmlname, $preSelectedValue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '', $objectfield = '')
8261 {
8262 global $conf, $extrafields, $user;
8263
8264 // Example of common usage for a link to a thirdparty
8265
8266 // We got this in a modulebuilder form of "MyObject" of module "mymodule".
8267 // ->fields is array( ... "fk_soc" => array("type"=>"integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))" ...)
8268 // $objectdesc = 'Societe'
8269 // $objectfield = 'myobject@mymodule:fk_soc' ('fk_soc' is code to retrieve myobject->fields['fk_soc'])
8270
8271 // We got this when showing an extrafields on resource that is a link to societe
8272 // extrafields 'link_to_societe' of Resource is 'link' to 'Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))" ...)'
8273 // $objectdesc = 'Societe'
8274 // $objectfield = 'resource:options_link_to_societe'
8275
8276 // With old usage:
8277 // $objectdesc = 'Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))'
8278 // $objectfield = ''
8279
8280 //var_dump($objectdesc.' '.$objectfield);
8281 //debug_print_backtrace();
8282
8283 $objectdescorig = $objectdesc;
8284 $objecttmp = null;
8285 $InfoFieldList = array();
8286 $classname = '';
8287 $filter = ''; // Ensure filter has value (for static analysis)
8288 $sortfield = ''; // Ensure filter has value (for static analysis)
8289
8290 if ($objectfield) { // We must retrieve the objectdesc from the field or extrafield
8291 // Example: $objectfield = 'product:options_package' or 'myobject@mymodule:options_myfield'
8292 $tmparray = explode(':', $objectfield);
8293
8294 // Get instance of object from $element
8295 $objectforfieldstmp = fetchObjectByElement(0, strtolower($tmparray[0]));
8296
8297 if (is_object($objectforfieldstmp)) {
8298 $objectdesc = '';
8299
8300 $reg = array();
8301 if (preg_match('/^options_(.*)$/', $tmparray[1], $reg)) {
8302 // For a property in extrafields
8303 $key = $reg[1];
8304 // fetch optionals attributes and labels
8305 $extrafields->fetch_name_optionals_label($objectforfieldstmp->table_element);
8306
8307 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key]) && $extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key] == 'link') {
8308 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options'])) {
8309 $tmpextrafields = array_keys($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options']);
8310 $objectdesc = $tmpextrafields[0];
8311 }
8312 }
8313 } else {
8314 // For a property in ->fields
8315 if (array_key_exists($tmparray[1], $objectforfieldstmp->fields)) {
8316 $objectdesc = $objectforfieldstmp->fields[$tmparray[1]]['type'];
8317 $objectdesc = preg_replace('/^integer[^:]*:/', '', $objectdesc);
8318 }
8319 }
8320 }
8321 }
8322
8323 if ($objectdesc) {
8324 // Example of value for $objectdesc:
8325 // Bom:bom/class/bom.class.php:0:t.status=1
8326 // Bom:bom/class/bom.class.php:0:t.status=1:ref
8327 // Bom:bom/class/bom.class.php:0:(t.status:=:1) OR (t.field2:=:2):ref
8328 $InfoFieldList = explode(":", $objectdesc, 4);
8329 $vartmp = (empty($InfoFieldList[3]) ? '' : $InfoFieldList[3]);
8330 $reg = array();
8331 if (preg_match('/^.*:(\w*)$/', $vartmp, $reg)) {
8332 $InfoFieldList[4] = $reg[1]; // take the sort field
8333 }
8334 $InfoFieldList[3] = preg_replace('/:\w*$/', '', $vartmp); // take the filter field
8335
8336 $classname = $InfoFieldList[0];
8337 $classpath = empty($InfoFieldList[1]) ? '' : $InfoFieldList[1];
8338 //$addcreatebuttonornot = empty($InfoFieldList[2]) ? 0 : $InfoFieldList[2];
8339 $filter = empty($InfoFieldList[3]) ? '' : $InfoFieldList[3];
8340 $sortfield = empty($InfoFieldList[4]) ? '' : $InfoFieldList[4];
8341
8342 // Load object according to $id and $element
8343 $objecttmp = fetchObjectByElement(0, strtolower($InfoFieldList[0]));
8344
8345 // Fallback to another solution to get $objecttmp
8346 if (empty($objecttmp) && !empty($classpath)) {
8347 dol_include_once($classpath);
8348
8349 if ($classname && class_exists($classname)) {
8350 $objecttmp = new $classname($this->db);
8351 }
8352 }
8353 }
8354
8355 // Make some replacement in $filter. May not be used if we used the ajax mode with $objectfield. In such a case
8356 // we propagate the $objectfield and not the filter and replacement is done by the ajax/selectobject.php component.
8357 $sharedentities = (is_object($objecttmp) && property_exists($objecttmp, 'element')) ? getEntity($objecttmp->element) : strtolower($classname);
8358 $filter = str_replace(
8359 array('__ENTITY__', '__SHARED_ENTITIES__', '__USER_ID__'),
8360 array($conf->entity, $sharedentities, $user->id),
8361 $filter
8362 );
8363
8364 if (!is_object($objecttmp)) {
8365 dol_syslog('selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc, LOG_WARNING);
8366 return 'selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc;
8367 }
8368 '@phan-var-force CommonObject $objecttmp';
8369
8370 //var_dump($filter);
8371 $prefixforautocompletemode = $objecttmp->element;
8372 if ($prefixforautocompletemode == 'societe') {
8373 $prefixforautocompletemode = 'company';
8374 }
8375 if ($prefixforautocompletemode == 'product') {
8376 $prefixforautocompletemode = 'produit';
8377 }
8378 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8379
8380 dol_syslog(get_class($this) . "::selectForForms filter=" . $filter, LOG_DEBUG);
8381
8382 // Generate the combo HTML component
8383 $out = '';
8384 if (!empty($conf->use_javascript_ajax) && getDolGlobalString($confkeyforautocompletemode) && !$forcecombo) {
8385 // No immediate load of all database
8386 $placeholder = '';
8387
8388 if ($preSelectedValue && empty($selected_input_value)) {
8389 $objecttmp->fetch($preSelectedValue);
8390 $selected_input_value = ($prefixforautocompletemode == 'company' ? $objecttmp->name : $objecttmp->ref);
8391
8392 $oldValueForShowOnCombobox = 0;
8393 foreach ($objecttmp->fields as $fieldK => $fielV) {
8394 if (!array_key_exists('showoncombobox', $fielV) || !$fielV['showoncombobox'] || empty($objecttmp->$fieldK)) {
8395 continue;
8396 }
8397
8398 if (!$oldValueForShowOnCombobox) {
8399 $selected_input_value = '';
8400 }
8401
8402 $selected_input_value .= $oldValueForShowOnCombobox ? ' - ' : '';
8403 $selected_input_value .= $objecttmp->$fieldK;
8404 $oldValueForShowOnCombobox = empty($fielV['showoncombobox']) ? 0 : $fielV['showoncombobox'];
8405 }
8406 }
8407
8408 // Set url and param to call to get json of the search results
8409 $urlforajaxcall = DOL_URL_ROOT . '/core/ajax/selectobject.php';
8410 $urloption = 'htmlname=' . urlencode($htmlname) . '&outjson=1&objectdesc=' . urlencode($objectdescorig) . '&objectfield='.urlencode($objectfield) . ($sortfield ? '&sortfield=' . urlencode($sortfield) : '');
8411
8412 // Activate the auto complete using ajax call.
8413 $out .= ajax_autocompleter($preSelectedValue, $htmlname, $urlforajaxcall, $urloption, getDolGlobalString($confkeyforautocompletemode), 0);
8414 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
8415 $out .= '<input type="text" class="' . $morecss . '"' . ($disabled ? ' disabled="disabled"' : '') . ' name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '') . ' />';
8416 } else {
8417 // Immediate load of table record.
8418 $out .= $this->selectForFormsList($objecttmp, $htmlname, $preSelectedValue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, 0, $disabled, $sortfield, $filter);
8419 }
8420
8421 return $out;
8422 }
8423
8424
8445 public function selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $outputmode = 0, $disabled = 0, $sortfield = '', $filter = '')
8446 {
8447 global $langs, $user, $hookmanager;
8448
8449 //print "$htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, $outputmode, $disabled";
8450
8451 $prefixforautocompletemode = $objecttmp->element;
8452 if ($prefixforautocompletemode == 'societe') {
8453 $prefixforautocompletemode = 'company';
8454 }
8455 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8456
8457 if (!empty($objecttmp->fields)) { // For object that declare it, it is better to use declared fields (like societe, contact, ...)
8458 $tmpfieldstoshow = '';
8459 foreach ($objecttmp->fields as $key => $val) {
8460 if (! (int) dol_eval($val['enabled'], 1, 1, '1')) {
8461 continue;
8462 }
8463 if (!empty($val['showoncombobox'])) {
8464 $tmpfieldstoshow .= ($tmpfieldstoshow ? ',' : '') . 't.' . $key;
8465 }
8466 }
8467 if ($tmpfieldstoshow) {
8468 $fieldstoshow = $tmpfieldstoshow;
8469 }
8470 } else {
8471 // For backward compatibility
8472 $objecttmp->fields['ref'] = array('type' => 'varchar(30)', 'label' => 'Ref', 'showoncombobox' => 1);
8473 }
8474
8475 if (empty($fieldstoshow)) {
8476 if (isset($objecttmp->fields['ref'])) {
8477 $fieldstoshow = 't.ref';
8478 } else {
8479 $langs->load("errors");
8480 $this->error = $langs->trans("ErrorNoFieldWithAttributeShowoncombobox");
8481 return $langs->trans('ErrorNoFieldWithAttributeShowoncombobox');
8482 }
8483 }
8484
8485 $out = '';
8486 $outarray = array();
8487 $tmparray = array();
8488
8489 $num = 0;
8490
8491 // Search data
8492 $sql = "SELECT t.rowid, " . $fieldstoshow . " FROM " . $this->db->prefix() . $objecttmp->table_element . " as t";
8493 if (!empty($objecttmp->isextrafieldmanaged)) {
8494 $sql .= " LEFT JOIN " . $this->db->prefix() . $objecttmp->table_element . "_extrafields as e ON t.rowid=e.fk_object";
8495 }
8496 if (isset($objecttmp->ismultientitymanaged)) {
8497 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8498 $tmparray = explode('@', $objecttmp->ismultientitymanaged);
8499 $sql .= " INNER JOIN " . $this->db->prefix() . $tmparray[1] . " as parenttable ON parenttable.rowid = t." . $tmparray[0];
8500 }
8501 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8502 if (!$user->hasRight('societe', 'client', 'voir')) {
8503 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
8504 }
8505 }
8506 }
8507
8508 // Add where from hooks
8509 $parameters = array(
8510 'object' => $objecttmp,
8511 'htmlname' => $htmlname,
8512 'filter' => $filter,
8513 'searchkey' => $searchkey
8514 );
8515
8516 $reshook = $hookmanager->executeHooks('selectForFormsListWhere', $parameters); // Note that $action and $object may have been modified by hook
8517 if (!empty($hookmanager->resPrint)) {
8518 $sql .= $hookmanager->resPrint;
8519 } else {
8520 $sql .= " WHERE 1=1";
8521 if (isset($objecttmp->ismultientitymanaged)) {
8522 if ($objecttmp->ismultientitymanaged == 1) {
8523 $sql .= " AND t.entity IN (" . getEntity($objecttmp->table_element) . ")";
8524 }
8525 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8526 $sql .= " AND parenttable.entity = t." . $tmparray[0];
8527 }
8528 if ($objecttmp->ismultientitymanaged == 1 && !empty($user->socid)) {
8529 if ($objecttmp->element == 'societe') {
8530 $sql .= " AND t.rowid = " . ((int) $user->socid);
8531 } else {
8532 $sql .= " AND t.fk_soc = " . ((int) $user->socid);
8533 }
8534 }
8535 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8536 if (!$user->hasRight('societe', 'client', 'voir')) {
8537 $sql .= " AND t.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
8538 }
8539 }
8540 }
8541 if ($searchkey != '') {
8542 $sql .= natural_search(explode(',', $fieldstoshow), $searchkey);
8543 }
8544
8545 if ($filter) { // Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
8546 $errormessage = '';
8547 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
8548 if ($errormessage) {
8549 return 'Error forging a SQL request from an universal criteria: ' . $errormessage;
8550 }
8551 }
8552 }
8553 $sql .= $this->db->order($sortfield ? $sortfield : $fieldstoshow, "ASC");
8554 //$sql.=$this->db->plimit($limit, 0);
8555 //print $sql;
8556
8557 // Build output string
8558 $resql = $this->db->query($sql);
8559 if ($resql) {
8560 // Construct $out and $outarray
8561 $out .= '<select id="' . $htmlname . '" class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ($moreparams ? ' ' . $moreparams : '') . ' name="' . $htmlname . '">' . "\n";
8562
8563 // Warning: Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'. Seems it is no more true with selec2 v4
8564 $textifempty = '&nbsp;';
8565
8566 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8567 if (getDolGlobalInt($confkeyforautocompletemode)) {
8568 if ($showempty && !is_numeric($showempty)) {
8569 $textifempty = $langs->trans($showempty);
8570 } else {
8571 $textifempty .= $langs->trans("All");
8572 }
8573 }
8574 if ($showempty) {
8575 $out .= '<option value="-1">' . $textifempty . '</option>' . "\n";
8576 }
8577
8578 $num = $this->db->num_rows($resql);
8579 $i = 0;
8580 if ($num) {
8581 while ($i < $num) {
8582 $obj = $this->db->fetch_object($resql);
8583 $label = '';
8584 $labelhtml = '';
8585 $tmparray = explode(',', $fieldstoshow);
8586 $oldvalueforshowoncombobox = 0;
8587 foreach ($tmparray as $key => $val) {
8588 $val = preg_replace('/t\./', '', $val);
8589 $label .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8590 $labelhtml .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8591 $label .= $obj->$val;
8592 $labelhtml .= $obj->$val;
8593
8594 $oldvalueforshowoncombobox = empty($objecttmp->fields[$val]['showoncombobox']) ? 0 : $objecttmp->fields[$val]['showoncombobox'];
8595 }
8596 if (empty($outputmode)) {
8597 if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid) {
8598 $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>';
8599 } else {
8600 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
8601 }
8602 } else {
8603 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label));
8604 }
8605
8606 $i++;
8607 if (($i % 10) == 0) {
8608 $out .= "\n";
8609 }
8610 }
8611 }
8612
8613 $out .= '</select>' . "\n";
8614
8615 if (!$forcecombo) {
8616 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8617 $out .= ajax_combobox($htmlname, array(), getDolGlobalInt($confkeyforautocompletemode, 0));
8618 }
8619 } else {
8620 dol_print_error($this->db);
8621 }
8622
8623 $this->result = array('nbofelement' => $num);
8624
8625 if ($outputmode) {
8626 return $outarray;
8627 }
8628 return $out;
8629 }
8630
8631
8655 public static function selectarray($htmlname, $array, $id = '', $show_empty = 0, $key_in_label = 0, $value_as_key = 0, $moreparam = '', $translate = 0, $maxlen = 0, $disabled = 0, $sort = '', $morecss = 'minwidth75', $addjscombo = 1, $moreparamonempty = '', $disablebademail = 0, $nohtmlescape = 0)
8656 {
8657 global $conf, $langs;
8658
8659 // Do we want a multiselect ?
8660 //$jsbeautify = 0;
8661 //if (preg_match('/^multi/',$htmlname)) $jsbeautify = 1;
8662 $jsbeautify = 1;
8663
8664 if ($value_as_key) {
8665 $array = array_combine($array, $array);
8666 }
8667
8668 '@phan-var-force array{label:string,data-html:string,disable?:int<0,1>,css?:string} $array'; // Array combine breaks information
8669
8670 $out = '';
8671
8672 if ($addjscombo < 0) {
8673 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8674 $addjscombo = 1;
8675 } else {
8676 $addjscombo = 0;
8677 }
8678 }
8679 $idname = str_replace(array('[', ']'), array('', ''), $htmlname);
8680 $out .= '<select id="' . preg_replace('/^\./', '', $idname) . '" ' . ($disabled ? 'disabled="disabled" ' : '') . 'class="flat ' . (preg_replace('/^\./', '', $htmlname)) . ($morecss ? ' ' . $morecss : '') . ' selectformat"';
8681 $out .= ' name="' . preg_replace('/^\./', '', $htmlname) . '" ' . ($moreparam ? $moreparam : '');
8682 $out .= '>'."\n";
8683
8684 if ($show_empty) {
8685 $textforempty = ' ';
8686 if (!empty($conf->use_javascript_ajax)) {
8687 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
8688 }
8689 if (!is_numeric($show_empty)) {
8690 $textforempty = $show_empty;
8691 }
8692 $out .= '<option class="optiongrey" ' . ($moreparamonempty ? $moreparamonempty . ' ' : '') . 'value="' . (((int) $show_empty) < 0 ? $show_empty : -1) . '"' . ($id == $show_empty ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
8693 }
8694 if (is_array($array)) {
8695 // Translate
8696 if ($translate) {
8697 foreach ($array as $key => $value) {
8698 if (!is_array($value)) {
8699 $array[$key] = $langs->trans($value);
8700 } else {
8701 $array[$key]['label'] = $langs->trans($value['label']);
8702 }
8703 }
8704 }
8705 // Sort
8706 if ($sort == 'ASC') {
8707 asort($array);
8708 } elseif ($sort == 'DESC') {
8709 arsort($array);
8710 }
8711
8712 foreach ($array as $key => $tmpvalue) {
8713 if (is_array($tmpvalue)) {
8714 $value = $tmpvalue['label'];
8715 //$valuehtml = empty($tmpvalue['data-html']) ? $value : $tmpvalue['data-html'];
8716 $disabled = empty($tmpvalue['disabled']) ? '' : ' disabled';
8717 $style = empty($tmpvalue['css']) ? '' : ' class="' . $tmpvalue['css'] . '"';
8718 } else {
8719 $value = $tmpvalue;
8720 //$valuehtml = $tmpvalue;
8721 $disabled = '';
8722 $style = '';
8723 }
8724 if (!empty($disablebademail)) {
8725 if (($disablebademail == 1 && !preg_match('/&lt;.+@.+&gt;/', $value))
8726 || ($disablebademail == 2 && preg_match('/---/', $value))) {
8727 $disabled = ' disabled';
8728 $style = ' class="warning"';
8729 }
8730 }
8731 if ($key_in_label) {
8732 if (empty($nohtmlescape)) {
8733 $selectOptionValue = dol_escape_htmltag($key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value));
8734 } else {
8735 $selectOptionValue = $key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value);
8736 }
8737 } else {
8738 if (empty($nohtmlescape)) {
8739 $selectOptionValue = dol_escape_htmltag($maxlen ? dol_trunc($value, $maxlen) : $value);
8740 } else {
8741 $selectOptionValue = $maxlen ? dol_trunc($value, $maxlen) : $value;
8742 }
8743 if ($value == '' || $value == '-') {
8744 $selectOptionValue = '&nbsp;';
8745 }
8746 }
8747 $out .= '<option value="' . $key . '"';
8748 $out .= $style . $disabled;
8749 if (is_array($id)) {
8750 if (in_array($key, $id) && !$disabled) {
8751 $out .= ' selected'; // To preselect a value
8752 }
8753 } else {
8754 $id = (string) $id; // if $id = 0, then $id = '0'
8755 if ($id != '' && (($id == (string) $key) || ($id == 'ifone' && count($array) == 1)) && !$disabled) {
8756 $out .= ' selected'; // To preselect a value
8757 }
8758 }
8759 if (!empty($nohtmlescape)) { // deprecated. Use instead the key 'data-html' into input $array, managed at next step to use HTML content.
8760 $out .= ' data-html="' . dol_escape_htmltag($selectOptionValue) . '"';
8761 }
8762
8763 if (is_array($tmpvalue)) {
8764 foreach ($tmpvalue as $keyforvalue => $valueforvalue) {
8765 if (preg_match('/^data-/', $keyforvalue)) { // The best solution if you want to use HTML values into the list is to use data-html.
8766 $out .= ' '.dol_escape_htmltag($keyforvalue).'="'.dol_escape_htmltag($valueforvalue).'"';
8767 }
8768 }
8769 }
8770 $out .= '>';
8771 $out .= $selectOptionValue;
8772 $out .= "</option>\n";
8773 }
8774 }
8775 $out .= "</select>";
8776
8777 // Add code for jquery to use multiselect
8778 if ($addjscombo && $jsbeautify) {
8779 // Enhance with select2
8780 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8781 $out .= ajax_combobox($idname, array(), 0, 0, 'resolve', (((int) $show_empty) < 0 ? (string) $show_empty : '-1'), $morecss);
8782 }
8783
8784 return $out;
8785 }
8786
8805 public static function selectArrayAjax($htmlname, $url, $id = '', $moreparam = '', $moreparamtourl = '', $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0)
8806 {
8807 global $conf, $langs;
8808 global $delayedhtmlcontent; // Will be used later outside of this function
8809
8810 // TODO Use an internal dolibarr component instead of select2
8811 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8812 return '';
8813 }
8814
8815 $out = '<select type="text" class="' . $htmlname . ($morecss ? ' ' . $morecss : '') . '" ' . ($moreparam ? $moreparam . ' ' : '') . 'name="' . $htmlname . '"></select>';
8816
8817 $outdelayed = '';
8818 if (!empty($conf->use_javascript_ajax)) {
8819 $tmpplugin = 'select2';
8820 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8821 <script nonce="' . getNonce() . '">
8822 $(document).ready(function () {
8823
8824 ' . ($callurlonselect ? 'var saveRemoteData = [];' : '') . '
8825
8826 $(".' . $htmlname . '").select2({
8827 ajax: {
8828 dir: "ltr",
8829 url: "' . $url . '",
8830 dataType: \'json\',
8831 delay: 250,
8832 data: function (params) {
8833 return {
8834 q: params.term, // search term
8835 page: params.page
8836 }
8837 },
8838 processResults: function (data) {
8839 // parse the results into the format expected by Select2.
8840 // since we are using custom formatting functions we do not need to alter the remote JSON data
8841 //console.log(data);
8842 saveRemoteData = data;
8843 /* format json result for select2 */
8844 result = []
8845 $.each( data, function( key, value ) {
8846 result.push({id: key, text: value.text});
8847 });
8848 //return {results:[{id:\'none\', text:\'aa\'}, {id:\'rrr\', text:\'Red\'},{id:\'bbb\', text:\'Search a into projects\'}], more:false}
8849 //console.log(result);
8850 return {results: result, more: false}
8851 },
8852 cache: true
8853 },
8854 language: select2arrayoflanguage,
8855 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8856 placeholder: "' . dol_escape_js($placeholder) . '",
8857 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8858 minimumInputLength: ' . ((int) $minimumInputLength) . ',
8859 formatResult: function (result, container, query, escapeMarkup) {
8860 return escapeMarkup(result.text);
8861 },
8862 });
8863
8864 ' . ($callurlonselect ? '
8865 /* Code to execute a GET when we select a value */
8866 $(".' . $htmlname . '").change(function() {
8867 var selected = $(".' . $htmlname . '").val();
8868 console.log("We select in selectArrayAjax the entry "+selected)
8869 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8870 $.each( saveRemoteData, function( key, value ) {
8871 if (key == selected)
8872 {
8873 console.log("selectArrayAjax - Do a redirect to "+value.url)
8874 location.assign(value.url);
8875 }
8876 });
8877 });' : '') . '
8878
8879 });
8880 </script>';
8881 }
8882
8883 if ($acceptdelayedhtml) {
8884 $delayedhtmlcontent .= $outdelayed;
8885 } else {
8886 $out .= $outdelayed;
8887 }
8888 return $out;
8889 }
8890
8910 public static function selectArrayFilter($htmlname, $array, $id = '', $moreparam = '', $disableFiltering = 0, $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0, $textfortitle = '')
8911 {
8912 global $conf, $langs;
8913 global $delayedhtmlcontent; // Will be used later outside of this function
8914
8915 // TODO Use an internal dolibarr component instead of select2
8916 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8917 return '';
8918 }
8919
8920 $out = '<select type="text"'.($textfortitle ? ' title="'.dol_escape_htmltag($textfortitle).'"' : '').' id="'.$htmlname.'" class="'.$htmlname.($morecss ? ' ' . $morecss : '').'"'.($moreparam ? ' '.$moreparam : '').' name="'.$htmlname.'"><option></option></select>';
8921
8922 $formattedarrayresult = array();
8923
8924 foreach ($array as $key => $value) {
8925 $o = new stdClass();
8926 $o->id = $key;
8927 $o->text = $value['text'];
8928 $o->url = $value['url'];
8929 $formattedarrayresult[] = $o;
8930 }
8931
8932 $outdelayed = '';
8933 if (!empty($conf->use_javascript_ajax)) {
8934 $tmpplugin = 'select2';
8935 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8936 <script nonce="' . getNonce() . '">
8937 $(document).ready(function () {
8938 var data = ' . json_encode($formattedarrayresult) . ';
8939
8940 ' . ($callurlonselect ? 'var saveRemoteData = ' . json_encode($array) . ';' : '') . '
8941
8942 $(".' . $htmlname . '").select2({
8943 data: data,
8944 language: select2arrayoflanguage,
8945 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8946 placeholder: "' . dol_escape_js($placeholder) . '",
8947 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8948 minimumInputLength: ' . $minimumInputLength . ',
8949 formatResult: function (result, container, query, escapeMarkup) {
8950 return escapeMarkup(result.text);
8951 },
8952 matcher: function (params, data) {
8953
8954 if(! data.id) return null;';
8955
8956 if ($callurlonselect) {
8957 // We forge the url with 'sall='
8958 $outdelayed .= '
8959
8960 var urlBase = data.url;
8961 var separ = urlBase.indexOf("?") >= 0 ? "&" : "?";
8962 /* console.log("params.term="+params.term); */
8963 /* console.log("params.term encoded="+encodeURIComponent(params.term)); */
8964 saveRemoteData[data.id].url = urlBase + separ + "search_all=" + encodeURIComponent(params.term.replace(/\"/g, ""));';
8965 }
8966
8967 if (!$disableFiltering) {
8968 $outdelayed .= '
8969
8970 if(data.text.match(new RegExp(params.term))) {
8971 return data;
8972 }
8973
8974 return null;';
8975 } else {
8976 $outdelayed .= '
8977
8978 return data;';
8979 }
8980
8981 $outdelayed .= '
8982 }
8983 });
8984
8985 ' . ($callurlonselect ? '
8986 /* Code to execute a GET when we select a value */
8987 $(".' . $htmlname . '").change(function() {
8988 var selected = $(".' . $htmlname . '").val();
8989 console.log("We select "+selected)
8990
8991 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8992 $.each( saveRemoteData, function( key, value ) {
8993 if (key == selected)
8994 {
8995 console.log("selectArrayFilter - Do a redirect to "+value.url)
8996 location.assign(value.url);
8997 }
8998 });
8999 });' : '') . '
9000
9001 });
9002 </script>';
9003 }
9004
9005 if ($acceptdelayedhtml) {
9006 $delayedhtmlcontent .= $outdelayed;
9007 } else {
9008 $out .= $outdelayed;
9009 }
9010 return $out;
9011 }
9012
9031 public static function multiselectarray($htmlname, $array, $selected = array(), $key_in_label = 0, $value_as_key = 0, $morecss = '', $translate = 0, $width = 0, $moreattrib = '', $elemtype = '', $placeholder = '', $addjscombo = -1)
9032 {
9033 global $conf, $langs;
9034
9035 $out = '';
9036
9037 if ($addjscombo < 0) {
9038 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
9039 $addjscombo = 1;
9040 } else {
9041 $addjscombo = 0;
9042 }
9043 }
9044
9045 $useenhancedmultiselect = 0;
9046 if (!empty($conf->use_javascript_ajax) && !defined('MAIN_DO_NOT_USE_JQUERY_MULTISELECT') && (getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT'))) {
9047 if ($addjscombo) {
9048 $useenhancedmultiselect = 1; // Use the js multiselect in one line. Possible only if $addjscombo not 0.
9049 }
9050 }
9051
9052 // We need a hidden field because when using the multiselect, if we unselect all, there is no
9053 // variable submitted at all, so no way to make a difference between variable not submitted and variable
9054 // submitted to nothing.
9055 $out .= '<input type="hidden" name="'.$htmlname.'_multiselect" value="1">';
9056 // Output select component
9057 $out .= '<select id="' . $htmlname . '" class="multiselect' . ($useenhancedmultiselect ? ' multiselectononeline' : '') . ($morecss ? ' ' . $morecss : '') . '" multiple name="' . $htmlname . '[]"' . ($moreattrib ? ' ' . $moreattrib : '') . ($width ? ' style="width: ' . (preg_match('/%/', (string) $width) ? $width : $width . 'px') . '"' : '') . '>' . "\n";
9058 if (is_array($array) && !empty($array)) {
9059 if ($value_as_key) {
9060 $array = array_combine($array, $array);
9061 }
9062
9063 if (!empty($array)) {
9064 foreach ($array as $key => $value) {
9065 $tmpkey = $key;
9066 $tmpvalue = $value;
9067 $tmpcolor = '';
9068 $tmppicto = '';
9069 $tmplabelhtml = '';
9070 if (is_array($value) && array_key_exists('id', $value) && array_key_exists('label', $value)) {
9071 $tmpkey = $value['id'];
9072 $tmpvalue = empty($value['label']) ? '' : $value['label'];
9073 $tmpcolor = empty($value['color']) ? '' : $value['color'];
9074 $tmppicto = empty($value['picto']) ? '' : $value['picto'];
9075 $tmplabelhtml = empty($value['labelhtml']) ? (empty($value['data-html']) ? '' : $value['data-html']): $value['labelhtml'];
9076 }
9077 $newval = ($translate ? $langs->trans($tmpvalue) : $tmpvalue);
9078 $newval = ($key_in_label ? $tmpkey . ' - ' . $newval : $newval);
9079
9080 $out .= '<option value="' . $tmpkey . '"';
9081 if (is_array($selected) && !empty($selected) && in_array((string) $tmpkey, $selected) && ((string) $tmpkey != '')) {
9082 $out .= ' selected';
9083 }
9084 if (!empty($tmplabelhtml)) {
9085 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
9086 } else {
9087 $tmplabelhtml = ($tmppicto ? img_picto('', $tmppicto, 'class="pictofixedwidth" style="color: #' . $tmpcolor . '"') : '') . $newval;
9088 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
9089 }
9090 $out .= '>';
9091 $out .= dol_htmlentitiesbr($newval);
9092 $out .= '</option>' . "\n";
9093 }
9094 }
9095 }
9096 $out .= '</select>' . "\n";
9097
9098 // Add code for jquery to use multiselect
9099 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT')) {
9100 $out .= "\n" . '<!-- JS CODE TO ENABLE select for id ' . $htmlname . ', addjscombo=' . $addjscombo . ' -->';
9101 $out .= "\n" . '<script nonce="' . getNonce() . '">' . "\n";
9102 if ($addjscombo == 1) {
9103 $tmpplugin = !getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT;
9104 $out .= 'function formatResult(record, container) {' . "\n";
9105 // If property data-html set, we decode html entities and use this.
9106 // Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, '', 0, 1) when building the select option.
9107 $out .= ' if ($(record.element).attr("data-html") != undefined && typeof htmlEntityDecodeJs === "function") {';
9108 //$out .= ' console.log("aaa");';
9109 $out .= ' return htmlEntityDecodeJs($(record.element).attr("data-html"));';
9110 $out .= ' }'."\n";
9111 $out .= ' return record.text;';
9112 $out .= '}' . "\n";
9113 $out .= 'function formatSelection(record) {' . "\n";
9114 if ($elemtype == 'category') {
9115 $out .= 'return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';';
9116 } else {
9117 $out .= 'return record.text;';
9118 }
9119 $out .= '}' . "\n";
9120 $out .= '$(document).ready(function () {
9121 $(\'#' . $htmlname . '\').' . $tmpplugin . '({';
9122 if ($placeholder) {
9123 $out .= '
9124 placeholder: {
9125 id: \'-1\',
9126 text: \'' . dol_escape_js($placeholder) . '\'
9127 },';
9128 }
9129 $out .= ' dir: \'ltr\',
9130 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag (ko with multiselect) */
9131 dropdownCssClass: \'' . $morecss . '\', /* Line to add class on the new <span class="select2-selection...> tag (ok with multiselect). Need full version of select2. */
9132 // Specify format function for dropdown item
9133 formatResult: formatResult,
9134 templateResult: formatResult, /* For 4.0 */
9135 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
9136 // Specify format function for selected item
9137 formatSelection: formatSelection,
9138 templateSelection: formatSelection, /* For 4.0 */
9139 language: select2arrayoflanguage
9140 });
9141
9142 /* Add also morecss to the css .select2 that is after the #htmlname, for component that are show dynamically after load, because select2 set
9143 the size only if component is not hidden by default on load */
9144 $(\'#' . $htmlname . ' + .select2\').addClass(\'' . $morecss . '\');
9145 });' . "\n";
9146 } elseif ($addjscombo == 2 && !defined('DISABLE_MULTISELECT')) {
9147 // Add other js lib
9148 // TODO external lib multiselect/jquery.multi-select.js must have been loaded to use this multiselect plugin
9149 // ...
9150 $out .= 'console.log(\'addjscombo=2 for htmlname=' . $htmlname . '\');';
9151 $out .= '$(document).ready(function () {
9152 $(\'#' . $htmlname . '\').multiSelect({
9153 containerHTML: \'<div class="multi-select-container">\',
9154 menuHTML: \'<div class="multi-select-menu">\',
9155 buttonHTML: \'<span class="multi-select-button ' . $morecss . '">\',
9156 menuItemHTML: \'<label class="multi-select-menuitem">\',
9157 activeClass: \'multi-select-container--open\',
9158 noneText: \'' . $placeholder . '\'
9159 });
9160 })';
9161 }
9162 $out .= '</script>';
9163 }
9164
9165 return $out;
9166 }
9167
9168
9180 public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage, $pos = '')
9181 {
9182 global $langs, $user;
9183
9184 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
9185 return '';
9186 }
9187 if (empty($array)) {
9188 return '';
9189 }
9190
9191 $tmpvar = "MAIN_SELECTEDFIELDS_" . $varpage; // To get list of saved selected fields to show
9192
9193 if (!empty($user->conf->$tmpvar)) { // A list of fields was already customized for user
9194 $tmparray = explode(',', $user->conf->$tmpvar);
9195 foreach ($array as $key => $val) {
9196 //var_dump($key);
9197 //var_dump($tmparray);
9198 if (in_array($key, $tmparray)) {
9199 $array[$key]['checked'] = 1;
9200 } else {
9201 $array[$key]['checked'] = 0;
9202 }
9203 }
9204 } else { // There is no list of fields already customized for user
9205 foreach ($array as $key => $val) {
9206 if (!empty($array[$key]['checked']) && $array[$key]['checked'] < 0) {
9207 $array[$key]['checked'] = 0;
9208 }
9209 }
9210 }
9211
9212 $listoffieldsforselection = '';
9213 $listcheckedstring = '';
9214
9215 foreach ($array as $key => $val) {
9216 // var_dump($val);
9217 // var_dump(array_key_exists('enabled', $val));
9218 // var_dump(!$val['enabled']);
9219 if (array_key_exists('enabled', $val) && isset($val['enabled']) && !$val['enabled']) {
9220 unset($array[$key]); // We don't want this field
9221 continue;
9222 }
9223 if (!empty($val['type']) && $val['type'] == 'separate') {
9224 // Field remains in array but we don't add it into $listoffieldsforselection
9225 //$listoffieldsforselection .= '<li>-----</li>';
9226 continue;
9227 }
9228 if (!empty($val['label']) && $val['label']) {
9229 if (!empty($val['langfile']) && is_object($langs)) {
9230 $langs->load($val['langfile']);
9231 }
9232
9233 // Note: $val['checked'] <> 0 means we must show the field into the combo list @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset
9234 $listoffieldsforselection .= '<li><input type="checkbox" id="checkbox' . $key . '" value="' . $key . '"' . ((!array_key_exists('checked', $val) || empty($val['checked']) || $val['checked'] == '-1') ? '' : ' checked="checked"') . '/><label for="checkbox' . $key . '">' . dol_escape_htmltag($langs->trans($val['label'])) . '</label></li>';
9235 $listcheckedstring .= (empty($val['checked']) ? '' : $key . ',');
9236 }
9237 }
9238
9239 $out = '<!-- Component multiSelectArrayWithCheckbox ' . $htmlname . ' -->
9240
9241 <dl class="dropdown">
9242 <dt>
9243 <a href="#' . $htmlname . '">
9244 ' . img_picto('', 'list') . '
9245 </a>
9246 <input type="hidden" class="' . $htmlname . '" name="' . $htmlname . '" value="' . $listcheckedstring . '">
9247 </dt>
9248 <dd class="dropdowndd">
9249 <div class="multiselectcheckbox'.$htmlname.'">
9250 <ul class="'.$htmlname.($pos == '1' ? 'left' : '').'">
9251 <li><input class="inputsearch_dropdownselectedfields width90p minwidth200imp" style="width:90%;" type="text" placeholder="'.$langs->trans('Search').'"></li>
9252 '.$listoffieldsforselection.'
9253 </ul>
9254 </div>
9255 </dd>
9256 </dl>
9257
9258 <script nonce="' . getNonce() . '" type="text/javascript">
9259 jQuery(document).ready(function () {
9260 $(\'.multiselectcheckbox' . $htmlname . ' input[type="checkbox"]\').on(\'click\', function () {
9261 console.log("A new field was added/removed, we edit field input[name=formfilteraction]");
9262
9263 $("input:hidden[name=formfilteraction]").val(\'listafterchangingselectedfields\'); // Update field so we know we changed something on selected fields after POST
9264
9265 var title = $(this).val() + ",";
9266 if ($(this).is(\':checked\')) {
9267 $(\'.' . $htmlname . '\').val(title + $(\'.' . $htmlname . '\').val());
9268 }
9269 else {
9270 $(\'.' . $htmlname . '\').val( $(\'.' . $htmlname . '\').val().replace(title, \'\') )
9271 }
9272 // Now, we submit page
9273 //$(this).parents(\'form:first\').submit();
9274 });
9275 $("input.inputsearch_dropdownselectedfields").on("keyup", function() {
9276 var value = $(this).val().toLowerCase();
9277 $(\'.multiselectcheckbox'.$htmlname.' li > label\').filter(function() {
9278 $(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
9279 });
9280 });
9281
9282
9283 });
9284 </script>
9285
9286 ';
9287 return $out;
9288 }
9289
9299 public function showCategories($id, $type, $rendermode = 0, $nolink = 0)
9300 {
9301 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
9302
9303 $cat = new Categorie($this->db);
9304 $categories = $cat->containing($id, $type);
9305
9306 if ($rendermode == 1) {
9307 $toprint = array();
9308 foreach ($categories as $c) {
9309 $ways = $c->print_all_ways(' &gt;&gt; ', ($nolink ? 'none' : ''), 0, 1); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
9310 foreach ($ways as $way) {
9311 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . $way . '</li>';
9312 }
9313 }
9314 if (empty($toprint)) {
9315 return '';
9316 } else {
9317 return '<div class="select2-container-multi-dolibarr"><ul class="select2-choices-dolibarr">' . implode(' ', $toprint) . '</ul></div>';
9318 }
9319 }
9320
9321 if ($rendermode == 0) {
9322 $arrayselected = array();
9323 $cate_arbo = $this->select_all_categories($type, '', 'parent', 64, 0, 3);
9324 foreach ($categories as $c) {
9325 $arrayselected[] = $c->id;
9326 }
9327
9328 return $this->multiselectarray('categories', $cate_arbo, $arrayselected, 0, 0, '', 0, '100%', 'disabled', 'category');
9329 }
9330
9331 return 'ErrorBadValueForParameterRenderMode'; // Should not happened
9332 }
9333
9343 public function showLinkedObjectBlock($object, $morehtmlright = '', $compatibleImportElementsList = array(), $title = 'RelatedObjects')
9344 {
9345 global $conf, $langs, $hookmanager;
9346 global $bc, $action;
9347
9348 $object->fetchObjectLinked();
9349
9350 // Bypass the default method
9351 $hookmanager->initHooks(array('commonobject'));
9352 $parameters = array(
9353 'morehtmlright' => $morehtmlright,
9354 'compatibleImportElementsList' => &$compatibleImportElementsList,
9355 );
9356 $reshook = $hookmanager->executeHooks('showLinkedObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9357
9358 $nbofdifferenttypes = count($object->linkedObjects);
9359
9360 if (empty($reshook)) {
9361 print '<!-- showLinkedObjectBlock -->';
9362 print load_fiche_titre($langs->trans($title), $morehtmlright, '', 0, 0, 'showlinkedobjectblock');
9363
9364
9365 print '<div class="div-table-responsive-no-min">';
9366 print '<table class="noborder allwidth" data-block="showLinkedObject" data-element="' . $object->element . '" data-elementid="' . $object->id . '" >';
9367
9368 print '<tr class="liste_titre">';
9369 print '<td>' . $langs->trans("Type") . '</td>';
9370 print '<td>' . $langs->trans("Ref") . '</td>';
9371 print '<td class="center"></td>';
9372 print '<td class="center">' . $langs->trans("Date") . '</td>';
9373 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9374 print '<td class="right">' . $langs->trans("Status") . '</td>';
9375 print '<td></td>';
9376 print '</tr>';
9377
9378 $nboftypesoutput = 0;
9379
9380 foreach ($object->linkedObjects as $objecttype => $objects) {
9381 $tplpath = $element = $subelement = $objecttype;
9382
9383 // to display import button on tpl
9384 $showImportButton = false;
9385 if (!empty($compatibleImportElementsList) && in_array($element, $compatibleImportElementsList)) {
9386 $showImportButton = true;
9387 }
9388
9389 $regs = array();
9390 if ($objecttype != 'supplier_proposal' && preg_match('/^([^_]+)_([^_]+)/i', $objecttype, $regs)) {
9391 $element = $regs[1];
9392 $subelement = $regs[2];
9393 $tplpath = $element . '/' . $subelement;
9394 }
9395 $tplname = 'linkedobjectblock';
9396
9397 // To work with non standard path
9398 if ($objecttype == 'facture') {
9399 $tplpath = 'compta/' . $element;
9400 if (!isModEnabled('invoice')) {
9401 continue; // Do not show if module disabled
9402 }
9403 } elseif ($objecttype == 'facturerec') {
9404 $tplpath = 'compta/facture';
9405 $tplname = 'linkedobjectblockForRec';
9406 if (!isModEnabled('invoice')) {
9407 continue; // Do not show if module disabled
9408 }
9409 } elseif ($objecttype == 'propal') {
9410 $tplpath = 'comm/' . $element;
9411 if (!isModEnabled('propal')) {
9412 continue; // Do not show if module disabled
9413 }
9414 } elseif ($objecttype == 'supplier_proposal') {
9415 if (!isModEnabled('supplier_proposal')) {
9416 continue; // Do not show if module disabled
9417 }
9418 } elseif ($objecttype == 'shipping' || $objecttype == 'shipment' || $objecttype == 'expedition') {
9419 $tplpath = 'expedition';
9420 if (!isModEnabled('shipping')) {
9421 continue; // Do not show if module disabled
9422 }
9423 } elseif ($objecttype == 'reception') {
9424 $tplpath = 'reception';
9425 if (!isModEnabled('reception')) {
9426 continue; // Do not show if module disabled
9427 }
9428 } elseif ($objecttype == 'delivery') {
9429 $tplpath = 'delivery';
9430 if (!getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) {
9431 continue; // Do not show if sub module disabled
9432 }
9433 } elseif ($objecttype == 'ficheinter') {
9434 $tplpath = 'fichinter';
9435 if (!isModEnabled('intervention')) {
9436 continue; // Do not show if module disabled
9437 }
9438 } elseif ($objecttype == 'invoice_supplier') {
9439 $tplpath = 'fourn/facture';
9440 } elseif ($objecttype == 'order_supplier') {
9441 $tplpath = 'fourn/commande';
9442 } elseif ($objecttype == 'expensereport') {
9443 $tplpath = 'expensereport';
9444 } elseif ($objecttype == 'subscription') {
9445 $tplpath = 'adherents';
9446 } elseif ($objecttype == 'conferenceorbooth') {
9447 $tplpath = 'eventorganization';
9448 } elseif ($objecttype == 'conferenceorboothattendee') {
9449 $tplpath = 'eventorganization';
9450 } elseif ($objecttype == 'mo') {
9451 $tplpath = 'mrp';
9452 if (!isModEnabled('mrp')) {
9453 continue; // Do not show if module disabled
9454 }
9455 }
9456
9457 global $linkedObjectBlock;
9458 $linkedObjectBlock = $objects;
9459
9460 // Output template part (modules that overwrite templates must declare this into descriptor)
9461 $dirtpls = array_merge($conf->modules_parts['tpl'], array('/' . $tplpath . '/tpl'));
9462 foreach ($dirtpls as $reldir) {
9463 $reldir = rtrim($reldir, '/');
9464 if ($nboftypesoutput == ($nbofdifferenttypes - 1)) { // No more type to show after
9465 global $noMoreLinkedObjectBlockAfter;
9466 $noMoreLinkedObjectBlockAfter = 1;
9467 }
9468
9469 $res = @include dol_buildpath($reldir . '/' . $tplname . '.tpl.php');
9470 if ($res) {
9471 $nboftypesoutput++;
9472 break;
9473 }
9474 }
9475 }
9476
9477 if (!$nboftypesoutput) {
9478 print '<tr><td class="impair" colspan="7"><span class="opacitymedium">' . $langs->trans("None") . '</span></td></tr>';
9479 }
9480
9481 print '</table>';
9482
9483 if (!empty($compatibleImportElementsList)) {
9484 $res = @include dol_buildpath('core/tpl/objectlinked_lineimport.tpl.php');
9485 }
9486
9487 print '</div>';
9488 }
9489
9490 return $nbofdifferenttypes;
9491 }
9492
9501 public function showLinkToObjectBlock($object, $restrictlinksto = array(), $excludelinksto = array())
9502 {
9503 global $conf, $langs, $hookmanager;
9504 global $action;
9505
9506 $linktoelem = '';
9507 $linktoelemlist = '';
9508 $listofidcompanytoscan = '';
9509
9510 if (!is_object($object->thirdparty)) {
9511 $object->fetch_thirdparty();
9512 }
9513
9514 $possiblelinks = array();
9515 if (is_object($object->thirdparty) && !empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
9516 $listofidcompanytoscan = $object->thirdparty->id;
9517 if (($object->thirdparty->parent > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PARENT_IN_LINKTO')) {
9518 $listofidcompanytoscan .= ',' . $object->thirdparty->parent;
9519 }
9520 if (($object->fk_project > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PROJECT_THIRDPARY_IN_LINKTO')) {
9521 include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
9522 $tmpproject = new Project($this->db);
9523 $tmpproject->fetch($object->fk_project);
9524 if ($tmpproject->socid > 0 && ($tmpproject->socid != $object->thirdparty->id)) {
9525 $listofidcompanytoscan .= ',' . $tmpproject->socid;
9526 }
9527 unset($tmpproject);
9528 }
9529
9530 $possiblelinks = array(
9531 'propal' => array(
9532 'enabled' => isModEnabled('propal'),
9533 'perms' => 1,
9534 'label' => 'LinkToProposal',
9535 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "propal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('propal') . ')'),
9536 'shipping' => array(
9537 'enabled' => isModEnabled('shipping'),
9538 'perms' => 1,
9539 'label' => 'LinkToExpedition',
9540 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "expedition as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('shipping') . ')'),
9541 'order' => array(
9542 'enabled' => isModEnabled('order'),
9543 'perms' => 1,
9544 'label' => 'LinkToOrder',
9545 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "commande as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('commande') . ')'),
9546 'invoice' => array(
9547 'enabled' => isModEnabled('invoice'),
9548 'perms' => 1,
9549 'label' => 'LinkToInvoice',
9550 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('invoice') . ')'),
9551 'invoice_template' => array(
9552 'enabled' => isModEnabled('invoice'),
9553 'perms' => 1,
9554 'label' => 'LinkToTemplateInvoice',
9555 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.titre as ref, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture_rec as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('invoice') . ')'),
9556 'contrat' => array(
9557 'enabled' => isModEnabled('contract'),
9558 'perms' => 1,
9559 'label' => 'LinkToContract',
9560 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_customer as ref_client, t.ref_supplier, SUM(td.total_ht) as total_ht
9561 FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "contrat as t, " . $this->db->prefix() . "contratdet as td WHERE t.fk_soc = s.rowid AND td.fk_contrat = t.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('contract') . ') GROUP BY s.rowid, s.nom, s.client, t.rowid, t.ref, t.ref_customer, t.ref_supplier'
9562 ),
9563 'fichinter' => array(
9564 'enabled' => isModEnabled('intervention'),
9565 'perms' => 1,
9566 'label' => 'LinkToIntervention',
9567 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "fichinter as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('intervention') . ')'),
9568 'supplier_proposal' => array(
9569 'enabled' => isModEnabled('supplier_proposal'),
9570 'perms' => 1,
9571 'label' => 'LinkToSupplierProposal',
9572 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, '' as ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "supplier_proposal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('supplier_proposal') . ')'),
9573 'order_supplier' => array(
9574 'enabled' => isModEnabled("supplier_order"),
9575 'perms' => 1,
9576 'label' => 'LinkToSupplierOrder',
9577 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('commande_fournisseur') . ')'),
9578 'invoice_supplier' => array(
9579 'enabled' => isModEnabled("supplier_invoice"),
9580 'perms' => 1, 'label' => 'LinkToSupplierInvoice',
9581 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "facture_fourn as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('facture_fourn') . ')'),
9582 'ticket' => array(
9583 'enabled' => isModEnabled('ticket'),
9584 'perms' => 1,
9585 'label' => 'LinkToTicket',
9586 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.track_id, '0' as total_ht FROM " . $this->db->prefix() . "societe as s, " . $this->db->prefix() . "ticket as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('ticket') . ')'),
9587 'mo' => array(
9588 'enabled' => isModEnabled('mrp'),
9589 'perms' => 1,
9590 'label' => 'LinkToMo',
9591 'sql' => "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.rowid, '0' as total_ht FROM " . $this->db->prefix() . "societe as s INNER JOIN " . $this->db->prefix() . "mrp_mo as t ON t.fk_soc = s.rowid WHERE t.fk_soc IN (" . $this->db->sanitize($listofidcompanytoscan) . ') AND t.entity IN (' . getEntity('mo') . ')')
9592 );
9593 }
9594
9595 if ($object->table_element == 'commande_fournisseur') {
9596 $possiblelinks['mo']['sql'] = "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.rowid, '0' as total_ht FROM ".$this->db->prefix()."societe as s INNER JOIN ".$this->db->prefix().'mrp_mo as t ON t.fk_soc = s.rowid WHERE t.entity IN ('.getEntity('mo').')';
9597 } elseif ($object->table_element == 'mrp_mo') {
9598 $possiblelinks['order_supplier']['sql'] = "SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".$this->db->prefix()."societe as s, ".$this->db->prefix().'commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.entity IN ('.getEntity('commande_fournisseur').')';
9599 }
9600
9601 $reshook = 0; // Ensure $reshook is defined for static analysis
9602 if (!empty($listofidcompanytoscan)) { // If empty, we don't have criteria to scan the object we can link to
9603 // Can complete the possiblelink array
9604 $hookmanager->initHooks(array('commonobject'));
9605 $parameters = array('listofidcompanytoscan' => $listofidcompanytoscan, 'possiblelinks' => $possiblelinks);
9606 $reshook = $hookmanager->executeHooks('showLinkToObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9607 }
9608
9609 if (empty($reshook)) {
9610 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9611 $possiblelinks = array_merge($possiblelinks, $hookmanager->resArray);
9612 }
9613 } elseif ($reshook > 0) {
9614 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9615 $possiblelinks = $hookmanager->resArray;
9616 }
9617 }
9618
9619 foreach ($possiblelinks as $key => $possiblelink) {
9620 $num = 0;
9621
9622 if (empty($possiblelink['enabled'])) {
9623 continue;
9624 }
9625
9626 if (!empty($possiblelink['perms']) && (empty($restrictlinksto) || in_array($key, $restrictlinksto)) && (empty($excludelinksto) || !in_array($key, $excludelinksto))) {
9627 print '<div id="' . $key . 'list"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display:none"') . '>';
9628
9629 if (getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9630 print '<br>'."\n";
9631 print '<!-- form to add a link from anywhere -->'."\n";
9632 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinkedbyref' . $key . '">';
9633 print '<input type="hidden" name="id" value="' . $object->id . '">';
9634 print '<input type="hidden" name="action" value="addlinkbyref">';
9635 print '<input type="hidden" name="token" value="' . newToken() . '">';
9636 print '<input type="hidden" name="addlink" value="' . $key . '">';
9637 print '<table class="noborder">';
9638 print '<tr>';
9639 //print '<td>' . $langs->trans("Ref") . '</td>';
9640 print '<td class="center"><input type="text" placeholder="'.dol_escape_htmltag($langs->trans("Ref")).'" name="reftolinkto" value="' . dol_escape_htmltag(GETPOST('reftolinkto', 'alpha')) . '">&nbsp;';
9641 print '<input type="submit" class="button small valignmiddle" value="' . $langs->trans('ToLink') . '">&nbsp;';
9642 print '<input type="submit" class="button small" name="cancel" value="' . $langs->trans('Cancel') . '"></td>';
9643 print '</tr>';
9644 print '</table>';
9645 print '</form>';
9646 }
9647
9648 $sql = $possiblelink['sql'];
9649
9650 $resqllist = $this->db->query($sql);
9651 if ($resqllist) {
9652 $num = $this->db->num_rows($resqllist);
9653 $i = 0;
9654
9655 print '<br>';
9656 print '<!-- form to add a link from object to same thirdparty -->'."\n";
9657 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinked' . $key . '">';
9658 print '<input type="hidden" name="action" value="addlink">';
9659 print '<input type="hidden" name="token" value="' . newToken() . '">';
9660 print '<input type="hidden" name="id" value="' . $object->id . '">';
9661 print '<input type="hidden" name="addlink" value="' . $key . '">';
9662 print '<table class="noborder">';
9663 print '<tr class="liste_titre">';
9664 print '<td class="nowrap"></td>';
9665 print '<td class="center">' . $langs->trans("Ref") . '</td>';
9666 print '<td class="left">' . $langs->trans("RefCustomer") . '</td>';
9667 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9668 print '<td class="left">' . $langs->trans("Company") . '</td>';
9669 print '</tr>';
9670 while ($i < $num) {
9671 $objp = $this->db->fetch_object($resqllist);
9672
9673 print '<tr class="oddeven">';
9674 print '<td class="left">';
9675 print '<input type="radio" name="idtolinkto" id="' . $key . '_' . $objp->rowid . '" value="' . $objp->rowid . '">';
9676 print '</td>';
9677 print '<td class="center"><label for="' . $key . '_' . $objp->rowid . '">' . $objp->ref . '</label></td>';
9678 print '<td>' . (!empty($objp->ref_client) ? $objp->ref_client : (!empty($objp->ref_supplier) ? $objp->ref_supplier : '')) . '</td>';
9679 print '<td class="right">';
9680 if ($possiblelink['label'] == 'LinkToContract') {
9681 $form = new Form($this->db);
9682 print $form->textwithpicto('', $langs->trans("InformationOnLinkToContract")) . ' ';
9683 }
9684 print '<span class="amount">' . (isset($objp->total_ht) ? price($objp->total_ht) : '') . '</span>';
9685 print '</td>';
9686 print '<td>' . $objp->name . '</td>';
9687 print '</tr>';
9688 $i++;
9689 }
9690 print '</table>';
9691 print '<div class="center">';
9692 if ($num) {
9693 print '<input type="submit" class="button valignmiddle marginleftonly marginrightonly small" value="' . $langs->trans('ToLink') . '">';
9694 }
9695 if (empty($conf->use_javascript_ajax)) {
9696 print '<input type="submit" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9697 } else {
9698 print '<input type="submit" onclick="jQuery(\'#' . $key . 'list\').toggle(); return false;" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9699 }
9700 print '</form>';
9701 $this->db->free($resqllist);
9702 } else {
9703 dol_print_error($this->db);
9704 }
9705 print '</div>';
9706
9707 //$linktoelem.=($linktoelem?' &nbsp; ':'');
9708 if ($num > 0 || getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9709 $linktoelemlist .= '<li><a href="#linkto' . $key . '" class="linkto dropdowncloseonclick" rel="' . $key . '">' . $langs->trans($possiblelink['label']) . ' (' . $num . ')</a></li>';
9710 // } else $linktoelem.=$langs->trans($possiblelink['label']);
9711 } else {
9712 $linktoelemlist .= '<li><span class="linktodisabled">' . $langs->trans($possiblelink['label']) . ' (0)</span></li>';
9713 }
9714 }
9715 }
9716
9717 if ($linktoelemlist) {
9718 $linktoelem = '
9719 <dl class="dropdown" id="linktoobjectname">
9720 ';
9721 if (!empty($conf->use_javascript_ajax)) {
9722 $linktoelem .= '<dt><a href="#linktoobjectname"><span class="fas fa-link paddingrightonly"></span>' . $langs->trans("LinkTo") . '...</a></dt>';
9723 }
9724 $linktoelem .= '<dd>
9725 <div class="multiselectlinkto">
9726 <ul class="ulselectedfields">' . $linktoelemlist . '
9727 </ul>
9728 </div>
9729 </dd>
9730 </dl>';
9731 } else {
9732 $linktoelem = '';
9733 }
9734
9735 if (!empty($conf->use_javascript_ajax)) {
9736 print '<!-- Add js to show linkto box -->
9737 <script nonce="' . getNonce() . '">
9738 jQuery(document).ready(function() {
9739 jQuery(".linkto").click(function() {
9740 console.log("We choose to show/hide links for rel="+jQuery(this).attr(\'rel\')+" so #"+jQuery(this).attr(\'rel\')+"list");
9741 jQuery("#"+jQuery(this).attr(\'rel\')+"list").toggle();
9742 });
9743 });
9744 </script>
9745 ';
9746 }
9747
9748 return $linktoelem;
9749 }
9750
9765 public function selectyesno($htmlname, $value = '', $option = 0, $disabled = false, $useempty = 0, $addjscombo = 0, $morecss = '', $labelyes = 'Yes', $labelno = 'No')
9766 {
9767 global $langs;
9768
9769 $yes = "yes";
9770 $no = "no";
9771 if ($option) {
9772 $yes = "1";
9773 $no = "0";
9774 }
9775
9776 $disabled = ($disabled ? ' disabled' : '');
9777
9778 $resultyesno = '<select class="flat width75' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '"' . $disabled . '>' . "\n";
9779 if ($useempty) {
9780 $resultyesno .= '<option value="-1"' . (($value < 0) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
9781 }
9782 if (("$value" == 'yes') || ($value == 1)) {
9783 $resultyesno .= '<option value="' . $yes . '" selected>' . $langs->trans($labelyes) . '</option>' . "\n";
9784 $resultyesno .= '<option value="' . $no . '">' . $langs->trans($labelno) . '</option>' . "\n";
9785 } else {
9786 $selected = (($useempty && $value != '0' && $value != 'no') ? '' : ' selected');
9787 $resultyesno .= '<option value="' . $yes . '">' . $langs->trans($labelyes) . '</option>' . "\n";
9788 $resultyesno .= '<option value="' . $no . '"' . $selected . '>' . $langs->trans($labelno) . '</option>' . "\n";
9789 }
9790 $resultyesno .= '</select>' . "\n";
9791
9792 if ($addjscombo) {
9793 $resultyesno .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($useempty < 0 ? (string) $useempty : '-1'), $morecss);
9794 }
9795
9796 return $resultyesno;
9797 }
9798
9799 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
9800
9810 public function select_export_model($selected = '', $htmlname = 'exportmodelid', $type = '', $useempty = 0)
9811 {
9812 // phpcs:enable
9813 $sql = "SELECT rowid, label";
9814 $sql .= " FROM " . $this->db->prefix() . "export_model";
9815 $sql .= " WHERE type = '" . $this->db->escape($type) . "'";
9816 $sql .= " ORDER BY rowid";
9817 $result = $this->db->query($sql);
9818 if ($result) {
9819 print '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
9820 if ($useempty) {
9821 print '<option value="-1">&nbsp;</option>';
9822 }
9823
9824 $num = $this->db->num_rows($result);
9825 $i = 0;
9826 while ($i < $num) {
9827 $obj = $this->db->fetch_object($result);
9828 if ($selected == $obj->rowid) {
9829 print '<option value="' . $obj->rowid . '" selected>';
9830 } else {
9831 print '<option value="' . $obj->rowid . '">';
9832 }
9833 print $obj->label;
9834 print '</option>';
9835 $i++;
9836 }
9837 print "</select>";
9838 } else {
9839 dol_print_error($this->db);
9840 }
9841 }
9842
9861 public function showrefnav($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $morehtmlright = '')
9862 {
9863 global $conf, $langs, $hookmanager, $extralanguages;
9864
9865 $ret = '';
9866 if (empty($fieldid)) {
9867 $fieldid = 'rowid';
9868 }
9869 if (empty($fieldref)) {
9870 $fieldref = 'ref';
9871 }
9872
9873 // Preparing gender's display if there is one
9874 $addgendertxt = '';
9875 if (property_exists($object, 'gender') && !empty($object->gender)) {
9876 $addgendertxt = ' ';
9877 switch ($object->gender) {
9878 case 'man':
9879 $addgendertxt .= '<i class="fas fa-mars"></i>';
9880 break;
9881 case 'woman':
9882 $addgendertxt .= '<i class="fas fa-venus"></i>';
9883 break;
9884 case 'other':
9885 $addgendertxt .= '<i class="fas fa-transgender"></i>';
9886 break;
9887 }
9888 }
9889
9890 // Add where from hooks
9891 if (is_object($hookmanager)) {
9892 $parameters = array('showrefnav' => true);
9893 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
9894 if (!empty($hookmanager->resPrint)) {
9895 if (empty($object->next_prev_filter) && preg_match('/^\s*AND/i', $hookmanager->resPrint)) {
9896 $object->next_prev_filter = preg_replace('/^\s*AND\s*/i', '', $hookmanager->resPrint);
9897 } elseif (!empty($object->next_prev_filter) && !preg_match('/^\s*AND/i', $hookmanager->resPrint)) {
9898 $object->next_prev_filter .= ' AND '.$hookmanager->resPrint;
9899 } else {
9900 $object->next_prev_filter .= $hookmanager->resPrint;
9901 }
9902 }
9903 }
9904
9905 $previous_ref = $next_ref = '';
9906 if ($shownav) {
9907 //print "paramid=$paramid,morehtml=$morehtml,shownav=$shownav,$fieldid,$fieldref,$morehtmlref,$moreparam";
9908 $object->load_previous_next_ref((isset($object->next_prev_filter) ? $object->next_prev_filter : ''), $fieldid, $nodbprefix);
9909
9910 $navurl = $_SERVER["PHP_SELF"];
9911 // Special case for project/task page
9912 if ($paramid == 'project_ref') {
9913 if (preg_match('/\/tasks\/(task|contact|note|document)\.php/', $navurl)) { // TODO Remove this when nav with project_ref on task pages are ok
9914 $navurl = preg_replace('/\/tasks\/(task|contact|time|note|document)\.php/', '/tasks.php', $navurl);
9915 $paramid = 'ref';
9916 }
9917 }
9918
9919 // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox
9920 // accesskey is for Mac: CTRL + key for all browsers
9921 $stringforfirstkey = $langs->trans("KeyboardShortcut");
9922 if ($conf->browser->name == 'chrome') {
9923 $stringforfirstkey .= ' ALT +';
9924 } elseif ($conf->browser->name == 'firefox') {
9925 $stringforfirstkey .= ' ALT + SHIFT +';
9926 } else {
9927 $stringforfirstkey .= ' CTL +';
9928 }
9929
9930 $previous_ref = $object->ref_previous ? '<a accesskey="p" alt="'.dol_escape_htmltag($langs->trans("Previous")).'" title="' . $stringforfirstkey . ' p" class="classfortooltip" href="' . $navurl . '?' . $paramid . '=' . urlencode($object->ref_previous) . $moreparam . '"><i class="fa fa-chevron-left"></i></a>' : '<span class="inactive"><i class="fa fa-chevron-left opacitymedium"></i></span>';
9931 $next_ref = $object->ref_next ? '<a accesskey="n" alt="'.dol_escape_htmltag($langs->trans("Next")).'" title="' . $stringforfirstkey . ' n" class="classfortooltip" href="' . $navurl . '?' . $paramid . '=' . urlencode($object->ref_next) . $moreparam . '"><i class="fa fa-chevron-right"></i></a>' : '<span class="inactive"><i class="fa fa-chevron-right opacitymedium"></i></span>';
9932 }
9933
9934 //print "xx".$previous_ref."x".$next_ref;
9935 $ret .= '<!-- Start banner content --><div style="vertical-align: middle">';
9936
9937 // Right part of banner
9938 if ($morehtmlright) {
9939 $ret .= '<div class="inline-block floatleft">' . $morehtmlright . '</div>';
9940 }
9941
9942 if ($previous_ref || $next_ref || $morehtml) {
9943 $ret .= '<div class="pagination paginationref"><ul class="right">';
9944 }
9945 if ($morehtml && getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2) {
9946 $ret .= '<!-- morehtml --><li class="noborder litext' . (($shownav && $previous_ref && $next_ref) ? ' clearbothonsmartphone' : '') . '">' . $morehtml . '</li>';
9947 }
9948 if ($shownav && ($previous_ref || $next_ref)) {
9949 $ret .= '<li class="pagination">' . $previous_ref . '</li>';
9950 $ret .= '<li class="pagination">' . $next_ref . '</li>';
9951 }
9952 if ($previous_ref || $next_ref || $morehtml) {
9953 $ret .= '</ul></div>';
9954 }
9955
9956 // Status
9957 $parameters = array('morehtmlstatus' => $morehtmlstatus);
9958 $reshook = $hookmanager->executeHooks('moreHtmlStatus', $parameters, $object); // Note that $action and $object may have been modified by hook
9959 if (empty($reshook)) {
9960 $morehtmlstatus .= $hookmanager->resPrint;
9961 } else {
9962 $morehtmlstatus = $hookmanager->resPrint;
9963 }
9964 if ($morehtmlstatus) {
9965 $ret .= '<div class="statusref">' . $morehtmlstatus . '</div>';
9966 }
9967
9968 $parameters = array();
9969 $reshook = $hookmanager->executeHooks('moreHtmlRef', $parameters, $object); // Note that $action and $object may have been modified by hook
9970 if (empty($reshook)) {
9971 $morehtmlref .= $hookmanager->resPrint;
9972 } elseif ($reshook > 0) {
9973 $morehtmlref = $hookmanager->resPrint;
9974 }
9975
9976 // Left part of banner
9977 if ($morehtmlleft) {
9978 if ($conf->browser->layout == 'phone') {
9979 $ret .= '<!-- morehtmlleft --><div class="floatleft">' . $morehtmlleft . '</div>';
9980 } else {
9981 $ret .= '<!-- morehtmlleft --><div class="inline-block floatleft">' . $morehtmlleft . '</div>';
9982 }
9983 }
9984
9985 //if ($conf->browser->layout == 'phone') $ret.='<div class="clearboth"></div>';
9986 $ret .= '<div class="inline-block floatleft valignmiddle maxwidth750 marginbottomonly refid' . (($shownav && ($previous_ref || $next_ref)) ? ' refidpadding' : '') . '">';
9987
9988 // For thirdparty, contact, user, member, the ref is the id, so we show something else
9989 if ($object->element == 'societe') {
9990 $ret .= dol_htmlentities($object->name);
9991
9992 // List of extra languages
9993 $arrayoflangcode = array();
9994 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
9995 $arrayoflangcode[] = getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE');
9996 }
9997
9998 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
9999 if (!is_object($extralanguages)) {
10000 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
10001 $extralanguages = new ExtraLanguages($this->db);
10002 }
10003 $extralanguages->fetch_name_extralanguages('societe');
10004
10005 if (!empty($extralanguages->attributes['societe']['name'])) {
10006 $object->fetchValuesForExtraLanguages();
10007
10008 $htmltext = '';
10009 // If there is extra languages
10010 foreach ($arrayoflangcode as $extralangcode) {
10011 $htmltext .= picto_from_langcode($extralangcode, 'class="pictoforlang paddingright"');
10012 if ($object->array_languages['name'][$extralangcode]) {
10013 $htmltext .= $object->array_languages['name'][$extralangcode];
10014 } else {
10015 $htmltext .= '<span class="opacitymedium">' . $langs->trans("SwitchInEditModeToAddTranslation") . '</span>';
10016 }
10017 }
10018 $ret .= '<!-- Show translations of name -->' . "\n";
10019 $ret .= $this->textwithpicto('', $htmltext, -1, 'language', 'opacitymedium paddingleft');
10020 }
10021 }
10022 } elseif ($object->element == 'member') {
10023 '@phan-var-force Adherent $object';
10024 $ret .= $object->ref . '<br>';
10025 $fullname = $object->getFullName($langs);
10026 if ($object->morphy == 'mor' && $object->societe) {
10027 $ret .= dol_htmlentities($object->societe) . ((!empty($fullname) && $object->societe != $fullname) ? ' (' . dol_htmlentities($fullname) . $addgendertxt . ')' : '');
10028 } else {
10029 $ret .= dol_htmlentities($fullname) . $addgendertxt . ((!empty($object->societe) && $object->societe != $fullname) ? ' (' . dol_htmlentities($object->societe) . ')' : '');
10030 }
10031 } elseif (in_array($object->element, array('contact', 'user'))) {
10032 $ret .= dol_htmlentities($object->getFullName($langs)) . $addgendertxt;
10033 } elseif ($object->element == 'usergroup') {
10034 $ret .= dol_htmlentities($object->name);
10035 } elseif (in_array($object->element, array('action', 'agenda'))) {
10036 '@phan-var-force ActionComm $object';
10037 $ret .= $object->ref . '<br>' . $object->label;
10038 } elseif (in_array($object->element, array('adherent_type'))) {
10039 $ret .= $object->label;
10040 } elseif ($object->element == 'ecm_directories') {
10041 $ret .= '';
10042 } elseif ($fieldref != 'none') {
10043 $ret .= dol_htmlentities(!empty($object->$fieldref) ? $object->$fieldref : "");
10044 }
10045 if ($morehtmlref) {
10046 // don't add a additional space, when "$morehtmlref" starts with a HTML div tag
10047 if (substr($morehtmlref, 0, 4) != '<div') {
10048 $ret .= ' ';
10049 }
10050
10051 $ret .= $morehtmlref;
10052 }
10053
10054 $ret .= '</div>';
10055
10056 $ret .= '</div><!-- End banner content -->';
10057
10058 return $ret;
10059 }
10060
10061
10070 public function showbarcode(&$object, $width = 100, $morecss = '')
10071 {
10072 global $conf;
10073
10074 //Check if barcode is filled in the card
10075 if (empty($object->barcode)) {
10076 return '';
10077 }
10078
10079 // Complete object if not complete
10080 if (empty($object->barcode_type_code) || empty($object->barcode_type_coder)) {
10081 // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
10082 $result = $object->fetch_barcode();
10083 //Check if fetch_barcode() failed
10084 if ($result < 1) {
10085 return '<!-- ErrorFetchBarcode -->';
10086 }
10087 }
10088
10089 // Barcode image @phan-suppress-next-line PhanUndeclaredProperty
10090 $url = DOL_URL_ROOT . '/viewimage.php?modulepart=barcode&generator=' . urlencode($object->barcode_type_coder) . '&code=' . urlencode($object->barcode) . '&encoding=' . urlencode($object->barcode_type_code);
10091 $out = '<!-- url barcode = ' . $url . ' -->';
10092 $out .= '<img src="' . $url . '"' . ($morecss ? ' class="' . $morecss . '"' : '') . '>';
10093
10094 return $out;
10095 }
10096
10114 public static function showphoto($modulepart, $object, $width = 100, $height = 0, $caneditfield = 0, $cssclass = 'photowithmargin', $imagesize = '', $addlinktofullsize = 1, $cache = 0, $forcecapture = '', $noexternsourceoverwrite = 0)
10115 {
10116 global $conf, $langs;
10117
10118 $entity = (empty($object->entity) ? $conf->entity : $object->entity);
10119 $id = (empty($object->id) ? $object->rowid : $object->id); // @phan-suppress-current-line PhanUndeclaredProperty (->rowid)
10120
10121 $dir = '';
10122 $file = '';
10123 $originalfile = '';
10124 $altfile = '';
10125 $email = '';
10126 $capture = '';
10127 if ($modulepart == 'societe') {
10128 $dir = $conf->societe->multidir_output[$entity];
10129 if (!empty($object->logo)) {
10130 if (dolIsAllowedForPreview($object->logo)) {
10131 if ((string) $imagesize == 'mini') {
10132 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_mini'); // getImageFileNameForSize include the thumbs
10133 } elseif ((string) $imagesize == 'small') {
10134 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_small');
10135 } else {
10136 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
10137 }
10138 $originalfile = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
10139 }
10140 }
10141 $email = $object->email;
10142 } elseif ($modulepart == 'contact') {
10143 $dir = $conf->societe->multidir_output[$entity] . '/contact';
10144 if (!empty($object->photo)) {
10145 if (dolIsAllowedForPreview($object->photo)) {
10146 if ((string) $imagesize == 'mini') {
10147 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10148 } elseif ((string) $imagesize == 'small') {
10149 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10150 } else {
10151 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
10152 }
10153 $originalfile = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
10154 }
10155 }
10156 $email = $object->email;
10157 $capture = 'user';
10158 } elseif ($modulepart == 'userphoto') {
10159 $dir = $conf->user->dir_output;
10160 if (!empty($object->photo)) {
10161 if (dolIsAllowedForPreview($object->photo)) {
10162 if ((string) $imagesize == 'mini') {
10163 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10164 } elseif ((string) $imagesize == 'small') {
10165 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10166 } else {
10167 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
10168 }
10169 $originalfile = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
10170 }
10171 }
10172 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
10173 $altfile = $object->id . ".jpg"; // For backward compatibility
10174 }
10175 $email = $object->email;
10176 $capture = 'user';
10177 } elseif ($modulepart == 'memberphoto') {
10178 $dir = $conf->adherent->dir_output;
10179 if (!empty($object->photo)) {
10180 if (dolIsAllowedForPreview($object->photo)) {
10181 if ((string) $imagesize == 'mini') {
10182 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10183 } elseif ((string) $imagesize == 'small') {
10184 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10185 } else {
10186 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
10187 }
10188 $originalfile = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
10189 }
10190 }
10191 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
10192 $altfile = $object->id . ".jpg"; // For backward compatibility
10193 }
10194 $email = $object->email;
10195 $capture = 'user';
10196 } else {
10197 // Generic case to show photos
10198 // TODO Implement this method in previous objects so we can always use this generic method.
10199 if ($modulepart != "unknown" && method_exists($object, 'getDataToShowPhoto')) {
10200 $tmpdata = $object->getDataToShowPhoto($modulepart, $imagesize);
10201
10202 $dir = $tmpdata['dir'];
10203 $file = $tmpdata['file'];
10204 $originalfile = $tmpdata['originalfile'];
10205 $altfile = $tmpdata['altfile'];
10206 $email = $tmpdata['email'];
10207 $capture = $tmpdata['capture'];
10208 }
10209 }
10210
10211 if ($forcecapture) {
10212 $capture = $forcecapture;
10213 }
10214
10215 $ret = '';
10216
10217 if ($dir) {
10218 if ($file && file_exists($dir . "/" . $file)) {
10219 if ($addlinktofullsize) {
10220 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
10221 if ($urladvanced) {
10222 $ret .= '<a href="' . $urladvanced . '">';
10223 } else {
10224 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
10225 }
10226 }
10227 $ret .= '<img alt="" class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . ' photologo' . (preg_replace('/[^a-z]/i', '_', $file)) . '" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($file) . '&cache=' . $cache . '">';
10228 if ($addlinktofullsize) {
10229 $ret .= '</a>';
10230 }
10231 } elseif ($altfile && file_exists($dir . "/" . $altfile)) {
10232 if ($addlinktofullsize) {
10233 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
10234 if ($urladvanced) {
10235 $ret .= '<a href="' . $urladvanced . '">';
10236 } else {
10237 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
10238 }
10239 }
10240 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="Photo alt" id="photologo' . (preg_replace('/[^a-z]/i', '_', $file)) . '" class="' . $cssclass . '" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($altfile) . '&cache=' . $cache . '">';
10241 if ($addlinktofullsize) {
10242 $ret .= '</a>';
10243 }
10244 } else {
10245 $nophoto = '/public/theme/common/nophoto.png';
10246 $defaultimg = 'identicon'; // For gravatar
10247 if (in_array($modulepart, array('societe', 'userphoto', 'contact', 'memberphoto'))) { // For modules that need a special image when photo not found
10248 if ($modulepart == 'societe' || ($modulepart == 'memberphoto' && !empty($object->morphy) && strpos($object->morphy, 'mor') !== false)) {
10249 $nophoto = 'company';
10250 } else {
10251 $nophoto = '/public/theme/common/user_anonymous.png';
10252 if (!empty($object->gender) && $object->gender == 'man') {
10253 $nophoto = '/public/theme/common/user_man.png';
10254 }
10255 if (!empty($object->gender) && $object->gender == 'woman') {
10256 $nophoto = '/public/theme/common/user_woman.png';
10257 }
10258 }
10259 }
10260
10261 if (isModEnabled('gravatar') && $email && empty($noexternsourceoverwrite)) {
10262 // see https://gravatar.com/site/implement/images/php/
10263 $ret .= '<!-- Put link to gravatar -->';
10264 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" title="' . $email . ' Gravatar avatar" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="https://www.gravatar.com/avatar/' . dol_hash(strtolower(trim($email)), 'sha256', 1) . '?s=' . $width . '&d=' . $defaultimg . '">'; // gravatar need md5 hash
10265 } else {
10266 if ($nophoto == 'company') {
10267 $ret .= '<div class="divforspanimg valignmiddle center photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . '>' . img_picto('', 'company') . '</div>';
10268 //$ret .= '<div class="difforspanimgright"></div>';
10269 } else {
10270 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . $nophoto . '">';
10271 }
10272 }
10273 }
10274
10275 if ($caneditfield) {
10276 if ($object->photo) {
10277 $ret .= "<br>\n";
10278 }
10279 $ret .= '<table class="nobordernopadding centpercent">';
10280 if ($object->photo) {
10281 $ret .= '<tr><td><input type="checkbox" class="flat photodelete" name="deletephoto" id="photodelete"> <label for="photodelete">' . $langs->trans("Delete") . '</label><br><br></td></tr>';
10282 }
10283 $ret .= '<tr><td class="tdoverflow">';
10284 $maxfilesizearray = getMaxFileSizeArray();
10285 $maxmin = $maxfilesizearray['maxmin'];
10286 if ($maxmin > 0) {
10287 $ret .= '<input type="hidden" name="MAX_FILE_SIZE" value="' . ($maxmin * 1024) . '">'; // MAX_FILE_SIZE must precede the field type=file
10288 }
10289 $ret .= '<input type="file" class="flat maxwidth200onsmartphone" name="photo" id="photoinput" accept="image/*"' . ($capture ? ' capture="' . $capture . '"' : '') . '>';
10290 $ret .= '</td></tr>';
10291 $ret .= '</table>';
10292 }
10293 }
10294
10295 return $ret;
10296 }
10297
10298 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
10299
10316 public function select_dolgroups($selected = 0, $htmlname = 'groupid', $show_empty = 0, $exclude = '', $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0', $multiple = false, $morecss = 'minwidth200')
10317 {
10318 // phpcs:enable
10319 global $conf, $user, $langs;
10320
10321 // Allow excluding groups
10322 $excludeGroups = null;
10323 if (is_array($exclude)) {
10324 $excludeGroups = implode(",", $exclude);
10325 }
10326 // Allow including groups
10327 $includeGroups = null;
10328 if (is_array($include)) {
10329 $includeGroups = implode(",", $include);
10330 }
10331
10332 if (!is_array($selected)) {
10333 $selected = array($selected);
10334 }
10335
10336 $out = '';
10337
10338 // Build sql to search groups
10339 $sql = "SELECT ug.rowid, ug.nom as name";
10340 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10341 $sql .= ", e.label";
10342 }
10343 $sql .= " FROM " . $this->db->prefix() . "usergroup as ug ";
10344 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10345 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid=ug.entity";
10346 if ($force_entity) {
10347 $sql .= " WHERE ug.entity IN (0, " . $force_entity . ")";
10348 } else {
10349 $sql .= " WHERE ug.entity IS NOT NULL";
10350 }
10351 } else {
10352 $sql .= " WHERE ug.entity IN (0, " . $conf->entity . ")";
10353 }
10354 if (is_array($exclude) && $excludeGroups) {
10355 $sql .= " AND ug.rowid NOT IN (" . $this->db->sanitize($excludeGroups) . ")";
10356 }
10357 if (is_array($include) && $includeGroups) {
10358 $sql .= " AND ug.rowid IN (" . $this->db->sanitize($includeGroups) . ")";
10359 }
10360 $sql .= " ORDER BY ug.nom ASC";
10361
10362 dol_syslog(get_class($this) . "::select_dolgroups", LOG_DEBUG);
10363 $resql = $this->db->query($sql);
10364 if ($resql) {
10365 // Enhance with select2
10366 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10367
10368 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
10369
10370 $num = $this->db->num_rows($resql);
10371 $i = 0;
10372 if ($num) {
10373 if ($show_empty && !$multiple) {
10374 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
10375 }
10376
10377 while ($i < $num) {
10378 $obj = $this->db->fetch_object($resql);
10379 $disableline = 0;
10380 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
10381 $disableline = 1;
10382 }
10383
10384 $label = $obj->name;
10385 $labelhtml = $obj->name;
10386 if (isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1) {
10387 $label .= " (" . $obj->label . ")";
10388 $labelhtml .= ' <span class="opacitymedium">(' . $obj->label . ')</span>';
10389 }
10390
10391 $out .= '<option value="' . $obj->rowid . '"';
10392 if ($disableline) {
10393 $out .= ' disabled';
10394 }
10395 if ((isset($selected[0]) && is_object($selected[0]) && $selected[0]->id == $obj->rowid)
10396 || ((!isset($selected[0]) || !is_object($selected[0])) && !empty($selected) && in_array($obj->rowid, $selected))) {
10397 $out .= ' selected';
10398 }
10399 $out .= ' data-html="'.dol_escape_htmltag($labelhtml).'"';
10400 $out .= '>';
10401 $out .= $label;
10402 $out .= '</option>';
10403 $i++;
10404 }
10405 } else {
10406 if ($show_empty) {
10407 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '></option>' . "\n";
10408 }
10409 $out .= '<option value="" disabled>' . $langs->trans("NoUserGroupDefined") . '</option>';
10410 }
10411 $out .= '</select>';
10412
10413 $out .= ajax_combobox($htmlname);
10414 } else {
10415 dol_print_error($this->db);
10416 }
10417
10418 return $out;
10419 }
10420
10421
10428 public function showFilterButtons($pos = '')
10429 {
10430 $out = '<div class="nowraponall">';
10431 $out .= '<button type="submit" class="liste_titre button_search reposition" name="button_search_x" value="x"><span class="fas fa-search"></span></button>';
10432 $out .= '<button type="submit" class="liste_titre button_removefilter reposition" name="button_removefilter_x" value="x"><span class="fas fa-times"></span></button>';
10433 $out .= '</div>';
10434
10435 return $out;
10436 }
10437
10446 public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10447 {
10448 global $conf;
10449
10450 $out = '';
10451
10452 if (!empty($conf->use_javascript_ajax)) {
10453 $out .= '<div class="inline-block checkallactions"><input type="checkbox" id="' . $cssclass . 's" name="' . $cssclass . 's" class="checkallactions"></div>';
10454 }
10455 $out .= '<script nonce="' . getNonce() . '">
10456 $(document).ready(function() {
10457 $("#' . $cssclass . 's").click(function() {
10458 if($(this).is(\':checked\')){
10459 console.log("We check all ' . $cssclass . ' and trigger the change method");
10460 $(".' . $cssclass . '").prop(\'checked\', true).trigger(\'change\');
10461 }
10462 else
10463 {
10464 console.log("We uncheck all");
10465 $(".' . $cssclass . '").prop(\'checked\', false).trigger(\'change\');
10466 }' . "\n";
10467 if ($calljsfunction) {
10468 $out .= 'if (typeof initCheckForSelect == \'function\') { initCheckForSelect(0, "' . $massactionname . '", "' . $cssclass . '"); } else { console.log("No function initCheckForSelect found. Call won\'t be done."); }';
10469 }
10470 $out .= ' });
10471 $(".' . $cssclass . '").change(function() {
10472 $(this).closest("tr").toggleClass("highlight", this.checked);
10473 });
10474 });
10475 </script>';
10476
10477 return $out;
10478 }
10479
10489 public function showFilterAndCheckAddButtons($addcheckuncheckall = 0, $cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10490 {
10491 $out = $this->showFilterButtons();
10492 if ($addcheckuncheckall) {
10493 $out .= $this->showCheckAddButtons($cssclass, $calljsfunction, $massactionname);
10494 }
10495 return $out;
10496 }
10497
10511 public function selectExpenseCategories($selected = '', $htmlname = 'fk_c_exp_tax_cat', $useempty = 0, $excludeid = array(), $target = '', $default_selected = 0, $params = array(), $info_admin = 1)
10512 {
10513 global $langs, $user;
10514
10515 $out = '';
10516 $sql = "SELECT rowid, label FROM " . $this->db->prefix() . "c_exp_tax_cat WHERE active = 1";
10517 $sql .= " AND entity IN (0," . getEntity('exp_tax_cat') . ")";
10518 if (!empty($excludeid)) {
10519 $sql .= " AND rowid NOT IN (" . $this->db->sanitize(implode(',', $excludeid)) . ")";
10520 }
10521 $sql .= " ORDER BY label";
10522
10523 $resql = $this->db->query($sql);
10524 if ($resql) {
10525 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp maxwidth200">';
10526 if ($useempty) {
10527 $out .= '<option value="0">&nbsp;</option>';
10528 }
10529
10530 while ($obj = $this->db->fetch_object($resql)) {
10531 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . $langs->trans($obj->label) . '</option>';
10532 }
10533 $out .= '</select>';
10534 $out .= ajax_combobox('select_' . $htmlname);
10535
10536 if (!empty($htmlname) && $user->admin && $info_admin) {
10537 $out .= ' ' . info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
10538 }
10539
10540 if (!empty($target)) {
10541 $sql = "SELECT c.id FROM " . $this->db->prefix() . "c_type_fees as c WHERE c.code = 'EX_KME' AND c.active = 1";
10542 $resql = $this->db->query($sql);
10543 if ($resql) {
10544 if ($this->db->num_rows($resql) > 0) {
10545 $obj = $this->db->fetch_object($resql);
10546 $out .= '<script nonce="' . getNonce() . '">
10547 $(function() {
10548 $("select[name=' . $target . ']").on("change", function() {
10549 var current_val = $(this).val();
10550 if (current_val == ' . $obj->id . ') {';
10551 if (!empty($default_selected) || !empty($selected)) {
10552 $out .= '$("select[name=' . $htmlname . ']").val("' . ($default_selected > 0 ? $default_selected : $selected) . '");';
10553 }
10554
10555 $out .= '
10556 $("select[name=' . $htmlname . ']").change();
10557 }
10558 });
10559
10560 $("select[name=' . $htmlname . ']").change(function() {
10561
10562 if ($("select[name=' . $target . ']").val() == ' . $obj->id . ') {
10563 // get price of kilometer to fill the unit price
10564 $.ajax({
10565 method: "POST",
10566 dataType: "json",
10567 data: { fk_c_exp_tax_cat: $(this).val(), token: \'' . currentToken() . '\' },
10568 url: "' . (DOL_URL_ROOT . '/expensereport/ajax/ajaxik.php?' . implode('&', $params)) . '",
10569 }).done(function( data, textStatus, jqXHR ) {
10570 console.log(data);
10571 if (typeof data.up != "undefined") {
10572 $("input[name=value_unit]").val(data.up);
10573 $("select[name=' . $htmlname . ']").attr("title", data.title);
10574 } else {
10575 $("input[name=value_unit]").val("");
10576 $("select[name=' . $htmlname . ']").attr("title", "");
10577 }
10578 });
10579 }
10580 });
10581 });
10582 </script>';
10583 }
10584 }
10585 }
10586 } else {
10587 dol_print_error($this->db);
10588 }
10589
10590 return $out;
10591 }
10592
10601 public function selectExpenseRanges($selected = '', $htmlname = 'fk_range', $useempty = 0)
10602 {
10603 global $conf, $langs;
10604
10605 $out = '';
10606 $sql = "SELECT rowid, range_ik FROM " . $this->db->prefix() . "c_exp_tax_range";
10607 $sql .= " WHERE entity = " . $conf->entity . " AND active = 1";
10608
10609 $resql = $this->db->query($sql);
10610 if ($resql) {
10611 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10612 if ($useempty) {
10613 $out .= '<option value="0"></option>';
10614 }
10615
10616 while ($obj = $this->db->fetch_object($resql)) {
10617 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . price($obj->range_ik, 0, $langs, 1, 0) . '</option>';
10618 }
10619 $out .= '</select>';
10620 } else {
10621 dol_print_error($this->db);
10622 }
10623
10624 return $out;
10625 }
10626
10637 public function selectExpense($selected = '', $htmlname = 'fk_c_type_fees', $useempty = 0, $allchoice = 1, $useid = 0)
10638 {
10639 global $langs;
10640
10641 $out = '';
10642 $sql = "SELECT id, code, label";
10643 $sql .= " FROM ".$this->db->prefix()."c_type_fees";
10644 $sql .= " WHERE active = 1";
10645
10646 $resql = $this->db->query($sql);
10647 if ($resql) {
10648 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10649 if ($useempty) {
10650 $out .= '<option value="0"></option>';
10651 }
10652 if ($allchoice) {
10653 $out .= '<option value="-1">' . $langs->trans('AllExpenseReport') . '</option>';
10654 }
10655
10656 $field = 'code';
10657 if ($useid) {
10658 $field = 'id';
10659 }
10660
10661 while ($obj = $this->db->fetch_object($resql)) {
10662 $key = $langs->trans($obj->code);
10663 $out .= '<option ' . ($selected == $obj->{$field} ? 'selected="selected"' : '') . ' value="' . $obj->{$field} . '">' . ($key != $obj->code ? $key : $obj->label) . '</option>';
10664 }
10665 $out .= '</select>';
10666
10667 $out .= ajax_combobox('select_'.$htmlname);
10668 } else {
10669 dol_print_error($this->db);
10670 }
10671
10672 return $out;
10673 }
10674
10693 public function selectInvoice($socid = -1, $selected = '', $htmlname = 'invoiceid', $maxlength = 24, $option_only = 0, $show_empty = '1', $discard_closed = 0, $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500', $projectsListId = '', $showproject = 'all', $usertofilter = null)
10694 {
10695 global $user, $conf, $langs;
10696
10697 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
10698
10699 if (is_null($usertofilter)) {
10700 $usertofilter = $user;
10701 }
10702
10703 $out = '';
10704
10705 $hideunselectables = false;
10706 if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
10707 $hideunselectables = true;
10708 }
10709
10710 if (empty($projectsListId)) {
10711 if (!$usertofilter->hasRight('projet', 'all', 'lire')) {
10712 $projectstatic = new Project($this->db);
10713 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertofilter, 0, 1);
10714 }
10715 }
10716
10717 // Search all projects
10718 $sql = "SELECT f.rowid, f.ref as fref, 'nolabel' as flabel, p.rowid as pid, f.ref,
10719 p.title, p.fk_soc, p.fk_statut, p.public,";
10720 $sql .= ' s.nom as name';
10721 $sql .= ' FROM ' . $this->db->prefix() . 'projet as p';
10722 $sql .= ' LEFT JOIN ' . $this->db->prefix() . 'societe as s ON s.rowid = p.fk_soc,';
10723 $sql .= ' ' . $this->db->prefix() . 'facture as f';
10724 $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
10725 $sql .= " AND f.fk_projet = p.rowid AND f.fk_statut=0"; //Brouillons seulement
10726 //if ($projectsListId) $sql.= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")";
10727 //if ($socid == 0) $sql.= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
10728 //if ($socid > 0) $sql.= " AND (p.fk_soc=".((int) $socid)." OR p.fk_soc IS NULL)";
10729 $sql .= " ORDER BY p.ref, f.ref ASC";
10730
10731 $resql = $this->db->query($sql);
10732 if ($resql) {
10733 // Use select2 selector
10734 if (!empty($conf->use_javascript_ajax)) {
10735 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10736 $comboenhancement = ajax_combobox($htmlname, array(), 0, $forcefocus);
10737 $out .= $comboenhancement;
10738 $morecss = 'minwidth200imp maxwidth500';
10739 }
10740
10741 if (empty($option_only)) {
10742 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10743 }
10744 if (!empty($show_empty)) {
10745 $out .= '<option value="0" class="optiongrey">';
10746 if (!is_numeric($show_empty)) {
10747 $out .= $show_empty;
10748 } else {
10749 $out .= '&nbsp;';
10750 }
10751 $out .= '</option>';
10752 }
10753 $num = $this->db->num_rows($resql);
10754 $i = 0;
10755 if ($num) {
10756 while ($i < $num) {
10757 $obj = $this->db->fetch_object($resql);
10758 // If we ask to filter on a company and user has no permission to see all companies and project is linked to another company, we hide project.
10759 if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$usertofilter->hasRight('societe', 'lire')) {
10760 // Do nothing
10761 } else {
10762 if ($discard_closed == 1 && $obj->fk_statut == Project::STATUS_CLOSED) {
10763 $i++;
10764 continue;
10765 }
10766
10767 $labeltoshow = '';
10768
10769 if ($showproject == 'all') {
10770 $labeltoshow .= dol_trunc($obj->ref, 18); // Invoice ref
10771 if ($obj->name) {
10772 $labeltoshow .= ' - ' . $obj->name; // Soc name
10773 }
10774
10775 $disabled = 0;
10776 if ($obj->fk_statut == Project::STATUS_DRAFT) {
10777 $disabled = 1;
10778 $labeltoshow .= ' - ' . $langs->trans("Draft");
10779 } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
10780 if ($discard_closed == 2) {
10781 $disabled = 1;
10782 }
10783 $labeltoshow .= ' - ' . $langs->trans("Closed");
10784 } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
10785 $disabled = 1;
10786 $labeltoshow .= ' - ' . $langs->trans("LinkedToAnotherCompany");
10787 }
10788 }
10789
10790 if (!empty($selected) && $selected == $obj->rowid) {
10791 $out .= '<option value="' . $obj->rowid . '" selected';
10792 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10793 $out .= '>' . $labeltoshow . '</option>';
10794 } else {
10795 if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
10796 $resultat = '';
10797 } else {
10798 $resultat = '<option value="' . $obj->rowid . '"';
10799 if ($disabled) {
10800 $resultat .= ' disabled';
10801 }
10802 //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
10803 //else $labeltoshow.=' ('.$langs->trans("Private").')';
10804 $resultat .= '>';
10805 $resultat .= $labeltoshow;
10806 $resultat .= '</option>';
10807 }
10808 $out .= $resultat;
10809 }
10810 }
10811 $i++;
10812 }
10813 }
10814 if (empty($option_only)) {
10815 $out .= '</select>';
10816 }
10817
10818 $this->db->free($resql);
10819
10820 return $out;
10821 } else {
10822 dol_print_error($this->db);
10823 return '';
10824 }
10825 }
10826
10840 public function selectInvoiceRec($selected = '', $htmlname = 'facrecid', $maxlength = 24, $option_only = 0, $show_empty = '1', $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500')
10841 {
10842 global $conf, $langs;
10843
10844 $out = '';
10845
10846 dol_syslog('FactureRec::fetch', LOG_DEBUG);
10847
10848 $sql = 'SELECT f.rowid, f.entity, f.titre as title, f.suspended, f.fk_soc';
10849 //$sql.= ', el.fk_source';
10850 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_rec as f';
10851 $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
10852 $sql .= " ORDER BY f.titre ASC";
10853
10854 $resql = $this->db->query($sql);
10855 if ($resql) {
10856 // Use select2 selector
10857 if (!empty($conf->use_javascript_ajax)) {
10858 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10859 $comboenhancement = ajax_combobox($htmlname, array(), 0, $forcefocus);
10860 $out .= $comboenhancement;
10861 $morecss = 'minwidth200imp maxwidth500';
10862 }
10863
10864 if (empty($option_only)) {
10865 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10866 }
10867 if (!empty($show_empty)) {
10868 $out .= '<option value="0" class="optiongrey">';
10869 if (!is_numeric($show_empty)) {
10870 $out .= $show_empty;
10871 } else {
10872 $out .= '&nbsp;';
10873 }
10874 $out .= '</option>';
10875 }
10876 $num = $this->db->num_rows($resql);
10877 if ($num) {
10878 while ($obj = $this->db->fetch_object($resql)) {
10879 $labeltoshow = dol_trunc($obj->title, 18); // Invoice ref
10880
10881 $disabled = 0;
10882 if (!empty($obj->suspended)) {
10883 $disabled = 1;
10884 $labeltoshow .= ' - ' . $langs->trans("Closed");
10885 }
10886
10887
10888 if (!empty($selected) && $selected == $obj->rowid) {
10889 $out .= '<option value="' . $obj->rowid . '" selected';
10890 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10891 $out .= '>' . $labeltoshow . '</option>';
10892 } else {
10893 if ($disabled && ($selected != $obj->rowid)) {
10894 $resultat = '';
10895 } else {
10896 $resultat = '<option value="' . $obj->rowid . '"';
10897 if ($disabled) {
10898 $resultat .= ' disabled';
10899 }
10900 $resultat .= '>';
10901 $resultat .= $labeltoshow;
10902 $resultat .= '</option>';
10903 }
10904 $out .= $resultat;
10905 }
10906 }
10907 }
10908 if (empty($option_only)) {
10909 $out .= '</select>';
10910 }
10911
10912 print $out;
10913
10914 $this->db->free($resql);
10915 return $num;
10916 } else {
10917 $this->errors[] = $this->db->lasterror;
10918 return -1;
10919 }
10920 }
10921
10931 public function searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput = array(), $search_component_params_hidden = '')
10932 {
10933 global $langs;
10934
10935 if ($search_component_params_hidden != '' && !preg_match('/^\‍(.*\‍)$/', $search_component_params_hidden)) { // If $search_component_params_hidden does not start and end with ()
10936 $search_component_params_hidden = '(' . $search_component_params_hidden . ')';
10937 }
10938
10939 $ret = '';
10940
10941 $ret .= '<div class="divadvancedsearchfieldcomp centpercent inline-block">';
10942 $ret .= '<a href="#" class="dropdownsearch-toggle unsetcolor">';
10943 $ret .= '<span class="fas fa-filter linkobject boxfilter paddingright pictofixedwidth" title="' . dol_escape_htmltag($langs->trans("Filters")) . '" id="idsubimgproductdistribution"></span>';
10944 $ret .= '</a>';
10945
10946 $ret .= '<div class="divadvancedsearchfieldcompinput inline-block minwidth500 maxwidth300onsmartphone">';
10947
10948 // Show select fields as tags.
10949 $ret .= '<div id="divsearch_component_params" name="divsearch_component_params" class="noborderbottom search_component_params inline-block valignmiddle">';
10950
10951 if ($search_component_params_hidden) {
10952 // Split the criteria on each AND
10953 //var_dump($search_component_params_hidden);
10954
10955 $arrayofandtags = dolForgeExplodeAnd($search_component_params_hidden);
10956
10957 // $arrayofandtags is now array( '...' , '...', ...)
10958 // Show each AND part
10959 foreach ($arrayofandtags as $tmpkey => $tmpval) {
10960 $errormessage = '';
10961 $searchtags = forgeSQLFromUniversalSearchCriteria($tmpval, $errormessage, 1, 1);
10962 if ($errormessage) {
10963 $this->error = 'ERROR in parsing search string: '.$errormessage;
10964 }
10965 // Remove first and last parenthesis but only if first is the opening and last the closing of the same group
10966 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
10967 $searchtags = removeGlobalParenthesis($searchtags);
10968
10969 $ret .= '<span class="marginleftonlyshort valignmiddle tagsearch" data-ufilterid="'.($tmpkey + 1).'" data-ufilter="'.dol_escape_htmltag($tmpval).'">';
10970 $ret .= '<span class="tagsearchdelete select2-selection__choice__remove" data-ufilterid="'.($tmpkey + 1).'">x</span> ';
10971 $ret .= dol_escape_htmltag($searchtags);
10972 $ret .= '</span>';
10973 }
10974 }
10975
10976 //$ret .= '<button type="submit" class="liste_titre button_search paddingleftonly" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
10977
10978 //$ret .= search_component_params
10979 //$texttoshow = '<div class="opacitymedium inline-block search_component_searchtext">'.$langs->trans("Search").'</div>';
10980 //$ret .= '<div class="search_component inline-block valignmiddle">'.$texttoshow.'</div>';
10981
10982 $show_search_component_params_hidden = 1;
10983 if ($show_search_component_params_hidden) {
10984 $ret .= '<input type="hidden" name="show_search_component_params_hidden" value="1">';
10985 }
10986 $ret .= "<!-- We store the full Universal Search String into this field. For example: (t.ref:like:'SO-%') AND ((t.ref:like:'CO-%') OR (t.ref:like:'AA%')) -->";
10987 $ret .= '<input type="hidden" id="search_component_params_hidden" name="search_component_params_hidden" value="' . dol_escape_htmltag($search_component_params_hidden) . '">';
10988 // $ret .= "<!-- sql= ".forgeSQLFromUniversalSearchCriteria($search_component_params_hidden, $errormessage)." -->";
10989
10990 // For compatibility with forms that show themself the search criteria in addition of this component, we output these fields
10991 foreach ($arrayofcriterias as $criteria) {
10992 foreach ($criteria as $criteriafamilykey => $criteriafamilyval) {
10993 if (in_array('search_' . $criteriafamilykey, $arrayofinputfieldsalreadyoutput)) {
10994 continue;
10995 }
10996 if (in_array($criteriafamilykey, array('rowid', 'ref_ext', 'entity', 'extraparams'))) {
10997 continue;
10998 }
10999 if (in_array($criteriafamilyval['type'], array('date', 'datetime', 'timestamp'))) {
11000 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_start">';
11001 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startyear">';
11002 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startmonth">';
11003 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startday">';
11004 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_end">';
11005 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endyear">';
11006 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endmonth">';
11007 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endday">';
11008 } else {
11009 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '">';
11010 }
11011 }
11012 }
11013
11014 $ret .= '</div>';
11015
11016 $ret .= "<!-- Field to enter a generic filter string: t.ref:like:'SO-%', t.date_creation:<:'20160101', t.date_creation:<:'2016-01-01 12:30:00', t.nature:is:NULL, t.field2:isnot:NULL -->\n";
11017 $ret .= '<input type="text" placeholder="' . $langs->trans("Filters") . '" id="search_component_params_input" name="search_component_params_input" class="noborderbottom search_component_input" value="">';
11018
11019 $ret .= '</div>';
11020 $ret .= '</div>';
11021
11022 $ret .= '<script>
11023 jQuery(".tagsearchdelete").click(function(e) {
11024 var filterid = $(this).parents().attr("data-ufilterid");
11025 console.log("We click to delete the criteria nb "+filterid);
11026
11027 // Regenerate the search_component_params_hidden with all data-ufilter except the one to delete, and post the page
11028 var newparamstring = \'\';
11029 $(\'.tagsearch\').each(function(index, element) {
11030 tmpfilterid = $(this).attr("data-ufilterid");
11031 if (tmpfilterid != filterid) {
11032 // We keep this criteria
11033 if (newparamstring == \'\') {
11034 newparamstring = $(this).attr("data-ufilter");
11035 } else {
11036 newparamstring = newparamstring + \' AND \' + $(this).attr("data-ufilter");
11037 }
11038 }
11039 });
11040 console.log("newparamstring = "+newparamstring);
11041
11042 jQuery("#search_component_params_hidden").val(newparamstring);
11043
11044 // We repost the form
11045 $(this).closest(\'form\').submit();
11046 });
11047
11048 jQuery("#search_component_params_input").keydown(function(e) {
11049 console.log("We press a key on the filter field that is "+jQuery("#search_component_params_input").val());
11050 console.log(e.which);
11051 if (jQuery("#search_component_params_input").val() == "" && e.which == 8) {
11052 /* We click on back when the input field is already empty */
11053 event.preventDefault();
11054 jQuery("#divsearch_component_params .tagsearch").last().remove();
11055 /* Regenerate content of search_component_params_hidden from remaining .tagsearch */
11056 var s = "";
11057 jQuery("#divsearch_component_params .tagsearch").each(function( index ) {
11058 if (s != "") {
11059 s = s + " AND ";
11060 }
11061 s = s + $(this).attr("data-ufilter");
11062 });
11063 console.log("New value for search_component_params_hidden = "+s);
11064 jQuery("#search_component_params_hidden").val(s);
11065 }
11066 });
11067
11068 </script>
11069 ';
11070
11071 return $ret;
11072 }
11073
11083 public function selectModelMail($prefix, $modelType = '', $default = 0, $addjscombo = 0)
11084 {
11085 global $langs, $user;
11086
11087 $retstring = '';
11088
11089 $TModels = array();
11090
11091 include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
11092 $formmail = new FormMail($this->db);
11093 $result = $formmail->fetchAllEMailTemplate($modelType, $user, $langs);
11094
11095 if ($default) {
11096 $TModels[0] = $langs->trans('DefaultMailModel');
11097 }
11098 if ($result > 0) {
11099 foreach ($formmail->lines_model as $model) {
11100 $TModels[$model->id] = $model->label;
11101 }
11102 }
11103
11104 $retstring .= '<select class="flat" id="select_' . $prefix . 'model_mail" name="' . $prefix . 'model_mail">';
11105
11106 foreach ($TModels as $id_model => $label_model) {
11107 $retstring .= '<option value="' . $id_model . '"';
11108 $retstring .= ">" . $label_model . "</option>";
11109 }
11110
11111 $retstring .= "</select>";
11112
11113 if ($addjscombo) {
11114 $retstring .= ajax_combobox('select_' . $prefix . 'model_mail');
11115 }
11116
11117 return $retstring;
11118 }
11119
11131 public function buttonsSaveCancel($save_label = 'Save', $cancel_label = 'Cancel', $morebuttons = array(), $withoutdiv = false, $morecss = '', $dol_openinpopup = '')
11132 {
11133 global $langs;
11134
11135 $buttons = array();
11136
11137 $save = array(
11138 'name' => 'save',
11139 'label_key' => $save_label,
11140 );
11141
11142 if ($save_label == 'Create' || $save_label == 'Add') {
11143 $save['name'] = 'add';
11144 } elseif ($save_label == 'Modify') {
11145 $save['name'] = 'edit';
11146 }
11147
11148 $cancel = array(
11149 'name' => 'cancel',
11150 'label_key' => 'Cancel',
11151 );
11152
11153 !empty($save_label) ? $buttons[] = $save : '';
11154
11155 if (!empty($morebuttons)) {
11156 $buttons[] = $morebuttons;
11157 }
11158
11159 !empty($cancel_label) ? $buttons[] = $cancel : '';
11160
11161 $retstring = $withoutdiv ? '' : '<div class="center">';
11162
11163 foreach ($buttons as $button) {
11164 $addclass = empty($button['addclass']) ? '' : $button['addclass'];
11165 $retstring .= '<input type="submit" class="button button-' . $button['name'] . ($morecss ? ' ' . $morecss : '') . ' ' . $addclass . '" name="' . $button['name'] . '" value="' . dol_escape_htmltag($langs->trans($button['label_key'])) . '">';
11166 }
11167 $retstring .= $withoutdiv ? '' : '</div>';
11168
11169 if ($dol_openinpopup) {
11170 $retstring .= '<!-- buttons are shown into a $dol_openinpopup=' . dol_escape_htmltag($dol_openinpopup) . ' context, so we enable the close of dialog on cancel -->' . "\n";
11171 $retstring .= '<script nonce="' . getNonce() . '">';
11172 $retstring .= 'jQuery(".button-cancel").click(function(e) {
11173 e.preventDefault(); console.log(\'We click on cancel in iframe popup ' . dol_escape_js($dol_openinpopup) . '\');
11174 window.parent.jQuery(\'#idfordialog' . dol_escape_js($dol_openinpopup) . '\').dialog(\'close\');
11175 });';
11176 $retstring .= '</script>';
11177 }
11178
11179 return $retstring;
11180 }
11181
11182
11183 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
11184
11191 {
11192 // phpcs:enable
11193 global $langs;
11194
11195 $num = count($this->cache_invoice_subtype);
11196 if ($num > 0) {
11197 return 0; // Cache already loaded
11198 }
11199
11200 dol_syslog(__METHOD__, LOG_DEBUG);
11201
11202 $sql = "SELECT rowid, code, label as label";
11203 $sql .= " FROM " . MAIN_DB_PREFIX . 'c_invoice_subtype';
11204 $sql .= " WHERE active = 1";
11205
11206 $resql = $this->db->query($sql);
11207 if ($resql) {
11208 $num = $this->db->num_rows($resql);
11209 $i = 0;
11210 while ($i < $num) {
11211 $obj = $this->db->fetch_object($resql);
11212
11213 // If translation exists, we use it, otherwise we take the default wording
11214 $label = ($langs->trans("InvoiceSubtype" . $obj->rowid) != "InvoiceSubtype" . $obj->rowid) ? $langs->trans("InvoiceSubtype" . $obj->rowid) : (($obj->label != '-') ? $obj->label : '');
11215 $this->cache_invoice_subtype[$obj->rowid]['rowid'] = $obj->rowid;
11216 $this->cache_invoice_subtype[$obj->rowid]['code'] = $obj->code;
11217 $this->cache_invoice_subtype[$obj->rowid]['label'] = $label;
11218 $i++;
11219 }
11220
11221 $this->cache_invoice_subtype = dol_sort_array($this->cache_invoice_subtype, 'code', 'asc', 0, 0, 1);
11222
11223 return $num;
11224 } else {
11225 dol_print_error($this->db);
11226 return -1;
11227 }
11228 }
11229
11230
11241 public function getSelectInvoiceSubtype($selected = 0, $htmlname = 'subtypeid', $addempty = 0, $noinfoadmin = 0, $morecss = '')
11242 {
11243 global $langs, $user;
11244
11245 $out = '';
11246 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
11247
11249
11250 $out .= '<select id="' . $htmlname . '" class="flat selectsubtype' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
11251 if ($addempty) {
11252 $out .= '<option value="0">&nbsp;</option>';
11253 }
11254
11255 foreach ($this->cache_invoice_subtype as $rowid => $subtype) {
11256 $label = $subtype['label'];
11257 $out .= '<option value="' . $subtype['rowid'] . '"';
11258 if ($selected == $subtype['rowid']) {
11259 $out .= ' selected="selected"';
11260 }
11261 $out .= '>';
11262 $out .= $label;
11263 $out .= '</option>';
11264 }
11265
11266 $out .= '</select>';
11267 if ($user->admin && empty($noinfoadmin)) {
11268 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
11269 }
11270 $out .= ajax_combobox($htmlname);
11271
11272 return $out;
11273 }
11274}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition security.php:637
ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLength=2, $autoselect=0, $ajaxoptions=array(), $moreparams='')
Generic function that return javascript to add to transform a common input text or select field into ...
Definition ajax.lib.php:48
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:456
ajax_multiautocompleter($htmlname, $fields, $url, $option='', $minLength=2, $autoselect=0)
Generic function that return javascript to add to a page to transform a common input text field into ...
Definition ajax.lib.php:305
ajax_event($htmlname, $events)
Add event management script.
Definition ajax.lib.php:559
$object ref
Definition info.php:79
Class to manage bank accounts.
Class to manage categories.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage contact/addresses.
Class to manage a WYSIWYG editor.
DAO Resource object.
const STATUS_OPEN_INTERNAL
Warehouse open and only operations for stock transfers/corrections allowed (not for customer shipping...
const STATUS_OPEN_ALL
Warehouse open and any operations are allowed (customer shipping, supplier dispatch,...
const STATUS_CLOSED
Warehouse closed, inactive.
Class to manage standard extra languages.
Class to manage invoices.
Class to manage generation of HTML components Only common components must be here.
selectModelMail($prefix, $modelType='', $default=0, $addjscombo=0)
selectModelMail
showFilterButtons($pos='')
Return HTML to show the search and clear search button.
selectyesno($htmlname, $value='', $option=0, $disabled=false, $useempty=0, $addjscombo=0, $morecss='', $labelyes='Yes', $labelno='No')
Return an html string with a select combo box to choose yes or no.
load_cache_vatrates($country_code)
Load into the cache ->cache_vatrates, all the vat rates of a country.
formInputReason($page, $selected='', $htmlname='demandreason', $addempty=0)
Output HTML form to select list of input reason (events that triggered an object creation,...
editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata='string', $editvalue='', $extObject=null, $custommsg=null, $moreparam='', $notabletag=1, $formatfunc='', $paramid='id', $gm='auto', $moreoptions=array(), $editaction='')
Output value of a field for an editable field.
form_availability($page, $selected='', $htmlname='availability', $addempty=0)
Show a form to select a delivery delay.
showLinkedObjectBlock($object, $morehtmlright='', $compatibleImportElementsList=array(), $title='RelatedObjects')
Show linked object block.
select_produits_fournisseurs($socid, $selected='', $htmlname='productid', $filtertype='', $filtre='', $ajaxoptions=array(), $hidelabel=0, $alsoproductwithnosupplierprice=0, $morecss='', $placeholder='')
Return list of products for customer (in Ajax if Ajax activated or go to select_produits_fournisseurs...
selectMassAction($selected, $arrayofaction, $alwaysvisible=0, $name='massaction', $cssclass='checkforselect')
Generate select HTML to choose massaction.
select_dolresources_forevent($action='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include=array(), $enableonly=array(), $force_entity='0', $maxlength=0, $showstatus=0, $morefilter='', $showproperties=0, $listofresourceid=array())
Return select list of resources.
formconfirm($page, $title, $question, $action, $formquestion='', $selectedchoice='', $useajax=0, $height=0, $width=500, $disableformtag=0, $labelbuttonyes='Yes', $labelbuttonno='No')
form_multicurrency_code($page, $selected='', $htmlname='multicurrency_code')
Show form with multicurrency code.
select_produits($selected=0, $htmlname='productid', $filtertype='', $limit=0, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(), $socid=0, $showempty='1', $forcecombo=0, $morecss='', $hidepriceinlabel=0, $warehouseStatus='', $selected_combinations=null, $nooutput=0, $status_purchase=-1)
Return list of products for customer.
showFilterAndCheckAddButtons($addcheckuncheckall=0, $cssclass='checkforaction', $calljsfunction=0, $massactionname="massaction")
Return HTML to show the search and clear search button.
select_company($selected='', $htmlname='socid', $filter='', $showempty='', $showtype=0, $forcecombo=0, $events=array(), $limit=0, $morecss='minwidth100', $moreparam='', $selected_input_value='', $hidelabel=1, $ajaxoptions=array(), $multiple=false, $excludeids=array(), $showcode=0)
Output html form to select a third party This call select_thirdparty_list() or ajax depending on setu...
textwithpicto($text, $htmltext, $direction=1, $type='help', $extracss='', $noencodehtmltext=0, $notabs=3, $tooltiptrigger='', $forcenowrap=0)
Show a text with a picto and a tooltip on picto.
select_dolgroups($selected=0, $htmlname='groupid', $show_empty=0, $exclude='', $disabled=0, $include='', $enableonly=array(), $force_entity='0', $multiple=false, $morecss='minwidth200')
Return select list of groups.
selectInputReason($selected='', $htmlname='demandreasonid', $exclude='', $addempty=0, $morecss='', $notooltip=0)
Return list of input reason (events that triggered an object creation, like after sending an emailing...
select_produits_list($selected=0, $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $filterkey='', $status=1, $finished=2, $outputmode=0, $socid=0, $showempty='1', $forcecombo=0, $morecss='maxwidth500', $hidepriceinlabel=0, $warehouseStatus='', $status_purchase=-1)
Return list of products for a customer.
select_dolusers_forevent($action='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include=array(), $enableonly=array(), $force_entity='0', $maxlength=0, $showstatus=0, $morefilter='', $showproperties=0, $listofuserid=array(), $listofcontactid=array(), $listofotherid=array())
Return select list of users.
select_contact($socid, $selected='', $htmlname='contactid', $showempty=0, $exclude='', $limitto='', $showfunction=0, $morecss='', $nokeyifsocid=true, $showsoc=0, $forcecombo=0, $events=array(), $moreparam='', $htmlid='', $selected_input_value='', $filter='')
Output html form to select a contact This call select_contacts() or ajax depending on setup.
select_incoterms($selected='', $location_incoterms='', $page='', $htmlname='incoterm_id', $htmloption='', $forcecombo=1, $events=array(), $disableautocomplete=0)
Return select list of incoterms.
selectDate($set_time='', $prefix='re', $h=0, $m=0, $empty=0, $form_name="", $d=1, $addnowlink=0, $disabled=0, $fullday='', $addplusone='', $adddateof='', $openinghours='', $stepminutes=1, $labeladddateof='', $placeholder='', $gm='auto')
Show a HTML widget to input a date or combo list for day, month, years and optionally hours and minut...
select_types_paiements($selected='', $htmlname='paiementtype', $filtertype='', $format=0, $empty=1, $noadmininfo=0, $maxlength=0, $active=1, $morecss='', $nooutput=0)
Return list of payment methods Constant MAIN_DEFAULT_PAYMENT_TYPE_ID can used to set default value bu...
select_currency($selected='', $htmlname='currency_id')
Retourne la liste des devises, dans la langue de l'utilisateur.
formSelectTransportMode($page, $selected='', $htmlname='transport_mode_id', $active=1, $addempty=0)
Show form with transport mode.
selectShippingMethod($selected='', $htmlname='shipping_method_id', $filtre='', $useempty=0, $moreattrib='', $noinfoadmin=0, $morecss='')
Return a HTML select list of shipping mode.
formSelectShippingMethod($page, $selected='', $htmlname='shipping_method_id', $addempty=0)
Display form to select shipping mode.
getSelectInvoiceSubtype($selected=0, $htmlname='subtypeid', $addempty=0, $noinfoadmin=0, $morecss='')
Return list of invoice subtypes.
form_contacts($page, $societe, $selected='', $htmlname='contactid')
Show forms to select a contact.
selectMultiCurrency($selected='', $htmlname='multicurrency_code', $useempty=0, $filter='', $excludeConfCurrency=false, $morecss='')
Return array of currencies in user language.
load_tva($htmlname='tauxtva', $selectedrate='', $societe_vendeuse=null, $societe_acheteuse=null, $idprod=0, $info_bits=0, $type='', $options_only=false, $mode=0, $type_vat=0)
Output an HTML select vat rate.
form_multicurrency_rate($page, $rate=0.0, $htmlname='multicurrency_tx', $currency='')
Show form with multicurrency rate.
load_cache_availability()
select_bom($selected='', $htmlname='bom_id', $limit=0, $status=1, $type=0, $showempty='1', $morecss='', $nooutput='', $forcecombo=0, $TProducts=[])
Return list of BOM for customer in Ajax if Ajax activated or go to select_produits_list.
selectcontacts($socid, $selected=array(), $htmlname='contactid', $showempty=0, $exclude='', $limitto='', $showfunction=0, $morecss='', $options_only=0, $showsoc=0, $forcecombo=0, $events=array(), $moreparam='', $htmlid='', $multiple=false, $disableifempty=0, $filter='')
Return HTML code of the SELECT of list of all contacts (for a third party or all).
static selectarray($htmlname, $array, $id='', $show_empty=0, $key_in_label=0, $value_as_key=0, $moreparam='', $translate=0, $maxlen=0, $disabled=0, $sort='', $morecss='minwidth75', $addjscombo=1, $moreparamonempty='', $disablebademail=0, $nohtmlescape=0)
Return a HTML select string, built from an array of key+value.
selectMembersList($selected='', $htmlname='adherentid', $filtertype='', $limit=20, $filterkey='', $status=1, $outputmode=0, $showempty='1', $forcecombo=0, $morecss='')
Return list of adherents.
select_type_fees($selected='', $htmlname='type', $showempty=0)
Return list of types of notes.
selectInvoiceRec($selected='', $htmlname='facrecid', $maxlength=24, $option_only=0, $show_empty='1', $forcefocus=0, $disabled=0, $morecss='maxwidth500')
Output a combo list with invoices qualified for a third party.
editInPlace($object, $value, $htmlname, $condition, $inputType='textarea', $editvalue=null, $extObject=null, $custommsg=null)
Output edit in place form.
selectUnits($selected='', $htmlname='units', $showempty=0, $unit_type='')
Creates HTML units selector (code => label)
select_produits_fournisseurs_list($socid, $selected='', $htmlname='productid', $filtertype='', $filtre='', $filterkey='', $statut=-1, $outputmode=0, $limit=100, $alsoproductwithnosupplierprice=0, $morecss='', $showstockinlist=0, $placeholder='')
Return list of suppliers products.
selectTicketsList($selected='', $htmlname='ticketid', $filtertype='', $limit=20, $filterkey='', $status=1, $outputmode=0, $showempty='1', $forcecombo=0, $morecss='')
Return list of tickets.
form_modes_reglement($page, $selected='', $htmlname='mode_reglement_id', $filtertype='', $active=1, $addempty=0, $type='', $nooutput=0)
Show form with payment mode.
constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel=0, $filterkey='', $novirtualstock=0)
Function to forge the string with OPTIONs of SELECT.
showLinkToObjectBlock($object, $restrictlinksto=array(), $excludelinksto=array())
Show block with links to link to other objects.
form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter='', $maxvalue=0, $more='', $hidelist=0, $discount_type=0)
Show a select box with available absolute discounts.
buttonsSaveCancel($save_label='Save', $cancel_label='Cancel', $morebuttons=array(), $withoutdiv=false, $morecss='', $dol_openinpopup='')
Output the buttons to submit a creation/edit form.
selectTransportMode($selected='', $htmlname='transportmode', $format=0, $empty=1, $noadmininfo=0, $maxlength=0, $active=1, $morecss='')
static showphoto($modulepart, $object, $width=100, $height=0, $caneditfield=0, $cssclass='photowithmargin', $imagesize='', $addlinktofullsize=1, $cache=0, $forcecapture='', $noexternsourceoverwrite=0)
Return HTML code to output a photo.
selectProjectsList($selected='', $htmlname='projectid', $filtertype='', $limit=20, $filterkey='', $status=1, $outputmode=0, $showempty='1', $forcecombo=0, $morecss='')
Return list of projects.
form_conditions_reglement($page, $selected='', $htmlname='cond_reglement_id', $addempty=0, $type='', $filtertype=-1, $deposit_percent=-1, $nooutput=0)
Show a form to select payment conditions.
selectSituationInvoices($selected='', $socid=0)
Creates HTML last in cycle situation invoices selector.
loadCacheInputReason()
Load into cache cache_demand_reason, array of input reasons.
selectPriceBaseType($selected='', $htmlname='price_base_type', $addjscombo=0)
Selection HT or TTC.
load_cache_transport_mode()
select_conditions_paiements($selected=0, $htmlname='condid', $filtertype=-1, $addempty=0, $noinfoadmin=0, $morecss='', $deposit_percent=-1, $noprint=0)
print list of payment modes.
select_remises($selected, $htmlname, $filter, $socid, $maxvalue=0)
Return HTML combo list of absolute discounts.
showbarcode(&$object, $width=100, $morecss='')
Return HTML code to output a barcode.
form_confirm($page, $title, $question, $action, $formquestion=array(), $selectedchoice="", $useajax=0, $height=170, $width=500)
load_cache_conditions_paiements()
form_project($page, $socid, $selected='', $htmlname='projectid', $discard_closed=0, $maxlength=20, $forcefocus=0, $nooutput=0, $textifnoproject='', $morecss='')
Show a form to select a project.
selectExpenseCategories($selected='', $htmlname='fk_c_exp_tax_cat', $useempty=0, $excludeid=array(), $target='', $default_selected=0, $params=array(), $info_admin=1)
Return HTML to show the select of expense categories.
select_product_fourn_price($productid, $htmlname='productfournpriceid', $selected_supplier=0)
Return list of suppliers prices for a product.
select_country($selected='', $htmlname='country_id', $htmloption='', $maxlength=0, $morecss='minwidth300', $usecodeaskey='', $showempty=1, $disablefavorites=0, $addspecialentries=0, $exclude_country_code=array(), $hideflags=0)
Return combo list of activated countries, into language of user.
select_type_of_lines($selected='', $htmlname='type', $showempty=0, $hidetext=0, $forceall=0, $morecss="")
Return list of types of lines (product or service) Example: 0=product, 1=service, 9=other (for extern...
form_date($page, $selected, $htmlname, $displayhour=0, $displaymin=0, $nooutput=0, $type='')
Show a form + html select a date.
showCheckAddButtons($cssclass='checkforaction', $calljsfunction=0, $massactionname="massaction")
Return HTML to show the search and clear search button.
__construct($db)
Constructor.
select_thirdparty_list($selected='', $htmlname='socid', $filter='', $showempty='', $showtype=0, $forcecombo=0, $events=array(), $filterkey='', $outputmode=0, $limit=0, $morecss='minwidth100', $moreparam='', $multiple=false, $excludeids=array(), $showcode=0)
Output html form to select a third party.
select_users($selected='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly=array(), $force_entity='0')
Return the HTML select list of users.
select_all_categories($type, $selected='', $htmlname="parent", $maxlength=64, $fromid=0, $outputmode=0, $include=0, $morecss='', $useempty=1)
Return list of categories having chosen type.
static selectArrayFilter($htmlname, $array, $id='', $moreparam='', $disableFiltering=0, $disabled=0, $minimumInputLength=1, $morecss='', $callurlonselect=0, $placeholder='', $acceptdelayedhtml=0, $textfortitle='')
Return a HTML select string, built from an array of key+value, but content returned into select is de...
select_date($set_time='', $prefix='re', $h=0, $m=0, $empty=0, $form_name="", $d=1, $addnowlink=0, $nooutput=0, $disabled=0, $fullday=0, $addplusone='', $adddateof='')
Show a HTML widget to input a date or combo list for day, month, years and optionally hours and minut...
load_cache_invoice_subtype()
Load into cache list of invoice subtypes.
select_export_model($selected='', $htmlname='exportmodelid', $type='', $useempty=0)
Return list of export templates.
selectDateToDate($set_time='', $set_time_end='', $prefix='re', $empty=0, $forcenewline=0)
Show 2 HTML widget to input a date or combo list for day, month, years and optionally hours and minut...
textwithtooltip($text, $htmltext, $tooltipon=1, $direction=0, $img='', $extracss='', $notabs=3, $incbefore='', $noencodehtmltext=0, $tooltiptrigger='', $forcenowrap=0)
Show a text and picto with tooltip on text or picto.
searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput=array(), $search_component_params_hidden='')
Output the component to make advanced search criteries.
select_dolusers($selected='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly='', $force_entity='', $maxlength=0, $showstatus=0, $morefilter='', $show_every=0, $enableonlytext='', $morecss='', $notdisabled=0, $outputmode=0, $multiple=false, $forcecombo=0)
Return select list of users.
getSelectConditionsPaiements($selected=0, $htmlname='condid', $filtertype=-1, $addempty=0, $noinfoadmin=0, $morecss='', $deposit_percent=-1)
Return list of payment modes.
widgetForTranslation($fieldname, $object, $perm, $typeofdata='string', $check='', $morecss='')
Output edit in place form.
load_cache_types_fees()
Load into cache cache_types_fees, array of types of fees.
static multiselectarray($htmlname, $array, $selected=array(), $key_in_label=0, $value_as_key=0, $morecss='', $translate=0, $width=0, $moreattrib='', $elemtype='', $placeholder='', $addjscombo=-1)
Show a multiselect form from an array.
form_thirdparty($page, $selected='', $htmlname='socid', $filter='', $showempty=0, $showtype=0, $forcecombo=0, $events=array(), $nooutput=0, $excludeids=array(), $textifnothirdparty='')
Output html select to select thirdparty.
selectEstablishments($selected='', $htmlname='entity', $status=0, $filtre='', $useempty=0, $moreattrib='')
Return a HTML select list of establishment.
formSelectAccount($page, $selected='', $htmlname='fk_account', $addempty=0)
Display form to select bank account.
form_users($page, $selected='', $htmlname='userid', $exclude=array(), $include=array())
Show a select form to choose a user.
editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata='string', $moreparam='', $fieldrequired=0, $notabletag=0, $paramid='id', $help='')
Output key field for an editable field.
showCategories($id, $type, $rendermode=0, $nolink=0)
Render list of categories linked to object with id $id and type $type.
load_cache_types_paiements()
selectAvailabilityDelay($selected='', $htmlname='availid', $filtertype='', $addempty=0, $morecss='')
Return the list of type of delay available.
selectCurrency($selected='', $htmlname='currency_id', $mode=0, $useempty='')
Retourne la liste des devises, dans la langue de l'utilisateur.
select_comptes($selected='', $htmlname='accountid', $status=0, $filtre='', $useempty=0, $moreattrib='', $showcurrency=0, $morecss='', $nooutput=0)
Return a HTML select list of bank accounts.
showrefnav($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $morehtmlright='')
Return a HTML area with the reference of object and a navigation bar for a business object Note: To c...
Class permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new Form...
Class to manage building of HTML components.
Class to manage forms for the module resource.
Class to manage hooks.
Class for MyObject.
Class to parse product price expressions.
Class to manage predefined suppliers products.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
currency_name($code_iso, $withcode=0, $outputlangs=null)
Return label of currency or code+label.
isInEEC($object)
Return if a country of an object is inside the EEC (European Economic Community)
getServerTimeZoneInt($refgmtdate='now')
Return server timezone int.
Definition date.lib.php:86
removeGlobalParenthesis($string)
Remove first and last parenthesis but only if first is the opening and last the closing of the same g...
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dolForgeExplodeAnd($sqlfilters)
Explode an universal search string with AND parts.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
dol_print_phone($phone, $countrycode='', $cid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0, $morecss='')
Format phone numbers according to country.
picto_from_langcode($codelang, $moreatt='', $notitlealt=0)
Return img flag of country for a language code or country code.
img_help($usehelpcursor=1, $usealttitle=1)
Show help logo with cursor "?".
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
currentToken()
Return the value of token currently saved into session with name 'token'.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
dol_print_url($url, $target='_blank', $max=32, $withpicto=0, $morecss='')
Show Url link.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_print_email($email, $cid=0, $socid=0, $addlink=0, $max=64, $showinvalid=1, $withpicto=0)
Show EMail link formatted for HTML output.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles=1, $removeclassattribute=1, $cleanalsojavascript=0, $allowiframe=0, $allowed_tags=array(), $allowlink=0)
Clean a string to keep only desirable HTML tags.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
dol_string_neverthesehtmltags($stringtoclean, $disallowed_tags=array('textarea'), $cleanalsosomestyles=0)
Clean a string from some undesirable HTML tags.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that returns whether VAT must be recoverable collected VAT (e.g.: VAT NPR in France)
dol_htmlentities($string, $flags=ENT_QUOTES|ENT_SUBSTITUTE, $encoding='UTF-8', $double_encode=false)
Replace htmlentities functions.
getImageFileNameForSize($file, $extName, $extImgTarget='')
Return the filename of file to get the thumbs.
getAdvancedPreviewUrl($modulepart, $relativepath, $alldata=0, $param='')
Return URL we can use for advanced preview links.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dolIsAllowedForPreview($file)
Return if a file is qualified for preview.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getNonce()
Return a random string to be used as a nonce value for js.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox=0, $check='restricthtml')
Sanitize a HTML to remove js, dangerous content and external link.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
a disabled
ui state ui widget content ui state ui widget header ui state a ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
testSqlAndScriptInject($val, $type)
Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET,...
Definition main.inc.php:123
measuringUnitString($unit, $measuring_style='', $scale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:137
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140
getMaxFileSizeArray()
Return the max allowed for file upload.
dol_hash($chain, $type='0', $nosalt=0)
Returns a hash (non reversible encryption) of a string.