dolibarr 20.0.2
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 // include search in supplier ref
3003 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
3004 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
3005 }
3006
3007 //Price by customer
3008 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
3009 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_customer_price as pcp ON pcp.fk_soc=" . ((int) $socid) . " AND pcp.fk_product=p.rowid";
3010 }
3011 // Units
3012 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3013 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3014 }
3015 // Multilang : we add translation
3016 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3017 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_lang as pl ON pl.fk_product = p.rowid ";
3018 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE') && !empty($socid)) {
3019 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
3020 $soc = new Societe($this->db);
3021 $result = $soc->fetch($socid);
3022 if ($result > 0 && !empty($soc->default_lang)) {
3023 $sql .= " AND pl.lang = '" . $this->db->escape($soc->default_lang) . "'";
3024 } else {
3025 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
3026 }
3027 } else {
3028 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
3029 }
3030 }
3031
3032 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
3033 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_attribute_combination pac ON pac.fk_product_child = p.rowid";
3034 }
3035
3036 $sql .= ' WHERE p.entity IN (' . getEntity('product') . ')';
3037
3038 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
3039 $sql .= " AND pac.rowid IS NULL";
3040 }
3041
3042 if ($finished == 0) {
3043 $sql .= " AND p.finished = " . ((int) $finished);
3044 } elseif ($finished == 1) {
3045 $sql .= " AND p.finished = ".((int) $finished);
3046 }
3047 if ($status >= 0) {
3048 $sql .= " AND p.tosell = ".((int) $status);
3049 }
3050 if ($status_purchase >= 0) {
3051 $sql .= " AND p.tobuy = " . ((int) $status_purchase);
3052 }
3053 // Filter by product type
3054 if (strval($filtertype) != '') {
3055 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3056 } elseif (!isModEnabled('product')) { // when product module is disabled, show services only
3057 $sql .= " AND p.fk_product_type = 1";
3058 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
3059 $sql .= " AND p.fk_product_type = 0";
3060 }
3061 // Add where from hooks
3062 $parameters = array();
3063 $reshook = $hookmanager->executeHooks('selectProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3064 $sql .= $hookmanager->resPrint;
3065 // Add criteria on ref/label
3066 if ($filterkey != '') {
3067 $sql .= ' AND (';
3068 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3069 // For natural search
3070 $search_crit = explode(' ', $filterkey);
3071 $i = 0;
3072 if (count($search_crit) > 1) {
3073 $sql .= "(";
3074 }
3075 foreach ($search_crit as $crit) {
3076 if ($i > 0) {
3077 $sql .= " AND ";
3078 }
3079 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3080 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3081 $sql .= " OR pl.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3082 }
3083 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
3084 $sql .= " OR pcp.ref_customer LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3085 }
3086 if (getDolGlobalString('PRODUCT_AJAX_SEARCH_ON_DESCRIPTION')) {
3087 $sql .= " OR p.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3088 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3089 $sql .= " OR pl.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3090 }
3091 }
3092 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
3093 $sql .= " OR 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 $sql .= ')';
3105 }
3106 if (count($warehouseStatusArray)) {
3107 $sql .= " GROUP BY " . $selectFields;
3108 }
3109
3110 //Sort by category
3111 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
3112 $sql .= " ORDER BY categorie_product_id ";
3113 //ASC OR DESC order
3114 (getDolGlobalInt('PRODUCT_SORT_BY_CATEGORY') == 1) ? $sql .= "ASC" : $sql .= "DESC";
3115 } else {
3116 $sql .= $this->db->order("p.ref");
3117 }
3118
3119 $sql .= $this->db->plimit($limit, 0);
3120
3121 // Build output string
3122 dol_syslog(get_class($this) . "::select_produits_list search products", LOG_DEBUG);
3123 $result = $this->db->query($sql);
3124 if ($result) {
3125 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3126 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3127 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3128
3129 $num = $this->db->num_rows($result);
3130
3131 $events = array();
3132
3133 if (!$forcecombo) {
3134 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
3135 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
3136 }
3137
3138 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
3139
3140 $textifempty = '';
3141 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
3142 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
3143 if (getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3144 if ($showempty && !is_numeric($showempty)) {
3145 $textifempty = $langs->trans($showempty);
3146 } else {
3147 $textifempty .= $langs->trans("All");
3148 }
3149 } else {
3150 if ($showempty && !is_numeric($showempty)) {
3151 $textifempty = $langs->trans($showempty);
3152 }
3153 }
3154 if ($showempty) {
3155 $out .= '<option value="-1" selected>' . ($textifempty ? $textifempty : '&nbsp;') . '</option>';
3156 }
3157
3158 $i = 0;
3159 while ($num && $i < $num) {
3160 $opt = '';
3161 $optJson = array();
3162 $objp = $this->db->fetch_object($result);
3163
3164 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
3165 $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type";
3166 $sql .= " FROM " . $this->db->prefix() . "product_price_by_qty";
3167 $sql .= " WHERE fk_product_price = " . ((int) $objp->price_rowid);
3168 $sql .= " ORDER BY quantity ASC";
3169
3170 dol_syslog(get_class($this) . "::select_produits_list search prices by qty", LOG_DEBUG);
3171 $result2 = $this->db->query($sql);
3172 if ($result2) {
3173 $nb_prices = $this->db->num_rows($result2);
3174 $j = 0;
3175 while ($nb_prices && $j < $nb_prices) {
3176 $objp2 = $this->db->fetch_object($result2);
3177
3178 $objp->price_by_qty_rowid = $objp2->rowid;
3179 $objp->price_by_qty_price_base_type = $objp2->price_base_type;
3180 $objp->price_by_qty_quantity = $objp2->quantity;
3181 $objp->price_by_qty_unitprice = $objp2->unitprice;
3182 $objp->price_by_qty_remise_percent = $objp2->remise_percent;
3183 // For backward compatibility
3184 $objp->quantity = $objp2->quantity;
3185 $objp->price = $objp2->price;
3186 $objp->unitprice = $objp2->unitprice;
3187 $objp->remise_percent = $objp2->remise_percent;
3188
3189 //$objp->tva_tx is not overwritten by $objp2 value
3190 //$objp->default_vat_code is not overwritten by $objp2 value
3191
3192 $this->constructProductListOption($objp, $opt, $optJson, 0, $selected, $hidepriceinlabel, $filterkey);
3193
3194 $j++;
3195
3196 // Add new entry
3197 // "key" value of json key array is used by jQuery automatically as selected value
3198 // "label" value of json key array is used by jQuery automatically as text for combo box
3199 $out .= $opt;
3200 array_push($outarray, $optJson);
3201 }
3202 }
3203 } else {
3204 if (isModEnabled('dynamicprices') && !empty($objp->fk_price_expression)) {
3205 $price_product = new Product($this->db);
3206 $price_product->fetch($objp->rowid, '', '', 1);
3207
3208 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3209 $priceparser = new PriceParser($this->db);
3210 $price_result = $priceparser->parseProduct($price_product);
3211 if ($price_result >= 0) {
3212 $objp->price = $price_result;
3213 $objp->unitprice = $price_result;
3214 //Calculate the VAT
3215 $objp->price_ttc = (float) price2num($objp->price) * (1 + ($objp->tva_tx / 100));
3216 $objp->price_ttc = price2num($objp->price_ttc, 'MU');
3217 }
3218 }
3219
3220 $this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected, $hidepriceinlabel, $filterkey);
3221 // Add new entry
3222 // "key" value of json key array is used by jQuery automatically as selected value
3223 // "label" value of json key array is used by jQuery automatically as text for combo box
3224 $out .= $opt;
3225 array_push($outarray, $optJson);
3226 }
3227
3228 $i++;
3229 }
3230
3231 $out .= '</select>';
3232
3233 $this->db->free($result);
3234
3235 if (empty($outputmode)) {
3236 return $out;
3237 }
3238
3239 return $outarray;
3240 } else {
3241 dol_print_error($this->db);
3242 }
3243
3244 return '';
3245 }
3246
3262 protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0)
3263 {
3264 global $langs, $conf, $user;
3265 global $hookmanager;
3266
3267 $outkey = '';
3268 $outval = '';
3269 $outref = '';
3270 $outlabel = '';
3271 $outlabel_translated = '';
3272 $outdesc = '';
3273 $outdesc_translated = '';
3274 $outbarcode = '';
3275 $outorigin = '';
3276 $outtype = '';
3277 $outprice_ht = '';
3278 $outprice_ttc = '';
3279 $outpricebasetype = '';
3280 $outtva_tx = '';
3281 $outdefault_vat_code = '';
3282 $outqty = 1;
3283 $outdiscount = 0;
3284
3285 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3286
3287 $label = $objp->label;
3288 if (!empty($objp->label_translated)) {
3289 $label = $objp->label_translated;
3290 }
3291 if (!empty($filterkey) && $filterkey != '') {
3292 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3293 }
3294
3295 $outkey = $objp->rowid;
3296 $outref = $objp->ref;
3297 $outrefcust = empty($objp->custref) ? '' : $objp->custref;
3298 $outlabel = $objp->label;
3299 $outdesc = $objp->description;
3300 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3301 $outlabel_translated = $objp->label_translated;
3302 $outdesc_translated = $objp->description_translated;
3303 }
3304 $outbarcode = $objp->barcode;
3305 $outorigin = $objp->fk_country;
3306 $outpbq = empty($objp->price_by_qty_rowid) ? '' : $objp->price_by_qty_rowid;
3307
3308 $outtype = $objp->fk_product_type;
3309 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3310 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3311
3312 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3313 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
3314 }
3315
3316 // Units
3317 $outvalUnits = '';
3318 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3319 if (!empty($objp->unit_short)) {
3320 $outvalUnits .= ' - ' . $objp->unit_short;
3321 }
3322 }
3323 if (getDolGlobalString('PRODUCT_SHOW_DIMENSIONS_IN_COMBO')) {
3324 if (!empty($objp->weight) && $objp->weight_units !== null) {
3325 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3326 $outvalUnits .= ' - ' . $unitToShow;
3327 }
3328 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3329 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3330 $outvalUnits .= ' - ' . $unitToShow;
3331 }
3332 if (!empty($objp->surface) && $objp->surface_units !== null) {
3333 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3334 $outvalUnits .= ' - ' . $unitToShow;
3335 }
3336 if (!empty($objp->volume) && $objp->volume_units !== null) {
3337 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3338 $outvalUnits .= ' - ' . $unitToShow;
3339 }
3340 }
3341 if ($outdurationvalue && $outdurationunit) {
3342 $da = array(
3343 'h' => $langs->trans('Hour'),
3344 'd' => $langs->trans('Day'),
3345 'w' => $langs->trans('Week'),
3346 'm' => $langs->trans('Month'),
3347 'y' => $langs->trans('Year')
3348 );
3349 if (isset($da[$outdurationunit])) {
3350 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3351 }
3352 }
3353
3354 $opt = '<option value="' . $objp->rowid . '"';
3355 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
3356 if (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0) {
3357 $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 . '"';
3358 }
3359 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3360 if ($user->hasRight('stock', 'lire')) {
3361 if ($objp->stock > 0) {
3362 $opt .= ' class="product_line_stock_ok"';
3363 } elseif ($objp->stock <= 0) {
3364 $opt .= ' class="product_line_stock_too_low"';
3365 }
3366 }
3367 }
3368 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
3369 $opt .= ' data-labeltrans="' . $outlabel_translated . '"';
3370 $opt .= ' data-desctrans="' . dol_escape_htmltag($outdesc_translated) . '"';
3371 }
3372 $opt .= '>';
3373 $opt .= $objp->ref;
3374 if (!empty($objp->custref)) {
3375 $opt .= ' (' . $objp->custref . ')';
3376 }
3377 if ($outbarcode) {
3378 $opt .= ' (' . $outbarcode . ')';
3379 }
3380 $opt .= ' - ' . dol_trunc($label, $maxlengtharticle);
3381 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3382 $opt .= ' (' . getCountry($outorigin, 1) . ')';
3383 }
3384
3385 $objRef = $objp->ref;
3386 if (!empty($objp->custref)) {
3387 $objRef .= ' (' . $objp->custref . ')';
3388 }
3389 if (!empty($filterkey) && $filterkey != '') {
3390 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3391 }
3392 $outval .= $objRef;
3393 if ($outbarcode) {
3394 $outval .= ' (' . $outbarcode . ')';
3395 }
3396 $outval .= ' - ' . dol_trunc($label, $maxlengtharticle);
3397 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3398 $outval .= ' (' . getCountry($outorigin, 1) . ')';
3399 }
3400
3401 // Units
3402 $opt .= $outvalUnits;
3403 $outval .= $outvalUnits;
3404
3405 $found = 0;
3406
3407 // Multiprice
3408 // If we need a particular price level (from 1 to n)
3409 if (empty($hidepriceinlabel) && $price_level >= 1 && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3410 $sql = "SELECT price, price_ttc, price_base_type, tva_tx, default_vat_code";
3411 $sql .= " FROM " . $this->db->prefix() . "product_price";
3412 $sql .= " WHERE fk_product = " . ((int) $objp->rowid);
3413 $sql .= " AND entity IN (" . getEntity('productprice') . ")";
3414 $sql .= " AND price_level = " . ((int) $price_level);
3415 $sql .= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid.
3416 $sql .= " LIMIT 1";
3417
3418 dol_syslog(get_class($this) . '::constructProductListOption search price for product ' . $objp->rowid . ' AND level ' . $price_level, LOG_DEBUG);
3419 $result2 = $this->db->query($sql);
3420 if ($result2) {
3421 $objp2 = $this->db->fetch_object($result2);
3422 if ($objp2) {
3423 $found = 1;
3424 if ($objp2->price_base_type == 'HT') {
3425 $opt .= ' - ' . price($objp2->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3426 $outval .= ' - ' . price($objp2->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3427 } else {
3428 $opt .= ' - ' . price($objp2->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3429 $outval .= ' - ' . price($objp2->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3430 }
3431 $outprice_ht = price($objp2->price);
3432 $outprice_ttc = price($objp2->price_ttc);
3433 $outpricebasetype = $objp2->price_base_type;
3434 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
3435 $outtva_tx = $objp2->tva_tx; // We use the vat rate on line of multiprice
3436 $outdefault_vat_code = $objp2->default_vat_code; // We use the vat code on line of multiprice
3437 } else {
3438 $outtva_tx = $objp->tva_tx; // We use the vat rate of product, not the one on line of multiprice
3439 $outdefault_vat_code = $objp->default_vat_code; // We use the vat code or product, not the one on line of multiprice
3440 }
3441 }
3442 } else {
3443 dol_print_error($this->db);
3444 }
3445 }
3446
3447 // Price by quantity
3448 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1 && (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3449 $found = 1;
3450 $outqty = $objp->quantity;
3451 $outdiscount = $objp->remise_percent;
3452 if ($objp->quantity == 1) {
3453 $opt .= ' - ' . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/";
3454 $outval .= ' - ' . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/";
3455 $opt .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3456 $outval .= $langs->transnoentities("Unit");
3457 } else {
3458 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3459 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3460 $opt .= $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3461 $outval .= $langs->transnoentities("Units");
3462 }
3463
3464 $outprice_ht = price($objp->unitprice);
3465 $outprice_ttc = price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
3466 $outpricebasetype = $objp->price_base_type;
3467 $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
3468 $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
3469 }
3470 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1) {
3471 $opt .= " (" . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3472 $outval .= " (" . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3473 }
3474 if (empty($hidepriceinlabel) && !empty($objp->remise_percent) && $objp->remise_percent >= 1) {
3475 $opt .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3476 $outval .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3477 }
3478
3479 // Price by customer
3480 if (empty($hidepriceinlabel) && getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
3481 if (!empty($objp->idprodcustprice)) {
3482 $found = 1;
3483
3484 if ($objp->custprice_base_type == 'HT') {
3485 $opt .= ' - ' . price($objp->custprice, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3486 $outval .= ' - ' . price($objp->custprice, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3487 } else {
3488 $opt .= ' - ' . price($objp->custprice_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3489 $outval .= ' - ' . price($objp->custprice_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3490 }
3491
3492 $outprice_ht = price($objp->custprice);
3493 $outprice_ttc = price($objp->custprice_ttc);
3494 $outpricebasetype = $objp->custprice_base_type;
3495 $outtva_tx = $objp->custtva_tx;
3496 $outdefault_vat_code = $objp->custdefault_vat_code;
3497 }
3498 }
3499
3500 // If level no defined or multiprice not found, we used the default price
3501 if (empty($hidepriceinlabel) && !$found) {
3502 if ($objp->price_base_type == 'HT') {
3503 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3504 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3505 } else {
3506 $opt .= ' - ' . price($objp->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3507 $outval .= ' - ' . price($objp->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3508 }
3509 $outprice_ht = price($objp->price);
3510 $outprice_ttc = price($objp->price_ttc);
3511 $outpricebasetype = $objp->price_base_type;
3512 $outtva_tx = $objp->tva_tx;
3513 $outdefault_vat_code = $objp->default_vat_code;
3514 }
3515
3516 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3517 if ($user->hasRight('stock', 'lire')) {
3518 $opt .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'), 0, $langs, 0, 0);
3519
3520 if ($objp->stock > 0) {
3521 $outval .= ' - <span class="product_line_stock_ok">';
3522 } elseif ($objp->stock <= 0) {
3523 $outval .= ' - <span class="product_line_stock_too_low">';
3524 }
3525 $outval .= $langs->transnoentities("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3526 $outval .= '</span>';
3527 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3528 $langs->load("stocks");
3529
3530 $tmpproduct = new Product($this->db);
3531 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3532 $tmpproduct->load_virtual_stock();
3533 $virtualstock = $tmpproduct->stock_theorique;
3534
3535 $opt .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3536
3537 $outval .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3538 if ($virtualstock > 0) {
3539 $outval .= '<span class="product_line_stock_ok">';
3540 } elseif ($virtualstock <= 0) {
3541 $outval .= '<span class="product_line_stock_too_low">';
3542 }
3543 $outval .= $virtualstock;
3544 $outval .= '</span>';
3545
3546 unset($tmpproduct);
3547 }
3548 }
3549 }
3550
3551 $parameters = array('objp' => $objp);
3552 $reshook = $hookmanager->executeHooks('constructProductListOption', $parameters); // Note that $action and $object may have been modified by hook
3553 if (empty($reshook)) {
3554 $opt .= $hookmanager->resPrint;
3555 } else {
3556 $opt = $hookmanager->resPrint;
3557 }
3558
3559 $opt .= "</option>\n";
3560 $optJson = array(
3561 'key' => $outkey,
3562 'value' => $outref,
3563 'label' => $outval,
3564 'label2' => $outlabel,
3565 'desc' => $outdesc,
3566 'type' => $outtype,
3567 'price_ht' => price2num($outprice_ht),
3568 'price_ttc' => price2num($outprice_ttc),
3569 'price_ht_locale' => price(price2num($outprice_ht)),
3570 'price_ttc_locale' => price(price2num($outprice_ttc)),
3571 'pricebasetype' => $outpricebasetype,
3572 'tva_tx' => $outtva_tx,
3573 'default_vat_code' => $outdefault_vat_code,
3574 'qty' => $outqty,
3575 'discount' => $outdiscount,
3576 'duration_value' => $outdurationvalue,
3577 'duration_unit' => $outdurationunit,
3578 'pbq' => $outpbq,
3579 'labeltrans' => $outlabel_translated,
3580 'desctrans' => $outdesc_translated,
3581 'ref_customer' => $outrefcust
3582 );
3583 }
3584
3585 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3586
3602 public function select_produits_fournisseurs($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $ajaxoptions = array(), $hidelabel = 0, $alsoproductwithnosupplierprice = 0, $morecss = '', $placeholder = '')
3603 {
3604 // phpcs:enable
3605 global $langs, $conf;
3606 global $price_level, $status, $finished;
3607
3608 if (!isset($status)) {
3609 $status = 1;
3610 }
3611
3612 $selected_input_value = '';
3613 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3614 if ($selected > 0) {
3615 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3616 $producttmpselect = new Product($this->db);
3617 $producttmpselect->fetch($selected);
3618 $selected_input_value = $producttmpselect->ref;
3619 unset($producttmpselect);
3620 }
3621
3622 // mode=2 means suppliers products
3623 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=2&status=' . $status . '&finished=' . $finished . '&alsoproductwithnosupplierprice=' . $alsoproductwithnosupplierprice;
3624 print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT'), 0, $ajaxoptions);
3625
3626 print($hidelabel ? '' : $langs->trans("RefOrLabel") . ' : ') . '<input type="text" class="'.$morecss.'" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . $placeholder . '"' : '') . '>';
3627 } else {
3628 print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', $status, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder);
3629 }
3630 }
3631
3632 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3633
3652 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 = '')
3653 {
3654 // phpcs:enable
3655 global $langs, $conf, $user;
3656 global $hookmanager;
3657
3658 $out = '';
3659 $outarray = array();
3660
3661 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3662
3663 $langs->load('stocks');
3664 // Units
3665 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3666 $langs->load('other');
3667 }
3668
3669 $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,";
3670 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice, pfp.barcode";
3671 $sql .= ", pfp.multicurrency_code, pfp.multicurrency_unitprice";
3672 $sql .= ", pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.default_vat_code, pfp.fk_soc, s.nom as name";
3673 $sql .= ", pfp.supplier_reputation";
3674 // if we use supplier description of the products
3675 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3676 $sql .= ", pfp.desc_fourn as description";
3677 } else {
3678 $sql .= ", p.description";
3679 }
3680 // Units
3681 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3682 $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";
3683 }
3684 $sql .= " FROM " . $this->db->prefix() . "product as p";
3685 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (" . getEntity('product') . ") )";
3686 if ($socid > 0) {
3687 $sql .= " AND pfp.fk_soc = " . ((int) $socid);
3688 }
3689 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3690 // Units
3691 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3692 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3693 }
3694 $sql .= " WHERE p.entity IN (" . getEntity('product') . ")";
3695 if ($statut != -1) {
3696 $sql .= " AND p.tobuy = " . ((int) $statut);
3697 }
3698 if (strval($filtertype) != '') {
3699 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3700 }
3701 if (!empty($filtre)) {
3702 $sql .= " " . $filtre;
3703 }
3704 // Add where from hooks
3705 $parameters = array();
3706 $reshook = $hookmanager->executeHooks('selectSuppliersProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3707 $sql .= $hookmanager->resPrint;
3708 // Add criteria on ref/label
3709 if ($filterkey != '') {
3710 $sql .= ' AND (';
3711 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3712 // For natural search
3713 $search_crit = explode(' ', $filterkey);
3714 $i = 0;
3715 if (count($search_crit) > 1) {
3716 $sql .= "(";
3717 }
3718 foreach ($search_crit as $crit) {
3719 if ($i > 0) {
3720 $sql .= " AND ";
3721 }
3722 $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) . "%'";
3723 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3724 $sql .= " OR pfp.desc_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3725 }
3726 $sql .= ")";
3727 $i++;
3728 }
3729 if (count($search_crit) > 1) {
3730 $sql .= ")";
3731 }
3732 if (isModEnabled('barcode')) {
3733 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3734 $sql .= " OR pfp.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3735 }
3736 $sql .= ')';
3737 }
3738 $sql .= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC";
3739 $sql .= $this->db->plimit($limit, 0);
3740
3741 // Build output string
3742
3743 dol_syslog(get_class($this) . "::select_produits_fournisseurs_list", LOG_DEBUG);
3744 $result = $this->db->query($sql);
3745 if ($result) {
3746 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3747 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3748
3749 $num = $this->db->num_rows($result);
3750
3751 //$out.='<select class="flat" id="select'.$htmlname.'" name="'.$htmlname.'">'; // remove select to have id same with combo and ajax
3752 $out .= '<select class="flat ' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '">';
3753 if (!$selected) {
3754 $out .= '<option value="-1" selected>' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3755 } else {
3756 $out .= '<option value="-1">' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3757 }
3758
3759 $i = 0;
3760 while ($i < $num) {
3761 $objp = $this->db->fetch_object($result);
3762
3763 if (is_null($objp->idprodfournprice)) {
3764 // There is no supplier price found, we will use the vat rate for sale
3765 $objp->tva_tx = $objp->tva_tx_sale;
3766 $objp->default_vat_code = $objp->default_vat_code_sale;
3767 }
3768
3769 $outkey = $objp->idprodfournprice; // id in table of price
3770 if (!$outkey && $alsoproductwithnosupplierprice) {
3771 $outkey = 'idprod_' . $objp->rowid; // id of product
3772 }
3773
3774 $outref = $objp->ref;
3775 $outbarcode = $objp->barcode;
3776 $outqty = 1;
3777 $outdiscount = 0;
3778 $outtype = $objp->fk_product_type;
3779 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3780 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3781
3782 // Units
3783 $outvalUnits = '';
3784 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3785 if (!empty($objp->unit_short)) {
3786 $outvalUnits .= ' - ' . $objp->unit_short;
3787 }
3788 if (!empty($objp->weight) && $objp->weight_units !== null) {
3789 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3790 $outvalUnits .= ' - ' . $unitToShow;
3791 }
3792 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3793 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3794 $outvalUnits .= ' - ' . $unitToShow;
3795 }
3796 if (!empty($objp->surface) && $objp->surface_units !== null) {
3797 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3798 $outvalUnits .= ' - ' . $unitToShow;
3799 }
3800 if (!empty($objp->volume) && $objp->volume_units !== null) {
3801 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3802 $outvalUnits .= ' - ' . $unitToShow;
3803 }
3804 if ($outdurationvalue && $outdurationunit) {
3805 $da = array(
3806 'h' => $langs->trans('Hour'),
3807 'd' => $langs->trans('Day'),
3808 'w' => $langs->trans('Week'),
3809 'm' => $langs->trans('Month'),
3810 'y' => $langs->trans('Year')
3811 );
3812 if (isset($da[$outdurationunit])) {
3813 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3814 }
3815 }
3816 }
3817
3818 $objRef = $objp->ref;
3819 if ($filterkey && $filterkey != '') {
3820 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3821 }
3822 $objRefFourn = $objp->ref_fourn;
3823 if ($filterkey && $filterkey != '') {
3824 $objRefFourn = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRefFourn, 1);
3825 }
3826 $label = $objp->label;
3827 if ($filterkey && $filterkey != '') {
3828 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3829 }
3830
3831 switch ($objp->fk_product_type) {
3833 $picto = 'product';
3834 break;
3836 $picto = 'service';
3837 break;
3838 default:
3839 $picto = '';
3840 break;
3841 }
3842
3843 if (empty($picto)) {
3844 $optlabel = '';
3845 } else {
3846 $optlabel = img_object('', $picto, 'class="paddingright classfortooltip"', 0, 0, 1);
3847 }
3848
3849 $optlabel .= $objp->ref;
3850 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3851 $optlabel .= ' <span class="opacitymedium">(' . $objp->ref_fourn . ')</span>';
3852 }
3853 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3854 $optlabel .= ' (' . $outbarcode . ')';
3855 }
3856 $optlabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3857
3858 $outvallabel = $objRef;
3859 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3860 $outvallabel .= ' (' . $objRefFourn . ')';
3861 }
3862 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3863 $outvallabel .= ' (' . $outbarcode . ')';
3864 }
3865 $outvallabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3866
3867 // Units
3868 $optlabel .= $outvalUnits;
3869 $outvallabel .= $outvalUnits;
3870
3871 if (!empty($objp->idprodfournprice)) {
3872 $outqty = $objp->quantity;
3873 $outdiscount = $objp->remise_percent;
3874 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3875 $prod_supplier = new ProductFournisseur($this->db);
3876 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3877 $prod_supplier->id = $objp->fk_product;
3878 $prod_supplier->fourn_qty = $objp->quantity;
3879 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3880 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3881
3882 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3883 $priceparser = new PriceParser($this->db);
3884 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3885 if ($price_result >= 0) {
3886 $objp->fprice = $price_result;
3887 if ($objp->quantity >= 1) {
3888 $objp->unitprice = $objp->fprice / $objp->quantity; // Replace dynamically unitprice
3889 }
3890 }
3891 }
3892 if ($objp->quantity == 1) {
3893 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3894 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/";
3895 $optlabel .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3896 $outvallabel .= $langs->transnoentities("Unit");
3897 } else {
3898 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3899 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3900 $optlabel .= ' ' . $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3901 $outvallabel .= ' ' . $langs->transnoentities("Units");
3902 }
3903
3904 if ($objp->quantity > 1) {
3905 $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
3906 $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
3907 }
3908 if ($objp->remise_percent >= 1) {
3909 $optlabel .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3910 $outvallabel .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3911 }
3912 if ($objp->duration) {
3913 $optlabel .= " - " . $objp->duration;
3914 $outvallabel .= " - " . $objp->duration;
3915 }
3916 if (!$socid) {
3917 $optlabel .= " - " . dol_trunc($objp->name, 8);
3918 $outvallabel .= " - " . dol_trunc($objp->name, 8);
3919 }
3920 if ($objp->supplier_reputation) {
3921 //TODO dictionary
3922 $reputations = array('' => $langs->trans('Standard'), 'FAVORITE' => $langs->trans('Favorite'), 'NOTTHGOOD' => $langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER' => $langs->trans('DoNotOrderThisProductToThisSupplier'));
3923
3924 $optlabel .= " - " . $reputations[$objp->supplier_reputation];
3925 $outvallabel .= " - " . $reputations[$objp->supplier_reputation];
3926 }
3927 } else {
3928 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3929 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3930 }
3931
3932 if (isModEnabled('stock') && $showstockinlist && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3933 $novirtualstock = ($showstockinlist == 2);
3934
3935 if ($user->hasRight('stock', 'lire')) {
3936 $outvallabel .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3937
3938 if ($objp->stock > 0) {
3939 $optlabel .= ' - <span class="product_line_stock_ok">';
3940 } elseif ($objp->stock <= 0) {
3941 $optlabel .= ' - <span class="product_line_stock_too_low">';
3942 }
3943 $optlabel .= $langs->transnoentities("Stock") . ':' . price(price2num($objp->stock, 'MS'));
3944 $optlabel .= '</span>';
3945 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3946 $langs->load("stocks");
3947
3948 $tmpproduct = new Product($this->db);
3949 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3950 $tmpproduct->load_virtual_stock();
3951 $virtualstock = $tmpproduct->stock_theorique;
3952
3953 $outvallabel .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3954
3955 $optlabel .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3956 if ($virtualstock > 0) {
3957 $optlabel .= '<span class="product_line_stock_ok">';
3958 } elseif ($virtualstock <= 0) {
3959 $optlabel .= '<span class="product_line_stock_too_low">';
3960 }
3961 $optlabel .= $virtualstock;
3962 $optlabel .= '</span>';
3963
3964 unset($tmpproduct);
3965 }
3966 }
3967 }
3968
3969 $optstart = '<option value="' . $outkey . '"';
3970 if ($selected && $selected == $objp->idprodfournprice) {
3971 $optstart .= ' selected';
3972 }
3973 if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) {
3974 $optstart .= ' disabled';
3975 }
3976
3977 if (!empty($objp->idprodfournprice) && $objp->idprodfournprice > 0) {
3978 $optstart .= ' data-product-id="' . dol_escape_htmltag($objp->rowid) . '"';
3979 $optstart .= ' data-price-id="' . dol_escape_htmltag($objp->idprodfournprice) . '"';
3980 $optstart .= ' data-qty="' . dol_escape_htmltag($objp->quantity) . '"';
3981 $optstart .= ' data-up="' . dol_escape_htmltag(price2num($objp->unitprice)) . '"';
3982 $optstart .= ' data-up-locale="' . dol_escape_htmltag(price($objp->unitprice)) . '"';
3983 $optstart .= ' data-discount="' . dol_escape_htmltag($outdiscount) . '"';
3984 $optstart .= ' data-tvatx="' . dol_escape_htmltag(price2num($objp->tva_tx)) . '"';
3985 $optstart .= ' data-tvatx-formated="' . dol_escape_htmltag(price($objp->tva_tx, 0, $langs, 1, -1, 2)) . '"';
3986 $optstart .= ' data-default-vat-code="' . dol_escape_htmltag($objp->default_vat_code) . '"';
3987 $optstart .= ' data-supplier-ref="' . dol_escape_htmltag($objp->ref_fourn) . '"';
3988 if (isModEnabled('multicurrency')) {
3989 $optstart .= ' data-multicurrency-code="' . dol_escape_htmltag($objp->multicurrency_code) . '"';
3990 $optstart .= ' data-multicurrency-up="' . dol_escape_htmltag($objp->multicurrency_unitprice) . '"';
3991 }
3992 }
3993 $optstart .= ' data-description="' . dol_escape_htmltag($objp->description, 0, 1) . '"';
3994
3995 $outarrayentry = array(
3996 'key' => $outkey,
3997 'value' => $outref,
3998 'label' => $outvallabel,
3999 'qty' => $outqty,
4000 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
4001 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
4002 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
4003 'tva_tx_formated' => price($objp->tva_tx, 0, $langs, 1, -1, 2),
4004 'tva_tx' => price2num($objp->tva_tx),
4005 'default_vat_code' => $objp->default_vat_code,
4006 'supplier_ref' => $objp->ref_fourn,
4007 'discount' => $outdiscount,
4008 'type' => $outtype,
4009 'duration_value' => $outdurationvalue,
4010 'duration_unit' => $outdurationunit,
4011 'disabled' => empty($objp->idprodfournprice),
4012 'description' => $objp->description
4013 );
4014 if (isModEnabled('multicurrency')) {
4015 $outarrayentry['multicurrency_code'] = $objp->multicurrency_code;
4016 $outarrayentry['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
4017 }
4018
4019 $parameters = array(
4020 'objp' => &$objp,
4021 'optstart' => &$optstart,
4022 'optlabel' => &$optlabel,
4023 'outvallabel' => &$outvallabel,
4024 'outarrayentry' => &$outarrayentry
4025 );
4026 $reshook = $hookmanager->executeHooks('selectProduitsFournisseurListOption', $parameters, $this);
4027
4028
4029 // Add new entry
4030 // "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
4031 // "label" value of json key array is used by jQuery automatically as text for combo box
4032 $out .= $optstart . ' data-html="' . dol_escape_htmltag($optlabel) . '">' . $optlabel . "</option>\n";
4033 $outarraypush = array(
4034 'key' => $outkey,
4035 'value' => $outref,
4036 'label' => $outvallabel,
4037 'qty' => $outqty,
4038 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
4039 'price_qty_ht_locale' => price($objp->fprice),
4040 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
4041 'price_unit_ht_locale' => price($objp->unitprice),
4042 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
4043 'tva_tx_formated' => price($objp->tva_tx),
4044 'tva_tx' => price2num($objp->tva_tx),
4045 'default_vat_code' => $objp->default_vat_code,
4046 'supplier_ref' => $objp->ref_fourn,
4047 'discount' => $outdiscount,
4048 'type' => $outtype,
4049 'duration_value' => $outdurationvalue,
4050 'duration_unit' => $outdurationunit,
4051 'disabled' => (empty($objp->idprodfournprice) ? true : false),
4052 'description' => $objp->description
4053 );
4054 if (isModEnabled('multicurrency')) {
4055 $outarraypush['multicurrency_code'] = $objp->multicurrency_code;
4056 $outarraypush['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
4057 }
4058 array_push($outarray, $outarraypush);
4059
4060 // Example of var_dump $outarray
4061 // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
4062 // ["label"]=>string(76) "ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
4063 // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false)
4064 //}
4065 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
4066 //$outval=array('label'=>'ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)');
4067 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
4068
4069 $i++;
4070 }
4071 $out .= '</select>';
4072
4073 $this->db->free($result);
4074
4075 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
4076 $out .= ajax_combobox($htmlname);
4077 } else {
4078 dol_print_error($this->db);
4079 }
4080
4081 if (empty($outputmode)) {
4082 return $out;
4083 }
4084 return $outarray;
4085 }
4086
4087 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4088
4097 public function select_product_fourn_price($productid, $htmlname = 'productfournpriceid', $selected_supplier = 0)
4098 {
4099 // phpcs:enable
4100 global $langs, $conf;
4101
4102 $langs->load('stocks');
4103
4104 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, pfp.fk_soc,";
4105 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,";
4106 $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name";
4107 $sql .= " FROM " . $this->db->prefix() . "product as p";
4108 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
4109 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
4110 $sql .= " WHERE pfp.entity IN (" . getEntity('productsupplierprice') . ")";
4111 $sql .= " AND p.tobuy = 1";
4112 $sql .= " AND s.fournisseur = 1";
4113 $sql .= " AND p.rowid = " . ((int) $productid);
4114 if (!getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED')) {
4115 $sql .= " ORDER BY s.nom, pfp.ref_fourn DESC";
4116 } else {
4117 $sql .= " ORDER BY pfp.unitprice ASC";
4118 }
4119
4120 dol_syslog(get_class($this) . "::select_product_fourn_price", LOG_DEBUG);
4121 $result = $this->db->query($sql);
4122
4123 if ($result) {
4124 $num = $this->db->num_rows($result);
4125
4126 $form = '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4127
4128 if (!$num) {
4129 $form .= '<option value="0">-- ' . $langs->trans("NoSupplierPriceDefinedForThisProduct") . ' --</option>';
4130 } else {
4131 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
4132 $form .= '<option value="0">&nbsp;</option>';
4133
4134 $i = 0;
4135 while ($i < $num) {
4136 $objp = $this->db->fetch_object($result);
4137
4138 $opt = '<option value="' . $objp->idprodfournprice . '"';
4139 //if there is only one supplier, preselect it
4140 if ($num == 1 || ($selected_supplier > 0 && $objp->fk_soc == $selected_supplier) || ($i == 0 && getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED'))) {
4141 $opt .= ' selected';
4142 }
4143 $opt .= '>' . $objp->name . ' - ' . $objp->ref_fourn . ' - ';
4144
4145 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
4146 $prod_supplier = new ProductFournisseur($this->db);
4147 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
4148 $prod_supplier->id = $productid;
4149 $prod_supplier->fourn_qty = $objp->quantity;
4150 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
4151 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
4152
4153 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
4154 $priceparser = new PriceParser($this->db);
4155 $price_result = $priceparser->parseProductSupplier($prod_supplier);
4156 if ($price_result >= 0) {
4157 $objp->fprice = $price_result;
4158 if ($objp->quantity >= 1) {
4159 $objp->unitprice = $objp->fprice / $objp->quantity;
4160 }
4161 }
4162 }
4163 if ($objp->quantity == 1) {
4164 $opt .= price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
4165 }
4166
4167 $opt .= $objp->quantity . ' ';
4168
4169 if ($objp->quantity == 1) {
4170 $opt .= $langs->trans("Unit");
4171 } else {
4172 $opt .= $langs->trans("Units");
4173 }
4174 if ($objp->quantity > 1) {
4175 $opt .= " - ";
4176 $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");
4177 }
4178 if ($objp->duration) {
4179 $opt .= " - " . $objp->duration;
4180 }
4181 $opt .= "</option>\n";
4182
4183 $form .= $opt;
4184 $i++;
4185 }
4186 }
4187
4188 $form .= '</select>';
4189 $this->db->free($result);
4190 return $form;
4191 } else {
4192 dol_print_error($this->db);
4193 return '';
4194 }
4195 }
4196
4197
4198 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4205 {
4206 // phpcs:enable
4207 global $langs;
4208
4209 $num = count($this->cache_conditions_paiements);
4210 if ($num > 0) {
4211 return 0; // Cache already loaded
4212 }
4213
4214 dol_syslog(__METHOD__, LOG_DEBUG);
4215
4216 $sql = "SELECT rowid, code, libelle as label, deposit_percent";
4217 $sql .= " FROM " . $this->db->prefix() . 'c_payment_term';
4218 $sql .= " WHERE entity IN (" . getEntity('c_payment_term') . ")";
4219 $sql .= " AND active > 0";
4220 $sql .= " ORDER BY sortorder";
4221
4222 $resql = $this->db->query($sql);
4223 if ($resql) {
4224 $num = $this->db->num_rows($resql);
4225 $i = 0;
4226 while ($i < $num) {
4227 $obj = $this->db->fetch_object($resql);
4228
4229 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4230 $label = ($langs->trans("PaymentConditionShort" . $obj->code) != "PaymentConditionShort" . $obj->code ? $langs->trans("PaymentConditionShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4231 $this->cache_conditions_paiements[$obj->rowid]['code'] = $obj->code;
4232 $this->cache_conditions_paiements[$obj->rowid]['label'] = $label;
4233 $this->cache_conditions_paiements[$obj->rowid]['deposit_percent'] = $obj->deposit_percent;
4234 $i++;
4235 }
4236
4237 //$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1); // We use the field sortorder of table
4238
4239 return $num;
4240 } else {
4241 dol_print_error($this->db);
4242 return -1;
4243 }
4244 }
4245
4246 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4247
4253 public function load_cache_availability()
4254 {
4255 // phpcs:enable
4256 global $langs;
4257
4258 $num = count($this->cache_availability); // TODO Use $conf->cache['availability'] instead of $this->cache_availability
4259 if ($num > 0) {
4260 return 0; // Cache already loaded
4261 }
4262
4263 dol_syslog(__METHOD__, LOG_DEBUG);
4264
4265 $langs->load('propal');
4266
4267 $sql = "SELECT rowid, code, label, position";
4268 $sql .= " FROM " . $this->db->prefix() . 'c_availability';
4269 $sql .= " WHERE active > 0";
4270
4271 $resql = $this->db->query($sql);
4272 if ($resql) {
4273 $num = $this->db->num_rows($resql);
4274 $i = 0;
4275 while ($i < $num) {
4276 $obj = $this->db->fetch_object($resql);
4277
4278 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4279 $label = ($langs->trans("AvailabilityType" . $obj->code) != "AvailabilityType" . $obj->code ? $langs->trans("AvailabilityType" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4280 $this->cache_availability[$obj->rowid]['code'] = $obj->code;
4281 $this->cache_availability[$obj->rowid]['label'] = $label;
4282 $this->cache_availability[$obj->rowid]['position'] = $obj->position;
4283 $i++;
4284 }
4285
4286 $this->cache_availability = dol_sort_array($this->cache_availability, 'position', 'asc', 0, 0, 1);
4287
4288 return $num;
4289 } else {
4290 dol_print_error($this->db);
4291 return -1;
4292 }
4293 }
4294
4305 public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0, $morecss = '')
4306 {
4307 global $langs, $user;
4308
4309 $this->load_cache_availability();
4310
4311 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4312
4313 print '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4314 if ($addempty) {
4315 print '<option value="0">&nbsp;</option>';
4316 }
4317 foreach ($this->cache_availability as $id => $arrayavailability) {
4318 if ($selected == $id) {
4319 print '<option value="' . $id . '" selected>';
4320 } else {
4321 print '<option value="' . $id . '">';
4322 }
4323 print dol_escape_htmltag($arrayavailability['label']);
4324 print '</option>';
4325 }
4326 print '</select>';
4327 if ($user->admin) {
4328 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4329 }
4330 print ajax_combobox($htmlname);
4331 }
4332
4338 public function loadCacheInputReason()
4339 {
4340 global $langs;
4341
4342 $num = count($this->cache_demand_reason); // TODO Use $conf->cache['input_reason'] instead of $this->cache_demand_reason
4343 if ($num > 0) {
4344 return 0; // Cache already loaded
4345 }
4346
4347 $sql = "SELECT rowid, code, label";
4348 $sql .= " FROM " . $this->db->prefix() . 'c_input_reason';
4349 $sql .= " WHERE active > 0";
4350
4351 $resql = $this->db->query($sql);
4352 if ($resql) {
4353 $num = $this->db->num_rows($resql);
4354 $i = 0;
4355 $tmparray = array();
4356 while ($i < $num) {
4357 $obj = $this->db->fetch_object($resql);
4358
4359 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4360 $label = ($obj->label != '-' ? $obj->label : '');
4361 if ($langs->trans("DemandReasonType" . $obj->code) != "DemandReasonType" . $obj->code) {
4362 $label = $langs->trans("DemandReasonType" . $obj->code); // So translation key DemandReasonTypeSRC_XXX will work
4363 }
4364 if ($langs->trans($obj->code) != $obj->code) {
4365 $label = $langs->trans($obj->code); // So translation key SRC_XXX will work
4366 }
4367
4368 $tmparray[$obj->rowid]['id'] = $obj->rowid;
4369 $tmparray[$obj->rowid]['code'] = $obj->code;
4370 $tmparray[$obj->rowid]['label'] = $label;
4371 $i++;
4372 }
4373
4374 $this->cache_demand_reason = dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1);
4375
4376 unset($tmparray);
4377 return $num;
4378 } else {
4379 dol_print_error($this->db);
4380 return -1;
4381 }
4382 }
4383
4396 public function selectInputReason($selected = '', $htmlname = 'demandreasonid', $exclude = '', $addempty = 0, $morecss = '', $notooltip = 0)
4397 {
4398 global $langs, $user;
4399
4400 $this->loadCacheInputReason();
4401
4402 print '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4403 if ($addempty) {
4404 print '<option value="0"' . (empty($selected) ? ' selected' : '') . '>&nbsp;</option>';
4405 }
4406 foreach ($this->cache_demand_reason as $id => $arraydemandreason) {
4407 if ($arraydemandreason['code'] == $exclude) {
4408 continue;
4409 }
4410
4411 if ($selected && ($selected == $arraydemandreason['id'] || $selected == $arraydemandreason['code'])) {
4412 print '<option value="' . $arraydemandreason['id'] . '" selected>';
4413 } else {
4414 print '<option value="' . $arraydemandreason['id'] . '">';
4415 }
4416 $label = $arraydemandreason['label']; // Translation of label was already done into the ->loadCacheInputReason
4417 print $langs->trans($label);
4418 print '</option>';
4419 }
4420 print '</select>';
4421 if ($user->admin && empty($notooltip)) {
4422 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4423 }
4424 print ajax_combobox('select_' . $htmlname);
4425 }
4426
4427 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4428
4435 {
4436 // phpcs:enable
4437 global $langs;
4438
4439 $num = count($this->cache_types_paiements); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_types_paiements
4440 if ($num > 0) {
4441 return $num; // Cache already loaded
4442 }
4443
4444 dol_syslog(__METHOD__, LOG_DEBUG);
4445
4446 $this->cache_types_paiements = array();
4447
4448 $sql = "SELECT id, code, libelle as label, type, active";
4449 $sql .= " FROM " . $this->db->prefix() . "c_paiement";
4450 $sql .= " WHERE entity IN (" . getEntity('c_paiement') . ")";
4451
4452 $resql = $this->db->query($sql);
4453 if ($resql) {
4454 $num = $this->db->num_rows($resql);
4455 $i = 0;
4456 while ($i < $num) {
4457 $obj = $this->db->fetch_object($resql);
4458
4459 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4460 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4461 $this->cache_types_paiements[$obj->id]['id'] = $obj->id;
4462 $this->cache_types_paiements[$obj->id]['code'] = $obj->code;
4463 $this->cache_types_paiements[$obj->id]['label'] = $label;
4464 $this->cache_types_paiements[$obj->id]['type'] = $obj->type;
4465 $this->cache_types_paiements[$obj->id]['active'] = $obj->active;
4466 $i++;
4467 }
4468
4469 $this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1);
4470
4471 return $num;
4472 } else {
4473 dol_print_error($this->db);
4474 return -1;
4475 }
4476 }
4477
4478
4479 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4480
4499 public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1, $noprint = 0)
4500 {
4501 // phpcs:enable
4502 $out = $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, $noinfoadmin, $morecss, $deposit_percent);
4503 if (empty($noprint)) {
4504 print $out;
4505 } else {
4506 return $out;
4507 }
4508 }
4509
4510
4527 public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4528 {
4529 global $langs, $user, $conf;
4530
4531 $out = '';
4532 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4533
4535
4536 // Set default value if not already set by caller
4537 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID')) {
4538 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TERM_ID", LOG_NOTICE);
4539 $selected = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID');
4540 }
4541
4542 $out .= '<select id="' . $htmlname . '" class="flat selectpaymentterms' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4543 if ($addempty) {
4544 $out .= '<option value="0">&nbsp;</option>';
4545 }
4546
4547 $selectedDepositPercent = null;
4548
4549 foreach ($this->cache_conditions_paiements as $id => $arrayconditions) {
4550 if ($filtertype <= 0 && !empty($arrayconditions['deposit_percent'])) {
4551 continue;
4552 }
4553
4554 if ($selected == $id) {
4555 $selectedDepositPercent = $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'];
4556 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '" selected>';
4557 } else {
4558 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '">';
4559 }
4560 $label = $arrayconditions['label'];
4561
4562 if (!empty($arrayconditions['deposit_percent'])) {
4563 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'], $label);
4564 }
4565
4566 $out .= $label;
4567 $out .= '</option>';
4568 }
4569 $out .= '</select>';
4570 if ($user->admin && empty($noinfoadmin)) {
4571 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4572 }
4573 $out .= ajax_combobox($htmlname);
4574
4575 if ($deposit_percent >= 0) {
4576 $out .= ' <span id="' . $htmlname . '_deposit_percent_container"' . (empty($selectedDepositPercent) ? ' style="display: none"' : '') . '>';
4577 $out .= $langs->trans('DepositPercent') . ' : ';
4578 $out .= '<input id="' . $htmlname . '_deposit_percent" name="' . $htmlname . '_deposit_percent" class="maxwidth50" value="' . $deposit_percent . '" />';
4579 $out .= '</span>';
4580 $out .= '
4581 <script nonce="' . getNonce() . '">
4582 $(document).ready(function () {
4583 $("#' . $htmlname . '").change(function () {
4584 let $selected = $(this).find("option:selected");
4585 let depositPercent = $selected.attr("data-deposit_percent");
4586
4587 if (depositPercent.length > 0) {
4588 $("#' . $htmlname . '_deposit_percent_container").show().find("#' . $htmlname . '_deposit_percent").val(depositPercent);
4589 } else {
4590 $("#' . $htmlname . '_deposit_percent_container").hide();
4591 }
4592
4593 return true;
4594 });
4595 });
4596 </script>';
4597 }
4598
4599 return $out;
4600 }
4601
4602
4603 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4604
4621 public function select_types_paiements($selected = '', $htmlname = 'paiementtype', $filtertype = '', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '', $nooutput = 0)
4622 {
4623 // phpcs:enable
4624 global $langs, $user, $conf;
4625
4626 $out = '';
4627
4628 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
4629
4630 $filterarray = array();
4631 if ($filtertype == 'CRDT') {
4632 $filterarray = array(0, 2, 3);
4633 } elseif ($filtertype == 'DBIT') {
4634 $filterarray = array(1, 2, 3);
4635 } elseif ($filtertype != '' && $filtertype != '-1') {
4636 $filterarray = explode(',', $filtertype);
4637 }
4638
4640
4641 // Set default value if not already set by caller
4642 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID')) {
4643 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TYPE_ID", LOG_NOTICE);
4644 $selected = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID');
4645 }
4646
4647 $out .= '<select id="select' . $htmlname . '" class="flat selectpaymenttypes' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4648 if ($empty) {
4649 $out .= '<option value="">&nbsp;</option>';
4650 }
4651 foreach ($this->cache_types_paiements as $id => $arraytypes) {
4652 // If not good status
4653 if ($active >= 0 && $arraytypes['active'] != $active) {
4654 continue;
4655 }
4656
4657 // We skip of the user requested to filter on specific payment methods
4658 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
4659 continue;
4660 }
4661
4662 // We discard empty lines if showempty is on because an empty line has already been output.
4663 if ($empty && empty($arraytypes['code'])) {
4664 continue;
4665 }
4666
4667 if ($format == 0) {
4668 $out .= '<option value="' . $id . '"';
4669 } elseif ($format == 1) {
4670 $out .= '<option value="' . $arraytypes['code'] . '"';
4671 } elseif ($format == 2) {
4672 $out .= '<option value="' . $arraytypes['code'] . '"';
4673 } elseif ($format == 3) {
4674 $out .= '<option value="' . $id . '"';
4675 }
4676 // Print attribute selected or not
4677 if ($format == 1 || $format == 2) {
4678 if ($selected == $arraytypes['code']) {
4679 $out .= ' selected';
4680 }
4681 } else {
4682 if ($selected == $id) {
4683 $out .= ' selected';
4684 }
4685 }
4686 $out .= '>';
4687 $value = '';
4688 if ($format == 0) {
4689 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4690 } elseif ($format == 1) {
4691 $value = $arraytypes['code'];
4692 } elseif ($format == 2) {
4693 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4694 } elseif ($format == 3) {
4695 $value = $arraytypes['code'];
4696 }
4697 $out .= $value ? $value : '&nbsp;';
4698 $out .= '</option>';
4699 }
4700 $out .= '</select>';
4701 if ($user->admin && !$noadmininfo) {
4702 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4703 }
4704 $out .= ajax_combobox('select' . $htmlname);
4705
4706 if (empty($nooutput)) {
4707 print $out;
4708 } else {
4709 return $out;
4710 }
4711 }
4712
4713
4722 public function selectPriceBaseType($selected = '', $htmlname = 'price_base_type', $addjscombo = 0)
4723 {
4724 global $langs;
4725
4726 $return = '<select class="flat maxwidth100" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4727 $options = array(
4728 'HT' => $langs->trans("HT"),
4729 'TTC' => $langs->trans("TTC")
4730 );
4731 foreach ($options as $id => $value) {
4732 if ($selected == $id) {
4733 $return .= '<option value="' . $id . '" selected>' . $value;
4734 } else {
4735 $return .= '<option value="' . $id . '">' . $value;
4736 }
4737 $return .= '</option>';
4738 }
4739 $return .= '</select>';
4740 if ($addjscombo) {
4741 $return .= ajax_combobox('select_' . $htmlname);
4742 }
4743
4744 return $return;
4745 }
4746
4747 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4748
4755 {
4756 // phpcs:enable
4757 global $langs;
4758
4759 $num = count($this->cache_transport_mode); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_transport_mode
4760 if ($num > 0) {
4761 return $num; // Cache already loaded
4762 }
4763
4764 dol_syslog(__METHOD__, LOG_DEBUG);
4765
4766 $this->cache_transport_mode = array();
4767
4768 $sql = "SELECT rowid, code, label, active";
4769 $sql .= " FROM " . $this->db->prefix() . "c_transport_mode";
4770 $sql .= " WHERE entity IN (" . getEntity('c_transport_mode') . ")";
4771
4772 $resql = $this->db->query($sql);
4773 if ($resql) {
4774 $num = $this->db->num_rows($resql);
4775 $i = 0;
4776 while ($i < $num) {
4777 $obj = $this->db->fetch_object($resql);
4778
4779 // If traduction exist, we use it else we take the default label
4780 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4781 $this->cache_transport_mode[$obj->rowid]['rowid'] = $obj->rowid;
4782 $this->cache_transport_mode[$obj->rowid]['code'] = $obj->code;
4783 $this->cache_transport_mode[$obj->rowid]['label'] = $label;
4784 $this->cache_transport_mode[$obj->rowid]['active'] = $obj->active;
4785 $i++;
4786 }
4787
4788 $this->cache_transport_mode = dol_sort_array($this->cache_transport_mode, 'label', 'asc', 0, 0, 1);
4789
4790 return $num;
4791 } else {
4792 dol_print_error($this->db);
4793 return -1;
4794 }
4795 }
4796
4810 public function selectTransportMode($selected = '', $htmlname = 'transportmode', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '')
4811 {
4812 global $langs, $user;
4813
4814 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $format, LOG_DEBUG);
4815
4817
4818 print '<select id="select' . $htmlname . '" class="flat selectmodetransport' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4819 if ($empty) {
4820 print '<option value="">&nbsp;</option>';
4821 }
4822 foreach ($this->cache_transport_mode as $id => $arraytypes) {
4823 // If not good status
4824 if ($active >= 0 && $arraytypes['active'] != $active) {
4825 continue;
4826 }
4827
4828 // We discard empty line if showempty is on because an empty line has already been output.
4829 if ($empty && empty($arraytypes['code'])) {
4830 continue;
4831 }
4832
4833 if ($format == 0) {
4834 print '<option value="' . $id . '"';
4835 } elseif ($format == 1) {
4836 print '<option value="' . $arraytypes['code'] . '"';
4837 } elseif ($format == 2) {
4838 print '<option value="' . $arraytypes['code'] . '"';
4839 } elseif ($format == 3) {
4840 print '<option value="' . $id . '"';
4841 }
4842 // If text is selected, we compare with code, else with id
4843 if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) {
4844 print ' selected';
4845 } elseif ($selected == $id) {
4846 print ' selected';
4847 }
4848 print '>';
4849 $value = '';
4850 if ($format == 0) {
4851 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4852 } elseif ($format == 1) {
4853 $value = $arraytypes['code'];
4854 } elseif ($format == 2) {
4855 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4856 } elseif ($format == 3) {
4857 $value = $arraytypes['code'];
4858 }
4859 print $value ? $value : '&nbsp;';
4860 print '</option>';
4861 }
4862 print '</select>';
4863 if ($user->admin && !$noadmininfo) {
4864 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4865 }
4866 }
4867
4880 public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '', $noinfoadmin = 0, $morecss = '')
4881 {
4882 global $langs, $user;
4883
4884 $langs->load("admin");
4885 $langs->load("deliveries");
4886
4887 $sql = "SELECT rowid, code, libelle as label";
4888 $sql .= " FROM " . $this->db->prefix() . "c_shipment_mode";
4889 $sql .= " WHERE active > 0";
4890 if ($filtre) {
4891 $sql .= " AND " . $filtre;
4892 }
4893 $sql .= " ORDER BY libelle ASC";
4894
4895 dol_syslog(get_class($this) . "::selectShippingMode", LOG_DEBUG);
4896 $result = $this->db->query($sql);
4897 if ($result) {
4898 $num = $this->db->num_rows($result);
4899 $i = 0;
4900 if ($num) {
4901 print '<select id="select' . $htmlname . '" class="flat selectshippingmethod' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4902 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4903 print '<option value="-1">&nbsp;</option>';
4904 }
4905 while ($i < $num) {
4906 $obj = $this->db->fetch_object($result);
4907 if ($selected == $obj->rowid) {
4908 print '<option value="' . $obj->rowid . '" selected>';
4909 } else {
4910 print '<option value="' . $obj->rowid . '">';
4911 }
4912 print ($langs->trans("SendingMethod" . strtoupper($obj->code)) != "SendingMethod" . strtoupper($obj->code)) ? $langs->trans("SendingMethod" . strtoupper($obj->code)) : $obj->label;
4913 print '</option>';
4914 $i++;
4915 }
4916 print "</select>";
4917 if ($user->admin && empty($noinfoadmin)) {
4918 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4919 }
4920
4921 print ajax_combobox('select' . $htmlname);
4922 } else {
4923 print $langs->trans("NoShippingMethodDefined");
4924 }
4925 } else {
4926 dol_print_error($this->db);
4927 }
4928 }
4929
4939 public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0)
4940 {
4941 global $langs;
4942
4943 $langs->load("deliveries");
4944
4945 if ($htmlname != "none") {
4946 print '<form method="POST" action="' . $page . '">';
4947 print '<input type="hidden" name="action" value="setshippingmethod">';
4948 print '<input type="hidden" name="token" value="' . newToken() . '">';
4949 $this->selectShippingMethod($selected, $htmlname, '', $addempty);
4950 print '<input type="submit" class="button valignmiddle" value="' . $langs->trans("Modify") . '">';
4951 print '</form>';
4952 } else {
4953 if ($selected) {
4954 $code = $langs->getLabelFromKey($this->db, $selected, 'c_shipment_mode', 'rowid', 'code');
4955 print $langs->trans("SendingMethod" . strtoupper($code));
4956 } else {
4957 print "&nbsp;";
4958 }
4959 }
4960 }
4961
4970 public function selectSituationInvoices($selected = '', $socid = 0)
4971 {
4972 global $langs;
4973
4974 $langs->load('bills');
4975
4976 $opt = '<option value="" selected></option>';
4977 $sql = "SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc";
4978 $sql .= ' FROM ' . $this->db->prefix() . 'facture';
4979 $sql .= ' WHERE entity IN (' . getEntity('invoice') . ')';
4980 $sql .= ' AND situation_counter >= 1';
4981 $sql .= ' AND fk_soc = ' . (int) $socid;
4982 $sql .= ' AND type <> 2';
4983 $sql .= ' ORDER by situation_cycle_ref, situation_counter desc';
4984 $resql = $this->db->query($sql);
4985
4986 if ($resql && $this->db->num_rows($resql) > 0) {
4987 // Last seen cycle
4988 $ref = 0;
4989 while ($obj = $this->db->fetch_object($resql)) {
4990 //Same cycle ?
4991 if ($obj->situation_cycle_ref != $ref) {
4992 // Just seen this cycle
4993 $ref = $obj->situation_cycle_ref;
4994 //not final ?
4995 if ($obj->situation_final != 1) {
4996 //Not prov?
4997 if (substr($obj->ref, 1, 4) != 'PROV') {
4998 if ($selected == $obj->rowid) {
4999 $opt .= '<option value="' . $obj->rowid . '" selected>' . $obj->ref . '</option>';
5000 } else {
5001 $opt .= '<option value="' . $obj->rowid . '">' . $obj->ref . '</option>';
5002 }
5003 }
5004 }
5005 }
5006 }
5007 } else {
5008 dol_syslog("Error sql=" . $sql . ", error=" . $this->error, LOG_ERR);
5009 }
5010 if ($opt == '<option value ="" selected></option>') {
5011 $opt = '<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>';
5012 }
5013 return $opt;
5014 }
5015
5025 public function selectUnits($selected = '', $htmlname = 'units', $showempty = 0, $unit_type = '')
5026 {
5027 global $langs;
5028
5029 $langs->load('products');
5030
5031 $return = '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
5032
5033 $sql = "SELECT rowid, label, code FROM " . $this->db->prefix() . "c_units";
5034 $sql .= ' WHERE active > 0';
5035 if (!empty($unit_type)) {
5036 $sql .= " AND unit_type = '" . $this->db->escape($unit_type) . "'";
5037 }
5038 $sql .= " ORDER BY sortorder";
5039
5040 $resql = $this->db->query($sql);
5041 if ($resql && $this->db->num_rows($resql) > 0) {
5042 if ($showempty) {
5043 $return .= '<option value="none"></option>';
5044 }
5045
5046 while ($res = $this->db->fetch_object($resql)) {
5047 $unitLabel = $res->label;
5048 if (!empty($langs->tab_translate['unit' . $res->code])) { // check if Translation is available before
5049 $unitLabel = $langs->trans('unit' . $res->code) != $res->label ? $langs->trans('unit' . $res->code) : $res->label;
5050 }
5051
5052 if ($selected == $res->rowid) {
5053 $return .= '<option value="' . $res->rowid . '" selected>' . $unitLabel . '</option>';
5054 } else {
5055 $return .= '<option value="' . $res->rowid . '">' . $unitLabel . '</option>';
5056 }
5057 }
5058 $return .= '</select>';
5059 }
5060 return $return;
5061 }
5062
5063 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5064
5079 public function select_comptes($selected = '', $htmlname = 'accountid', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '', $showcurrency = 0, $morecss = '', $nooutput = 0)
5080 {
5081 // phpcs:enable
5082 global $langs;
5083
5084 $out = '';
5085
5086 $langs->load("admin");
5087 $num = 0;
5088
5089 $sql = "SELECT rowid, label, bank, clos as status, currency_code";
5090 $sql .= " FROM " . $this->db->prefix() . "bank_account";
5091 $sql .= " WHERE entity IN (" . getEntity('bank_account') . ")";
5092 if ($status != 2) {
5093 $sql .= " AND clos = " . (int) $status;
5094 }
5095 if ($filtre) { // TODO Support USF
5096 $sql .= " AND " . $filtre;
5097 }
5098 $sql .= " ORDER BY label";
5099
5100 dol_syslog(get_class($this) . "::select_comptes", LOG_DEBUG);
5101 $result = $this->db->query($sql);
5102 if ($result) {
5103 $num = $this->db->num_rows($result);
5104 $i = 0;
5105 if ($num) {
5106 $out .= '<select id="select' . $htmlname . '" class="flat selectbankaccount' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5107
5108 if (!empty($useempty) && !is_numeric($useempty)) {
5109 $out .= '<option value="-1">'.$langs->trans($useempty).'</option>';
5110 } elseif ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5111 $out .= '<option value="-1">&nbsp;</option>';
5112 }
5113
5114 while ($i < $num) {
5115 $obj = $this->db->fetch_object($result);
5116 if ($selected == $obj->rowid || ($useempty == 2 && $num == 1 && empty($selected))) {
5117 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '" selected>';
5118 } else {
5119 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '">';
5120 }
5121 $out .= trim($obj->label);
5122 if ($showcurrency) {
5123 $out .= ' (' . $obj->currency_code . ')';
5124 }
5125 if ($status == 2 && $obj->status == 1) {
5126 $out .= ' (' . $langs->trans("Closed") . ')';
5127 }
5128 $out .= '</option>';
5129 $i++;
5130 }
5131 $out .= "</select>";
5132 $out .= ajax_combobox('select' . $htmlname);
5133 } else {
5134 if ($status == 0) {
5135 $out .= '<span class="opacitymedium">' . $langs->trans("NoActiveBankAccountDefined") . '</span>';
5136 } else {
5137 $out .= '<span class="opacitymedium">' . $langs->trans("NoBankAccountFound") . '</span>';
5138 }
5139 }
5140 } else {
5141 dol_print_error($this->db);
5142 }
5143
5144 // Output or return
5145 if (empty($nooutput)) {
5146 print $out;
5147 } else {
5148 return $out;
5149 }
5150
5151 return $num;
5152 }
5153
5165 public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '')
5166 {
5167 global $langs;
5168
5169 $langs->load("admin");
5170 $num = 0;
5171
5172 $sql = "SELECT rowid, name, fk_country, status, entity";
5173 $sql .= " FROM " . $this->db->prefix() . "establishment";
5174 $sql .= " WHERE 1=1";
5175 if ($status != 2) {
5176 $sql .= " AND status = " . (int) $status;
5177 }
5178 if ($filtre) { // TODO Support USF
5179 $sql .= " AND " . $filtre;
5180 }
5181 $sql .= " ORDER BY name";
5182
5183 dol_syslog(get_class($this) . "::select_establishment", LOG_DEBUG);
5184 $result = $this->db->query($sql);
5185 if ($result) {
5186 $num = $this->db->num_rows($result);
5187 $i = 0;
5188 if ($num) {
5189 print '<select id="select' . $htmlname . '" class="flat selectestablishment" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5190 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5191 print '<option value="-1">&nbsp;</option>';
5192 }
5193
5194 while ($i < $num) {
5195 $obj = $this->db->fetch_object($result);
5196 if ($selected == $obj->rowid) {
5197 print '<option value="' . $obj->rowid . '" selected>';
5198 } else {
5199 print '<option value="' . $obj->rowid . '">';
5200 }
5201 print trim($obj->name);
5202 if ($status == 2 && $obj->status == 1) {
5203 print ' (' . $langs->trans("Closed") . ')';
5204 }
5205 print '</option>';
5206 $i++;
5207 }
5208 print "</select>";
5209 } else {
5210 if ($status == 0) {
5211 print '<span class="opacitymedium">' . $langs->trans("NoActiveEstablishmentDefined") . '</span>';
5212 } else {
5213 print '<span class="opacitymedium">' . $langs->trans("NoEstablishmentFound") . '</span>';
5214 }
5215 }
5216
5217 return $num;
5218 } else {
5219 dol_print_error($this->db);
5220 return -1;
5221 }
5222 }
5223
5233 public function formSelectAccount($page, $selected = '', $htmlname = 'fk_account', $addempty = 0)
5234 {
5235 global $langs;
5236 if ($htmlname != "none") {
5237 print '<form method="POST" action="' . $page . '">';
5238 print '<input type="hidden" name="action" value="setbankaccount">';
5239 print '<input type="hidden" name="token" value="' . newToken() . '">';
5240 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
5241 $nbaccountfound = $this->select_comptes($selected, $htmlname, 0, '', $addempty);
5242 if ($nbaccountfound > 0) {
5243 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5244 }
5245 print '</form>';
5246 } else {
5247 $langs->load('banks');
5248
5249 if ($selected) {
5250 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
5251 $bankstatic = new Account($this->db);
5252 $result = $bankstatic->fetch($selected);
5253 if ($result) {
5254 print $bankstatic->getNomUrl(1);
5255 }
5256 } else {
5257 print "&nbsp;";
5258 }
5259 }
5260 }
5261
5262 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5263
5283 public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $fromid = 0, $outputmode = 0, $include = 0, $morecss = '', $useempty = 1)
5284 {
5285 // phpcs:enable
5286 global $conf, $langs;
5287 $langs->load("categories");
5288
5289 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
5290
5291 // For backward compatibility
5292 if (is_numeric($type)) {
5293 dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING);
5294 }
5295
5296 if ($type === Categorie::TYPE_BANK_LINE) {
5297 // TODO Move this into common category feature
5298 $cate_arbo = array();
5299 $sql = "SELECT c.label, c.rowid";
5300 $sql .= " FROM " . $this->db->prefix() . "bank_categ as c";
5301 $sql .= " WHERE entity = " . $conf->entity;
5302 $sql .= " ORDER BY c.label";
5303 $result = $this->db->query($sql);
5304 if ($result) {
5305 $num = $this->db->num_rows($result);
5306 $i = 0;
5307 while ($i < $num) {
5308 $objp = $this->db->fetch_object($result);
5309 if ($objp) {
5310 $cate_arbo[$objp->rowid] = array('id' => $objp->rowid, 'fulllabel' => $objp->label, 'color' => '', 'picto' => 'category');
5311 }
5312 $i++;
5313 }
5314 $this->db->free($result);
5315 } else {
5316 dol_print_error($this->db);
5317 }
5318 } else {
5319 $cat = new Categorie($this->db);
5320 $cate_arbo = $cat->get_full_arbo($type, $fromid, $include);
5321 }
5322
5323 $outarray = array();
5324 $outarrayrichhtml = array();
5325
5326
5327 $output = '<select class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
5328 if (is_array($cate_arbo)) {
5329 $num = count($cate_arbo);
5330
5331 if (!$num) {
5332 $output .= '<option value="-1" disabled>' . $langs->trans("NoCategoriesDefined") . '</option>';
5333 } else {
5334 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5335 $output .= '<option value="-1">&nbsp;</option>';
5336 }
5337 foreach ($cate_arbo as $key => $value) {
5338 if ($cate_arbo[$key]['id'] == $selected || ($selected === 'auto' && count($cate_arbo) == 1)) {
5339 $add = 'selected ';
5340 } else {
5341 $add = '';
5342 }
5343
5344 $labeltoshow = img_picto('', 'category', 'class="pictofixedwidth" style="color: #' . $cate_arbo[$key]['color'] . '"');
5345 $labeltoshow .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5346
5347 $outarray[$cate_arbo[$key]['id']] = $cate_arbo[$key]['fulllabel'];
5348
5349 $outarrayrichhtml[$cate_arbo[$key]['id']] = $labeltoshow;
5350
5351 $output .= '<option ' . $add . 'value="' . $cate_arbo[$key]['id'] . '"';
5352 $output .= ' data-html="' . dol_escape_htmltag($labeltoshow) . '"';
5353 $output .= '>';
5354 $output .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5355 $output .= '</option>';
5356
5357 $cate_arbo[$key]['data-html'] = $labeltoshow;
5358 }
5359 }
5360 }
5361 $output .= '</select>';
5362 $output .= "\n";
5363
5364 if ($outputmode == 2) {
5365 // TODO: handle error when $cate_arbo is not an array
5366 return $cate_arbo;
5367 } elseif ($outputmode == 1) {
5368 return $outarray;
5369 } elseif ($outputmode == 3) {
5370 return $outarrayrichhtml;
5371 }
5372 return $output;
5373 }
5374
5375 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5376
5393 public function form_confirm($page, $title, $question, $action, $formquestion = array(), $selectedchoice = "", $useajax = 0, $height = 170, $width = 500)
5394 {
5395 // phpcs:enable
5396 dol_syslog(__METHOD__ . ': using form_confirm is deprecated. Use formconfim instead.', LOG_WARNING);
5397 print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width);
5398 }
5399
5427 public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No')
5428 {
5429 global $langs, $conf;
5430
5431 $more = '<!-- formconfirm - before call, page=' . dol_escape_htmltag($page) . ' -->';
5432 $formconfirm = '';
5433 $inputok = array();
5434 $inputko = array();
5435
5436 // Clean parameters
5437 $newselectedchoice = empty($selectedchoice) ? "no" : $selectedchoice;
5438 if ($conf->browser->layout == 'phone') {
5439 $width = '95%';
5440 }
5441
5442 // Set height automatically if not defined
5443 if (empty($height)) {
5444 $height = 220;
5445 if (is_array($formquestion) && count($formquestion) > 2) {
5446 $height += ((count($formquestion) - 2) * 24);
5447 }
5448 }
5449
5450 if (is_array($formquestion) && !empty($formquestion)) {
5451 // First add hidden fields and value
5452 foreach ($formquestion as $key => $input) {
5453 if (is_array($input) && !empty($input)) {
5454 if ($input['type'] == 'hidden') {
5455 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5456 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5457
5458 $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";
5459 }
5460 }
5461 }
5462
5463 // Now add questions
5464 $moreonecolumn = '';
5465 $more .= '<div class="tagtable paddingtopbottomonly centpercent noborderspacing">' . "\n";
5466 foreach ($formquestion as $key => $input) {
5467 if (is_array($input) && !empty($input)) {
5468 $size = (!empty($input['size']) ? ' size="' . $input['size'] . '"' : ''); // deprecated. Use morecss instead.
5469 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5470 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5471
5472 if ($input['type'] == 'text') {
5473 $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";
5474 } elseif ($input['type'] == 'password') {
5475 $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";
5476 } elseif ($input['type'] == 'textarea') {
5477 /*$more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">'.$input['label'].'</div><div class="tagtd">';
5478 $more .= '<textarea name="'.$input['name'].'" class="'.$morecss.'"'.$moreattr.'>';
5479 $more .= $input['value'];
5480 $more .= '</textarea>';
5481 $more .= '</div></div>'."\n";*/
5482 $moreonecolumn .= '<div class="margintoponly">';
5483 $moreonecolumn .= $input['label'] . '<br>';
5484 $moreonecolumn .= '<textarea name="' . dol_escape_htmltag($input['name']) . '" id="' . dol_escape_htmltag($input['name']) . '" class="' . $morecss . '"' . $moreattr . '>';
5485 $moreonecolumn .= $input['value'];
5486 $moreonecolumn .= '</textarea>';
5487 $moreonecolumn .= '</div>';
5488 } elseif (in_array($input['type'], ['select', 'multiselect'])) {
5489 if (empty($morecss)) {
5490 $morecss = 'minwidth100';
5491 }
5492
5493 $show_empty = isset($input['select_show_empty']) ? $input['select_show_empty'] : 1;
5494 $key_in_label = isset($input['select_key_in_label']) ? $input['select_key_in_label'] : 0;
5495 $value_as_key = isset($input['select_value_as_key']) ? $input['select_value_as_key'] : 0;
5496 $translate = isset($input['select_translate']) ? $input['select_translate'] : 0;
5497 $maxlen = isset($input['select_maxlen']) ? $input['select_maxlen'] : 0;
5498 $disabled = isset($input['select_disabled']) ? $input['select_disabled'] : 0;
5499 $sort = isset($input['select_sort']) ? $input['select_sort'] : '';
5500
5501 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">';
5502 if (!empty($input['label'])) {
5503 $more .= $input['label'] . '</div><div class="tagtd left">';
5504 }
5505 if ($input['type'] == 'select') {
5506 $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);
5507 } else {
5508 $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);
5509 }
5510 $more .= '</div></div>' . "\n";
5511 } elseif ($input['type'] == 'checkbox') {
5512 $more .= '<div class="tagtr">';
5513 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '"><label for="' . dol_escape_htmltag($input['name']) . '">' . $input['label'] . '</label></div><div class="tagtd">';
5514 $more .= '<input type="checkbox" class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $moreattr;
5515 if (!is_bool($input['value']) && $input['value'] != 'false' && $input['value'] != '0' && $input['value'] != '') {
5516 $more .= ' checked';
5517 }
5518 if (is_bool($input['value']) && $input['value']) {
5519 $more .= ' checked';
5520 }
5521 if (isset($input['disabled'])) {
5522 $more .= ' disabled';
5523 }
5524 $more .= ' /></div>';
5525 $more .= '</div>' . "\n";
5526 } elseif ($input['type'] == 'radio') {
5527 $i = 0;
5528 foreach ($input['values'] as $selkey => $selval) {
5529 $more .= '<div class="tagtr">';
5530 if (isset($input['label'])) {
5531 if ($i == 0) {
5532 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? ' tdtop' : (' tdtop ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5533 } else {
5534 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' "' . $input['tdclass'])) . '">&nbsp;</div>';
5535 }
5536 }
5537 $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;
5538 if (!empty($input['disabled'])) {
5539 $more .= ' disabled';
5540 }
5541 if (isset($input['default']) && $input['default'] === $selkey) {
5542 $more .= ' checked="checked"';
5543 }
5544 $more .= ' /> ';
5545 $more .= '<label for="' . dol_escape_htmltag($input['name'] . $selkey) . '" class="valignmiddle">' . $selval . '</label>';
5546 $more .= '</div></div>' . "\n";
5547 $i++;
5548 }
5549 } elseif ($input['type'] == 'date' || $input['type'] == 'datetime') {
5550 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5551 $more .= '<div class="tagtd">';
5552 $addnowlink = (empty($input['datenow']) ? 0 : 1);
5553 $h = $m = 0;
5554 if ($input['type'] == 'datetime') {
5555 $h = isset($input['hours']) ? $input['hours'] : 1;
5556 $m = isset($input['minutes']) ? $input['minutes'] : 1;
5557 }
5558 $more .= $this->selectDate(isset($input['value']) ? $input['value'] : -1, $input['name'], $h, $m, 0, '', 1, $addnowlink);
5559 $more .= '</div></div>'."\n";
5560 $formquestion[] = array('name' => $input['name'].'day');
5561 $formquestion[] = array('name' => $input['name'].'month');
5562 $formquestion[] = array('name' => $input['name'].'year');
5563 $formquestion[] = array('name' => $input['name'].'hour');
5564 $formquestion[] = array('name' => $input['name'].'min');
5565 } elseif ($input['type'] == 'other') { // can be 1 column or 2 depending if label is set or not
5566 $more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">';
5567 if (!empty($input['label'])) {
5568 $more .= $input['label'] . '</div><div class="tagtd">';
5569 }
5570 $more .= $input['value'];
5571 $more .= '</div></div>' . "\n";
5572 } elseif ($input['type'] == 'onecolumn') {
5573 $moreonecolumn .= '<div class="margintoponly">';
5574 $moreonecolumn .= $input['value'];
5575 $moreonecolumn .= '</div>' . "\n";
5576 } elseif ($input['type'] == 'hidden') {
5577 // Do nothing more, already added by a previous loop
5578 } elseif ($input['type'] == 'separator') {
5579 $more .= '<br>';
5580 } else {
5581 $more .= 'Error type ' . $input['type'] . ' for the confirm box is not a supported type';
5582 }
5583 }
5584 }
5585 $more .= '</div>' . "\n";
5586 $more .= $moreonecolumn;
5587 }
5588
5589 // JQUERY method dialog is broken with smartphone, we use standard HTML.
5590 // 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
5591 // See page product/card.php for example
5592 if (!empty($conf->dol_use_jmobile)) {
5593 $useajax = 0;
5594 }
5595 if (empty($conf->use_javascript_ajax)) {
5596 $useajax = 0;
5597 }
5598
5599 if ($useajax) {
5600 $autoOpen = true;
5601 $dialogconfirm = 'dialog-confirm';
5602 $button = '';
5603 if (!is_numeric($useajax)) {
5604 $button = $useajax;
5605 $useajax = 1;
5606 $autoOpen = false;
5607 $dialogconfirm .= '-' . $button;
5608 }
5609 $pageyes = $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=yes';
5610 $pageno = ($useajax == 2 ? $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=no' : '');
5611
5612 // Add input fields into list of fields to read during submit (inputok and inputko)
5613 if (is_array($formquestion)) {
5614 foreach ($formquestion as $key => $input) {
5615 //print "xx ".$key." rr ".is_array($input)."<br>\n";
5616 // Add name of fields to propagate with the GET when submitting the form with button OK.
5617 if (is_array($input) && isset($input['name'])) {
5618 if (strpos($input['name'], ',') > 0) {
5619 $inputok = array_merge($inputok, explode(',', $input['name']));
5620 } else {
5621 array_push($inputok, $input['name']);
5622 }
5623 }
5624 // Add name of fields to propagate with the GET when submitting the form with button KO.
5625 // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset
5626 if (is_array($input) && isset($input['inputko']) && $input['inputko'] == 1 && isset($input['name'])) {
5627 array_push($inputko, $input['name']);
5628 }
5629 }
5630 }
5631
5632 // Show JQuery confirm box.
5633 $formconfirm .= '<div id="' . $dialogconfirm . '" title="' . dol_escape_htmltag($title) . '" style="display: none;">';
5634 if (is_array($formquestion) && array_key_exists('text', $formquestion) && !empty($formquestion['text'])) {
5635 $formconfirm .= '<div class="confirmtext">' . $formquestion['text'] . '</div>' . "\n";
5636 }
5637 if (!empty($more)) {
5638 $formconfirm .= '<div class="confirmquestions">' . $more . '</div>' . "\n";
5639 }
5640 $formconfirm .= ($question ? '<div class="confirmmessage">' . img_help(0, '') . ' ' . $question . '</div>' : '');
5641 $formconfirm .= '</div>' . "\n";
5642
5643 $formconfirm .= "\n<!-- begin code of popup for formconfirm page=" . $page . " -->\n";
5644 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5645 $formconfirm .= "/* Code for the jQuery('#dialogforpopup').dialog() */\n";
5646 $formconfirm .= 'jQuery(document).ready(function() {
5647 $(function() {
5648 $( "#' . $dialogconfirm . '" ).dialog(
5649 {
5650 autoOpen: ' . ($autoOpen ? "true" : "false") . ',';
5651 if ($newselectedchoice == 'no') {
5652 $formconfirm .= '
5653 open: function() {
5654 $(this).parent().find("button.ui-button:eq(2)").focus();
5655 },';
5656 }
5657
5658 $jsforcursor = '';
5659 if ($useajax == 1) {
5660 $jsforcursor = '// The call to urljump can be slow, so we set the wait cursor' . "\n";
5661 $jsforcursor .= 'jQuery("html,body,#id-container").addClass("cursorwait");' . "\n";
5662 }
5663
5664 $postconfirmas = 'GET';
5665
5666 $formconfirm .= '
5667 resizable: false,
5668 height: "' . $height . '",
5669 width: "' . $width . '",
5670 modal: true,
5671 closeOnEscape: false,
5672 buttons: {
5673 "' . dol_escape_js($langs->transnoentities($labelbuttonyes)) . '": function() {
5674 var options = "token=' . urlencode(newToken()) . '";
5675 var inputok = ' . json_encode($inputok) . '; /* List of fields into form */
5676 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5677 var pageyes = "' . dol_escape_js(!empty($pageyes) ? $pageyes : '') . '";
5678
5679 if (inputok.length > 0) {
5680 $.each(inputok, function(i, inputname) {
5681 var more = "";
5682 var inputvalue;
5683 if ($("input[name=\'" + inputname + "\']").attr("type") == "radio") {
5684 inputvalue = $("input[name=\'" + inputname + "\']:checked").val();
5685 } else {
5686 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5687 inputvalue = $("#" + inputname + more).val();
5688 }
5689 if (typeof inputvalue == "undefined") { inputvalue=""; }
5690 console.log("formconfirm check inputname="+inputname+" inputvalue="+inputvalue);
5691 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5692 });
5693 }
5694 var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "&") + options;
5695 if (pageyes.length > 0) {';
5696 if ($postconfirmas == 'GET') {
5697 $formconfirm .= 'location.href = urljump;';
5698 } else {
5699 $formconfirm .= $jsforcursor;
5700 $formconfirm .= 'var post = $.post(
5701 pageyes,
5702 options,
5703 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5704 );';
5705 }
5706 $formconfirm .= '
5707 console.log("after post ok");
5708 }
5709 $(this).dialog("close");
5710 },
5711 "' . dol_escape_js($langs->transnoentities($labelbuttonno)) . '": function() {
5712 var options = "token=' . urlencode(newToken()) . '";
5713 var inputko = ' . json_encode($inputko) . '; /* List of fields into form */
5714 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5715 var pageno="' . dol_escape_js(!empty($pageno) ? $pageno : '') . '";
5716 if (inputko.length > 0) {
5717 $.each(inputko, function(i, inputname) {
5718 var more = "";
5719 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5720 var inputvalue = $("#" + inputname + more).val();
5721 if (typeof inputvalue == "undefined") { inputvalue=""; }
5722 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5723 });
5724 }
5725 var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "&") + options;
5726 //alert(urljump);
5727 if (pageno.length > 0) {';
5728 if ($postconfirmas == 'GET') {
5729 $formconfirm .= 'location.href = urljump;';
5730 } else {
5731 $formconfirm .= $jsforcursor;
5732 $formconfirm .= 'var post = $.post(
5733 pageno,
5734 options,
5735 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5736 );';
5737 }
5738 $formconfirm .= '
5739 console.log("after post ko");
5740 }
5741 $(this).dialog("close");
5742 }
5743 }
5744 }
5745 );
5746
5747 var button = "' . $button . '";
5748 if (button.length > 0) {
5749 $( "#" + button ).click(function() {
5750 $("#' . $dialogconfirm . '").dialog("open");
5751 });
5752 }
5753 });
5754 });
5755 </script>';
5756 $formconfirm .= "<!-- end ajax formconfirm -->\n";
5757 } else {
5758 $formconfirm .= "\n<!-- begin formconfirm page=" . dol_escape_htmltag($page) . " -->\n";
5759
5760 if (empty($disableformtag)) {
5761 $formconfirm .= '<form method="POST" action="' . $page . '" class="notoptoleftroright">' . "\n";
5762 }
5763
5764 $formconfirm .= '<input type="hidden" name="action" value="' . $action . '">' . "\n";
5765 $formconfirm .= '<input type="hidden" name="token" value="' . newToken() . '">' . "\n";
5766
5767 $formconfirm .= '<table class="valid centpercent">' . "\n";
5768
5769 // Line title
5770 $formconfirm .= '<tr class="validtitre"><td class="validtitre" colspan="2">';
5771 $formconfirm .= img_picto('', 'pictoconfirm') . ' ' . $title;
5772 $formconfirm .= '</td></tr>' . "\n";
5773
5774 // Line text
5775 if (is_array($formquestion) && array_key_exists('text', $formquestion) && !empty($formquestion['text'])) {
5776 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . $formquestion['text'] . '</td></tr>' . "\n";
5777 }
5778
5779 // Line form fields
5780 if ($more) {
5781 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . "\n";
5782 $formconfirm .= $more;
5783 $formconfirm .= '</td></tr>' . "\n";
5784 }
5785
5786 // Line with question
5787 $formconfirm .= '<tr class="valid">';
5788 $formconfirm .= '<td class="valid">' . $question . '</td>';
5789 $formconfirm .= '<td class="valid center">';
5790 $formconfirm .= $this->selectyesno("confirm", $newselectedchoice, 0, false, 0, 0, 'marginleftonly marginrightonly', $labelbuttonyes, $labelbuttonno);
5791 $formconfirm .= '<input class="button valignmiddle confirmvalidatebutton small" type="submit" value="' . $langs->trans("Validate") . '">';
5792 $formconfirm .= '</td>';
5793 $formconfirm .= '</tr>' . "\n";
5794
5795 $formconfirm .= '</table>' . "\n";
5796
5797 if (empty($disableformtag)) {
5798 $formconfirm .= "</form>\n";
5799 }
5800 $formconfirm .= '<br>';
5801
5802 if (!empty($conf->use_javascript_ajax)) {
5803 $formconfirm .= '<!-- code to disable button to avoid double clic -->';
5804 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5805 $formconfirm .= '
5806 $(document).ready(function () {
5807 $(".confirmvalidatebutton").on("click", function() {
5808 console.log("We click on button confirmvalidatebutton");
5809 $(this).attr("disabled", "disabled");
5810 setTimeout(\'$(".confirmvalidatebutton").removeAttr("disabled")\', 3000);
5811 //console.log($(this).closest("form"));
5812 $(this).closest("form").submit();
5813 });
5814 });
5815 ';
5816 $formconfirm .= '</script>' . "\n";
5817 }
5818
5819 $formconfirm .= "<!-- end formconfirm -->\n";
5820 }
5821
5822 return $formconfirm;
5823 }
5824
5825
5826 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5827
5843 public function form_project($page, $socid, $selected = '', $htmlname = 'projectid', $discard_closed = 0, $maxlength = 20, $forcefocus = 0, $nooutput = 0, $textifnoproject = '', $morecss = '')
5844 {
5845 // phpcs:enable
5846 global $langs;
5847
5848 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
5849 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
5850
5851 $out = '';
5852
5853 $formproject = new FormProjets($this->db);
5854
5855 $langs->load("project");
5856 if ($htmlname != "none") {
5857 $out .= '<form method="post" action="' . $page . '">';
5858 $out .= '<input type="hidden" name="action" value="classin">';
5859 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5860 $out .= $formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1, 0, $morecss);
5861 $out .= '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5862 $out .= '</form>';
5863 } else {
5864 $out .= '<span class="project_head_block">';
5865 if ($selected) {
5866 $projet = new Project($this->db);
5867 $projet->fetch($selected);
5868 $out .= $projet->getNomUrl(0, '', 1);
5869 } else {
5870 $out .= '<span class="opacitymedium">' . $textifnoproject . '</span>';
5871 }
5872 $out .= '</span>';
5873 }
5874
5875 if (empty($nooutput)) {
5876 print $out;
5877 return '';
5878 }
5879 return $out;
5880 }
5881
5882 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5883
5899 public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0, $type = '', $filtertype = -1, $deposit_percent = -1, $nooutput = 0)
5900 {
5901 // phpcs:enable
5902 global $langs;
5903
5904 $out = '';
5905
5906 if ($htmlname != "none") {
5907 $out .= '<form method="POST" action="' . $page . '">';
5908 $out .= '<input type="hidden" name="action" value="setconditions">';
5909 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5910 if ($type) {
5911 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5912 }
5913 $out .= $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, 0, '', $deposit_percent);
5914 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5915 $out .= '</form>';
5916 } else {
5917 if ($selected) {
5919 if (isset($this->cache_conditions_paiements[$selected])) {
5920 $label = $this->cache_conditions_paiements[$selected]['label'];
5921
5922 if (!empty($this->cache_conditions_paiements[$selected]['deposit_percent'])) {
5923 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $this->cache_conditions_paiements[$selected]['deposit_percent'], $label);
5924 }
5925
5926 $out .= $label;
5927 } else {
5928 $langs->load('errors');
5929 $out .= $langs->trans('ErrorNotInDictionaryPaymentConditions');
5930 }
5931 } else {
5932 $out .= '&nbsp;';
5933 }
5934 }
5935
5936 if (empty($nooutput)) {
5937 print $out;
5938 return '';
5939 }
5940 return $out;
5941 }
5942
5943 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5944
5954 public function form_availability($page, $selected = '', $htmlname = 'availability', $addempty = 0)
5955 {
5956 // phpcs:enable
5957 global $langs;
5958 if ($htmlname != "none") {
5959 print '<form method="post" action="' . $page . '">';
5960 print '<input type="hidden" name="action" value="setavailability">';
5961 print '<input type="hidden" name="token" value="' . newToken() . '">';
5962 $this->selectAvailabilityDelay($selected, $htmlname, -1, $addempty);
5963 print '<input type="submit" name="modify" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5964 print '<input type="submit" name="cancel" class="button smallpaddingimp" value="' . $langs->trans("Cancel") . '">';
5965 print '</form>';
5966 } else {
5967 if ($selected) {
5968 $this->load_cache_availability();
5969 print $this->cache_availability[$selected]['label'];
5970 } else {
5971 print "&nbsp;";
5972 }
5973 }
5974 }
5975
5986 public function formInputReason($page, $selected = '', $htmlname = 'demandreason', $addempty = 0)
5987 {
5988 global $langs;
5989 if ($htmlname != "none") {
5990 print '<form method="post" action="' . $page . '">';
5991 print '<input type="hidden" name="action" value="setdemandreason">';
5992 print '<input type="hidden" name="token" value="' . newToken() . '">';
5993 $this->selectInputReason($selected, $htmlname, -1, $addempty);
5994 print '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5995 print '</form>';
5996 } else {
5997 if ($selected) {
5998 $this->loadCacheInputReason();
5999 foreach ($this->cache_demand_reason as $key => $val) {
6000 if ($val['id'] == $selected) {
6001 print $val['label'];
6002 break;
6003 }
6004 }
6005 } else {
6006 print "&nbsp;";
6007 }
6008 }
6009 }
6010
6011 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6012
6026 public function form_date($page, $selected, $htmlname, $displayhour = 0, $displaymin = 0, $nooutput = 0, $type = '')
6027 {
6028 // phpcs:enable
6029 global $langs;
6030
6031 $ret = '';
6032
6033 if ($htmlname != "none") {
6034 $ret .= '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
6035 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
6036 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
6037 if ($type) {
6038 $ret .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
6039 }
6040 $ret .= '<table class="nobordernopadding">';
6041 $ret .= '<tr><td>';
6042 $ret .= $this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form' . $htmlname, 1, 0);
6043 $ret .= '</td>';
6044 $ret .= '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6045 $ret .= '</tr></table></form>';
6046 } else {
6047 if ($displayhour) {
6048 $ret .= dol_print_date($selected, 'dayhour');
6049 } else {
6050 $ret .= dol_print_date($selected, 'day');
6051 }
6052 }
6053
6054 if (empty($nooutput)) {
6055 print $ret;
6056 }
6057 return $ret;
6058 }
6059
6060
6061 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6062
6073 public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = array(), $include = array())
6074 {
6075 // phpcs:enable
6076 global $langs;
6077
6078 if ($htmlname != "none") {
6079 print '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
6080 print '<input type="hidden" name="action" value="set' . $htmlname . '">';
6081 print '<input type="hidden" name="token" value="' . newToken() . '">';
6082 print $this->select_dolusers($selected, $htmlname, 1, $exclude, 0, $include);
6083 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6084 print '</form>';
6085 } else {
6086 if ($selected) {
6087 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
6088 $theuser = new User($this->db);
6089 $theuser->fetch($selected);
6090 print $theuser->getNomUrl(1);
6091 } else {
6092 print "&nbsp;";
6093 }
6094 }
6095 }
6096
6097
6098 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6099
6113 public function form_modes_reglement($page, $selected = '', $htmlname = 'mode_reglement_id', $filtertype = '', $active = 1, $addempty = 0, $type = '', $nooutput = 0)
6114 {
6115 // phpcs:enable
6116 global $langs;
6117
6118 $out = '';
6119 if ($htmlname != "none") {
6120 $out .= '<form method="POST" action="' . $page . '">';
6121 $out .= '<input type="hidden" name="action" value="setmode">';
6122 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6123 if ($type) {
6124 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
6125 }
6126 $out .= $this->select_types_paiements($selected, $htmlname, $filtertype, 0, $addempty, 0, 0, $active, '', 1);
6127 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6128 $out .= '</form>';
6129 } else {
6130 if ($selected) {
6132 $out .= $this->cache_types_paiements[$selected]['label'];
6133 } else {
6134 $out .= "&nbsp;";
6135 }
6136 }
6137
6138 if ($nooutput) {
6139 return $out;
6140 } else {
6141 print $out;
6142 }
6143 return '';
6144 }
6145
6156 public function formSelectTransportMode($page, $selected = '', $htmlname = 'transport_mode_id', $active = 1, $addempty = 0)
6157 {
6158 global $langs;
6159 if ($htmlname != "none") {
6160 print '<form method="POST" action="' . $page . '">';
6161 print '<input type="hidden" name="action" value="settransportmode">';
6162 print '<input type="hidden" name="token" value="' . newToken() . '">';
6163 $this->selectTransportMode($selected, $htmlname, 0, $addempty, 0, 0, $active);
6164 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6165 print '</form>';
6166 } else {
6167 if ($selected) {
6169 print $this->cache_transport_mode[$selected]['label'];
6170 } else {
6171 print "&nbsp;";
6172 }
6173 }
6174 }
6175
6176 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6177
6186 public function form_multicurrency_code($page, $selected = '', $htmlname = 'multicurrency_code')
6187 {
6188 // phpcs:enable
6189 global $langs;
6190 if ($htmlname != "none") {
6191 print '<form method="POST" action="' . $page . '">';
6192 print '<input type="hidden" name="action" value="setmulticurrencycode">';
6193 print '<input type="hidden" name="token" value="' . newToken() . '">';
6194 print $this->selectMultiCurrency($selected, $htmlname, 0);
6195 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6196 print '</form>';
6197 } else {
6198 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6199 print !empty($selected) ? currency_name($selected, 1) : '&nbsp;';
6200 }
6201 }
6202
6203 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6204
6214 public function form_multicurrency_rate($page, $rate = 0.0, $htmlname = 'multicurrency_tx', $currency = '')
6215 {
6216 // phpcs:enable
6217 global $langs, $mysoc, $conf;
6218
6219 if ($htmlname != "none") {
6220 print '<form method="POST" action="' . $page . '">';
6221 print '<input type="hidden" name="action" value="setmulticurrencyrate">';
6222 print '<input type="hidden" name="token" value="' . newToken() . '">';
6223 print '<input type="text" class="maxwidth100" name="' . $htmlname . '" value="' . (!empty($rate) ? price(price2num($rate, 'CU')) : 1) . '" /> ';
6224 print '<select name="calculation_mode">';
6225 print '<option value="1">Change ' . $langs->trans("PriceUHT") . ' of lines</option>';
6226 print '<option value="2">Change ' . $langs->trans("PriceUHTCurrency") . ' of lines</option>';
6227 print '</select> ';
6228 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6229 print '</form>';
6230 } else {
6231 if (!empty($rate)) {
6232 print price($rate, 1, $langs, 0, 0);
6233 if ($currency && $rate != 1) {
6234 print ' &nbsp; (' . price($rate, 1, $langs, 0, 0) . ' ' . $currency . ' = 1 ' . $conf->currency . ')';
6235 }
6236 } else {
6237 print 1;
6238 }
6239 }
6240 }
6241
6242
6243 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6244
6260 public function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter = '', $maxvalue = 0, $more = '', $hidelist = 0, $discount_type = 0)
6261 {
6262 // phpcs:enable
6263 global $conf, $langs;
6264 if ($htmlname != "none") {
6265 print '<form method="post" action="' . $page . '">';
6266 print '<input type="hidden" name="action" value="setabsolutediscount">';
6267 print '<input type="hidden" name="token" value="' . newToken() . '">';
6268 print '<div class="inline-block">';
6269 if (!empty($discount_type)) {
6270 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
6271 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL") {
6272 $translationKey = 'HasAbsoluteDiscountFromSupplier'; // If we want deposit to be subtracted to payments only and not to total of final invoice
6273 } else {
6274 $translationKey = 'HasCreditNoteFromSupplier';
6275 }
6276 } else {
6277 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6278 $translationKey = 'HasAbsoluteDiscountFromSupplier';
6279 } else {
6280 $translationKey = 'HasCreditNoteFromSupplier';
6281 }
6282 }
6283 } else {
6284 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
6285 if (!$filter || $filter == "fk_facture_source IS NULL") {
6286 $translationKey = 'CompanyHasAbsoluteDiscount'; // If we want deposit to be subtracted to payments only and not to total of final invoice
6287 } else {
6288 $translationKey = 'CompanyHasCreditNote';
6289 }
6290 } else {
6291 if (!$filter || $filter == "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6292 $translationKey = 'CompanyHasAbsoluteDiscount';
6293 } else {
6294 $translationKey = 'CompanyHasCreditNote';
6295 }
6296 }
6297 }
6298 print $langs->trans($translationKey, price($amount, 0, $langs, 0, 0, -1, $conf->currency));
6299 if (empty($hidelist)) {
6300 print ' ';
6301 }
6302 print '</div>';
6303 if (empty($hidelist)) {
6304 print '<div class="inline-block" style="padding-right: 10px">';
6305 $newfilter = 'discount_type=' . intval($discount_type);
6306 if (!empty($discount_type)) {
6307 $newfilter .= ' AND fk_invoice_supplier IS NULL AND fk_invoice_supplier_line IS NULL'; // Supplier discounts available
6308 } else {
6309 $newfilter .= ' AND fk_facture IS NULL AND fk_facture_line IS NULL'; // Customer discounts available
6310 }
6311 if ($filter) {
6312 $newfilter .= ' AND (' . $filter . ')';
6313 }
6314 // output the combo of discounts
6315 $nbqualifiedlines = $this->select_remises($selected, $htmlname, $newfilter, $socid, $maxvalue);
6316 if ($nbqualifiedlines > 0) {
6317 print ' &nbsp; <input type="submit" class="button smallpaddingimp" value="' . dol_escape_htmltag($langs->trans("UseLine")) . '"';
6318 if (!empty($discount_type) && $filter && $filter != "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6319 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6320 }
6321 if (empty($discount_type) && $filter && $filter != "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6322 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6323 }
6324
6325 print '>';
6326 }
6327 print '</div>';
6328 }
6329 if ($more) {
6330 print '<div class="inline-block">';
6331 print $more;
6332 print '</div>';
6333 }
6334 print '</form>';
6335 } else {
6336 if ($selected) {
6337 print $selected;
6338 } else {
6339 print "0";
6340 }
6341 }
6342 }
6343
6344
6345 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6346
6356 public function form_contacts($page, $societe, $selected = '', $htmlname = 'contactid')
6357 {
6358 // phpcs:enable
6359 global $langs;
6360
6361 if ($htmlname != "none") {
6362 print '<form method="post" action="' . $page . '">';
6363 print '<input type="hidden" name="action" value="set_contact">';
6364 print '<input type="hidden" name="token" value="' . newToken() . '">';
6365 print '<table class="nobordernopadding">';
6366 print '<tr><td>';
6367 print $this->selectcontacts($societe->id, $selected, $htmlname);
6368 $num = $this->num;
6369 if ($num == 0) {
6370 $addcontact = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("AddContact") : $langs->trans("AddContactAddress"));
6371 print '<a href="' . DOL_URL_ROOT . '/contact/card.php?socid=' . $societe->id . '&amp;action=create&amp;backtoreferer=1">' . $addcontact . '</a>';
6372 }
6373 print '</td>';
6374 print '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6375 print '</tr></table></form>';
6376 } else {
6377 if ($selected) {
6378 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
6379 $contact = new Contact($this->db);
6380 $contact->fetch($selected);
6381 print $contact->getFullName($langs);
6382 } else {
6383 print "&nbsp;";
6384 }
6385 }
6386 }
6387
6388 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6389
6406 public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0, $excludeids = array(), $textifnothirdparty = '')
6407 {
6408 // phpcs:enable
6409 global $langs;
6410
6411 $out = '';
6412 if ($htmlname != "none") {
6413 $out .= '<form method="post" action="' . $page . '">';
6414 $out .= '<input type="hidden" name="action" value="set_thirdparty">';
6415 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6416 $out .= $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, 0, 'minwidth100', '', '', 1, array(), false, $excludeids);
6417 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6418 $out .= '</form>';
6419 } else {
6420 if ($selected) {
6421 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
6422 $soc = new Societe($this->db);
6423 $soc->fetch($selected);
6424 $out .= $soc->getNomUrl(0, '');
6425 } else {
6426 $out .= '<span class="opacitymedium">' . $textifnothirdparty . '</span>';
6427 }
6428 }
6429
6430 if ($nooutput) {
6431 return $out;
6432 } else {
6433 print $out;
6434 }
6435
6436 return '';
6437 }
6438
6439 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6440
6449 public function select_currency($selected = '', $htmlname = 'currency_id')
6450 {
6451 // phpcs:enable
6452 print $this->selectCurrency($selected, $htmlname);
6453 }
6454
6464 public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0, $useempty = '')
6465 {
6466 global $langs, $user;
6467
6468 $langs->loadCacheCurrencies('');
6469
6470 $out = '';
6471
6472 if ($selected == 'euro' || $selected == 'euros') {
6473 $selected = 'EUR'; // Pour compatibilite
6474 }
6475
6476 $out .= '<select class="flat maxwidth200onsmartphone minwidth300" name="' . $htmlname . '" id="' . $htmlname . '">';
6477 if ($useempty) {
6478 $out .= '<option value="-1" selected></option>';
6479 }
6480 foreach ($langs->cache_currencies as $code_iso => $currency) {
6481 $labeltoshow = $currency['label'];
6482 if ($mode == 1) {
6483 $labeltoshow .= ' <span class="opacitymedium">(' . $code_iso . ')</span>';
6484 } else {
6485 $labeltoshow .= ' <span class="opacitymedium">(' . $langs->getCurrencySymbol($code_iso) . ')</span>';
6486 }
6487
6488 if ($selected && $selected == $code_iso) {
6489 $out .= '<option value="' . $code_iso . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6490 } else {
6491 $out .= '<option value="' . $code_iso . '" data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6492 }
6493 $out .= $labeltoshow;
6494 $out .= '</option>';
6495 }
6496 $out .= '</select>';
6497 if ($user->admin) {
6498 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
6499 }
6500
6501 // Make select dynamic
6502 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6503 $out .= ajax_combobox($htmlname);
6504
6505 return $out;
6506 }
6507
6520 public function selectMultiCurrency($selected = '', $htmlname = 'multicurrency_code', $useempty = 0, $filter = '', $excludeConfCurrency = false, $morecss = '')
6521 {
6522 global $conf, $langs;
6523
6524 $langs->loadCacheCurrencies(''); // Load ->cache_currencies
6525
6526 $TCurrency = array();
6527
6528 $sql = "SELECT code FROM " . $this->db->prefix() . "multicurrency";
6529 $sql .= " WHERE entity IN ('" . getEntity('mutlicurrency') . "')";
6530 if ($filter) {
6531 $sql .= " AND " . $filter;
6532 }
6533 $resql = $this->db->query($sql);
6534 if ($resql) {
6535 while ($obj = $this->db->fetch_object($resql)) {
6536 $TCurrency[$obj->code] = $obj->code;
6537 }
6538 }
6539
6540 $out = '';
6541 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
6542 if ($useempty) {
6543 $out .= '<option value="">&nbsp;</option>';
6544 }
6545 // If company current currency not in table, we add it into list. Should always be available.
6546 if (!in_array($conf->currency, $TCurrency) && !$excludeConfCurrency) {
6547 $TCurrency[$conf->currency] = $conf->currency;
6548 }
6549 if (count($TCurrency) > 0) {
6550 foreach ($langs->cache_currencies as $code_iso => $currency) {
6551 if (isset($TCurrency[$code_iso])) {
6552 if (!empty($selected) && $selected == $code_iso) {
6553 $out .= '<option value="' . $code_iso . '" selected="selected">';
6554 } else {
6555 $out .= '<option value="' . $code_iso . '">';
6556 }
6557
6558 $out .= $currency['label'];
6559 $out .= ' (' . $langs->getCurrencySymbol($code_iso) . ')';
6560 $out .= '</option>';
6561 }
6562 }
6563 }
6564
6565 $out .= '</select>';
6566
6567 // Make select dynamic
6568 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6569 $out .= ajax_combobox($htmlname);
6570
6571 return $out;
6572 }
6573
6574 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6575
6582 public function load_cache_vatrates($country_code)
6583 {
6584 // phpcs:enable
6585 global $langs, $user;
6586
6587 $num = count($this->cache_vatrates);
6588 if ($num > 0) {
6589 return $num; // Cache already loaded
6590 }
6591
6592 dol_syslog(__METHOD__, LOG_DEBUG);
6593
6594 $sql = "SELECT t.rowid, t.type_vat, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
6595 $sql .= " FROM ".$this->db->prefix()."c_tva as t, ".$this->db->prefix()."c_country as c";
6596 $sql .= " WHERE t.fk_pays = c.rowid";
6597 $sql .= " AND t.active > 0";
6598 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
6599 $sql .= " AND c.code IN (" . $this->db->sanitize($country_code, 1) . ")";
6600 $sql .= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC";
6601
6602 $resql = $this->db->query($sql);
6603 if ($resql) {
6604 $num = $this->db->num_rows($resql);
6605 if ($num) {
6606 for ($i = 0; $i < $num; $i++) {
6607 $obj = $this->db->fetch_object($resql);
6608
6609 $tmparray = array();
6610 $tmparray['rowid'] = $obj->rowid;
6611 $tmparray['type_vat'] = $obj->type_vat;
6612 $tmparray['code'] = $obj->code;
6613 $tmparray['txtva'] = $obj->taux;
6614 $tmparray['nprtva'] = $obj->recuperableonly;
6615 $tmparray['localtax1'] = $obj->localtax1;
6616 $tmparray['localtax1_type'] = $obj->localtax1_type;
6617 $tmparray['localtax2'] = $obj->localtax2;
6618 $tmparray['localtax2_type'] = $obj->localtax1_type;
6619 $tmparray['label'] = $obj->taux . '%' . ($obj->code ? ' (' . $obj->code . ')' : ''); // Label must contains only 0-9 , . % or *
6620 $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
6621 $positiverates = '';
6622 if ($obj->taux) {
6623 $positiverates .= ($positiverates ? '/' : '') . $obj->taux;
6624 }
6625 if ($obj->localtax1) {
6626 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax1;
6627 }
6628 if ($obj->localtax2) {
6629 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax2;
6630 }
6631 if (empty($positiverates)) {
6632 $positiverates = '0';
6633 }
6634 $tmparray['labelpositiverates'] = $positiverates . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
6635
6636 $this->cache_vatrates[$obj->rowid] = $tmparray;
6637 }
6638
6639 return $num;
6640 } else {
6641 $this->error = '<span class="error">';
6642 $this->error .= $langs->trans("ErrorNoVATRateDefinedForSellerCountry", $country_code);
6643 $reg = array();
6644 if (!empty($user) && $user->admin && preg_match('/\'(..)\'/', $country_code, $reg)) {
6645 $langs->load("errors");
6646 $new_country_code = $reg[1];
6647 $country_id = dol_getIdFromCode($this->db, $new_country_code, 'c_pays', 'code', 'rowid');
6648 $this->error .= '<br>'.$langs->trans("ErrorFixThisHere", DOL_URL_ROOT.'/admin/dict.php?id=10'.($country_id > 0 ? '&countryidforinsert='.$country_id : ''));
6649 }
6650 $this->error .= '</span>';
6651 return -1;
6652 }
6653 } else {
6654 $this->error = '<span class="error">' . $this->db->error() . '</span>';
6655 return -2;
6656 }
6657 }
6658
6659 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6660
6683 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)
6684 {
6685 // phpcs:enable
6686 global $langs, $mysoc;
6687
6688 $langs->load('errors');
6689
6690 $return = '';
6691
6692 // Define defaultnpr, defaultttx and defaultcode
6693 $defaultnpr = ($info_bits & 0x01);
6694 $defaultnpr = (preg_match('/\*/', $selectedrate) ? 1 : $defaultnpr);
6695 $defaulttx = str_replace('*', '', $selectedrate);
6696 $defaultcode = '';
6697 $reg = array();
6698 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6699 $defaultcode = $reg[1];
6700 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6701 }
6702 //var_dump($selectedrate.'-'.$defaulttx.'-'.$defaultnpr.'-'.$defaultcode);
6703
6704 // Check parameters
6705 if (is_object($societe_vendeuse) && !$societe_vendeuse->country_code) {
6706 if ($societe_vendeuse->id == $mysoc->id) {
6707 $return .= '<span class="error">' . $langs->trans("ErrorYourCountryIsNotDefined") . '</span>';
6708 } else {
6709 $return .= '<span class="error">' . $langs->trans("ErrorSupplierCountryIsNotDefined") . '</span>';
6710 }
6711 return $return;
6712 }
6713
6714 //var_dump($societe_acheteuse);
6715 //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";
6716 //exit;
6717
6718 // Define list of countries to use to search VAT rates to show
6719 // First we defined code_country to use to find list
6720 if (is_object($societe_vendeuse)) {
6721 $code_country = "'" . $societe_vendeuse->country_code . "'";
6722 } else {
6723 $code_country = "'" . $mysoc->country_code . "'"; // Pour compatibilite ascendente
6724 }
6725 if (getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC')) { // If option to have vat for end customer for services is on
6726 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6727 // If SERVICE_ARE_ECOMMERCE_200238EC=1 combo list vat rate of purchaser and seller countries
6728 // If SERVICE_ARE_ECOMMERCE_200238EC=2 combo list only the vat rate of the purchaser country
6729 $selectVatComboMode = getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC');
6730 if (isInEEC($societe_vendeuse) && isInEEC($societe_acheteuse) && !$societe_acheteuse->isACompany()) {
6731 // We also add the buyer country code
6732 if (is_numeric($type)) {
6733 if ($type == 1) { // We know product is a service
6734 switch ($selectVatComboMode) {
6735 case '1':
6736 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6737 break;
6738 case '2':
6739 $code_country = "'" . $societe_acheteuse->country_code . "'";
6740 break;
6741 }
6742 }
6743 } elseif (!$idprod) { // We don't know type of product
6744 switch ($selectVatComboMode) {
6745 case '1':
6746 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6747 break;
6748 case '2':
6749 $code_country = "'" . $societe_acheteuse->country_code . "'";
6750 break;
6751 }
6752 } else {
6753 $prodstatic = new Product($this->db);
6754 $prodstatic->fetch($idprod);
6755 if ($prodstatic->type == Product::TYPE_SERVICE) { // We know product is a service
6756 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6757 }
6758 }
6759 }
6760 }
6761
6762 // Now we load the list of VAT
6763 $this->load_cache_vatrates($code_country); // If no vat defined, return -1 with message into this->error
6764
6765 // Keep only the VAT qualified for $type_vat
6766 $arrayofvatrates = array();
6767 foreach ($this->cache_vatrates as $cachevalue) {
6768 if (empty($cachevalue['type_vat']) || $cachevalue['type_vat'] != $type_vat) {
6769 $arrayofvatrates[] = $cachevalue;
6770 }
6771 }
6772
6773 $num = count($arrayofvatrates);
6774
6775 if ($num > 0) {
6776 // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '')
6777 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6778 $tmpthirdparty = new Societe($this->db);
6779
6780 $defaulttx = get_default_tva($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6781 $defaultnpr = get_default_npr($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6782
6783 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6784 $defaultcode = $reg[1];
6785 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6786 }
6787 if (empty($defaulttx)) {
6788 $defaultnpr = 0;
6789 }
6790 }
6791
6792 // If we fails to find a default vat rate, we take the last one in list
6793 // Because they are sorted in ascending order, the last one will be the higher one (we suppose the higher one is the current rate)
6794 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6795 if (!getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS')) {
6796 // We take the last one found in list
6797 $defaulttx = $arrayofvatrates[$num - 1]['txtva'];
6798 } else {
6799 // We will use the rate defined into MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS
6800 $defaulttx = '';
6801 if (getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS') != 'none') {
6802 $defaulttx = getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS');
6803 }
6804 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6805 $defaultcode = $reg[1];
6806 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6807 }
6808 }
6809 }
6810
6811 // Disabled if seller is not subject to VAT
6812 $disabled = false;
6813 $title = '';
6814 if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0") {
6815 // Override/enable VAT for expense report regardless of global setting - needed if expense report used for business expenses instead
6816 // of using supplier invoices (this is a very bad idea !)
6817 if (!getDolGlobalString('EXPENSEREPORT_OVERRIDE_VAT')) {
6818 $title = ' title="' . dol_escape_htmltag($langs->trans('VATIsNotUsed')) . '"';
6819 $disabled = true;
6820 }
6821 }
6822
6823 if (!$options_only) {
6824 $return .= '<select class="flat minwidth75imp maxwidth100 right" id="' . $htmlname . '" name="' . $htmlname . '"' . ($disabled ? ' disabled' : '') . $title . '>';
6825 }
6826
6827 $selectedfound = false;
6828 foreach ($arrayofvatrates as $rate) {
6829 // Keep only 0 if seller is not subject to VAT
6830 if ($disabled && $rate['txtva'] != 0) {
6831 continue;
6832 }
6833
6834 // Define key to use into select list
6835 $key = $rate['txtva'];
6836 $key .= $rate['nprtva'] ? '*' : '';
6837 if ($mode > 0 && $rate['code']) {
6838 $key .= ' (' . $rate['code'] . ')';
6839 }
6840 if ($mode < 0) {
6841 $key = $rate['rowid'];
6842 }
6843
6844 $return .= '<option value="' . $key . '"';
6845 if (!$selectedfound) {
6846 if ($defaultcode) { // If defaultcode is defined, we used it in priority to select combo option instead of using rate+npr flag
6847 if ($defaultcode == $rate['code']) {
6848 $return .= ' selected';
6849 $selectedfound = true;
6850 }
6851 } elseif ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr) {
6852 $return .= ' selected';
6853 $selectedfound = true;
6854 }
6855 }
6856 $return .= '>';
6857
6858 // Show label of VAT
6859 if ($mysoc->country_code == 'IN' || getDolGlobalString('MAIN_VAT_LABEL_IS_POSITIVE_RATES')) {
6860 // Label with all localtax and code. For example: x.y / a.b / c.d (CODE)'
6861 $return .= $rate['labelpositiverates'];
6862 } else {
6863 // Simple label
6864 $return .= vatrate($rate['label']);
6865 }
6866
6867 //$return.=($rate['code']?' '.$rate['code']:'');
6868 $return .= (empty($rate['code']) && $rate['nprtva']) ? ' *' : ''; // We show the * (old behaviour only if new vat code is not used)
6869
6870 $return .= '</option>';
6871 }
6872
6873 if (!$options_only) {
6874 $return .= '</select>';
6875 //$return .= ajax_combobox($htmlname); // This break for the moment the dynamic autoselection of a value when selecting a product in object lines
6876 }
6877 } else {
6878 $return .= $this->error;
6879 }
6880
6881 $this->num = $num;
6882 return $return;
6883 }
6884
6885
6886 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6887
6912 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 = '')
6913 {
6914 // phpcs:enable
6915 dol_syslog(__METHOD__ . ': using select_date is deprecated. Use selectDate instead.', LOG_WARNING);
6916 $retstring = $this->selectDate($set_time, $prefix, $h, $m, $empty, $form_name, $d, $addnowlink, $disabled, $fullday, $addplusone, $adddateof);
6917 if (!empty($nooutput)) {
6918 return $retstring;
6919 }
6920 print $retstring;
6921
6922 return '';
6923 }
6924
6940 public function selectDateToDate($set_time = '', $set_time_end = '', $prefix = 're', $empty = 0, $forcenewline = 0)
6941 {
6942 global $langs;
6943
6944 $ret = $this->selectDate($set_time, $prefix . '_start', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("from"), 'tzuserrel');
6945 if ($forcenewline) {
6946 $ret .= '<br>';
6947 }
6948 $ret .= $this->selectDate($set_time_end, $prefix . '_end', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"), 'tzuserrel');
6949 return $ret;
6950 }
6951
6979 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')
6980 {
6981 global $conf, $langs;
6982
6983 if ($gm === 'auto') {
6984 $gm = (empty($conf) ? 'tzserver' : $conf->tzuserinputkey);
6985 }
6986
6987 $retstring = '';
6988
6989 if ($prefix == '') {
6990 $prefix = 're';
6991 }
6992 if ($h == '') {
6993 $h = 0;
6994 }
6995 if ($m == '') {
6996 $m = 0;
6997 }
6998 $emptydate = 0;
6999 $emptyhours = 0;
7000 if ($stepminutes <= 0 || $stepminutes > 30) {
7001 $stepminutes = 1;
7002 }
7003 if ($empty == 1) {
7004 $emptydate = 1;
7005 $emptyhours = 1;
7006 }
7007 if ($empty == 2) {
7008 $emptydate = 0;
7009 $emptyhours = 1;
7010 }
7011 $orig_set_time = $set_time;
7012
7013 if ($set_time === '' && $emptydate == 0) {
7014 include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7015 if ($gm == 'tzuser' || $gm == 'tzuserrel') {
7016 $set_time = dol_now($gm);
7017 } else {
7018 $set_time = dol_now('tzuser') - (getServerTimeZoneInt('now') * 3600); // set_time must be relative to PHP server timezone
7019 }
7020 }
7021
7022 // Analysis of the pre-selection date
7023 $reg = array();
7024 $shour = '';
7025 $smin = '';
7026 $ssec = '';
7027 if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', $set_time, $reg)) { // deprecated usage
7028 // Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'
7029 $syear = (!empty($reg[1]) ? $reg[1] : '');
7030 $smonth = (!empty($reg[2]) ? $reg[2] : '');
7031 $sday = (!empty($reg[3]) ? $reg[3] : '');
7032 $shour = (!empty($reg[4]) ? $reg[4] : '');
7033 $smin = (!empty($reg[5]) ? $reg[5] : '');
7034 } elseif (strval($set_time) != '' && $set_time != -1) {
7035 // set_time est un timestamps (0 possible)
7036 $syear = dol_print_date($set_time, "%Y", $gm);
7037 $smonth = dol_print_date($set_time, "%m", $gm);
7038 $sday = dol_print_date($set_time, "%d", $gm);
7039 if ($orig_set_time != '') {
7040 $shour = dol_print_date($set_time, "%H", $gm);
7041 $smin = dol_print_date($set_time, "%M", $gm);
7042 $ssec = dol_print_date($set_time, "%S", $gm);
7043 }
7044 } else {
7045 // Date est '' ou vaut -1
7046 $syear = '';
7047 $smonth = '';
7048 $sday = '';
7049 $shour = getDolGlobalString('MAIN_DEFAULT_DATE_HOUR', ($h == -1 ? '23' : ''));
7050 $smin = getDolGlobalString('MAIN_DEFAULT_DATE_MIN', ($h == -1 ? '59' : ''));
7051 $ssec = getDolGlobalString('MAIN_DEFAULT_DATE_SEC', ($h == -1 ? '59' : ''));
7052 }
7053 if ($h == 3 || $h == 4) {
7054 $shour = '';
7055 }
7056 if ($m == 3) {
7057 $smin = '';
7058 }
7059
7060 $nowgmt = dol_now('gmt');
7061 //var_dump(dol_print_date($nowgmt, 'dayhourinputnoreduce', 'tzuserrel'));
7062
7063 // You can set MAIN_POPUP_CALENDAR to 'eldy' or 'jquery'
7064 $usecalendar = 'combo';
7065 if (!empty($conf->use_javascript_ajax) && (!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') != "none")) {
7066 $usecalendar = ((!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') == 'eldy') ? 'jquery' : $conf->global->MAIN_POPUP_CALENDAR);
7067 }
7068 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7069 // If we use a text browser or screen reader, we use the 'combo' date selector
7070 $usecalendar = 'html';
7071 }
7072
7073 if ($d) {
7074 // Show date with popup
7075 if ($usecalendar != 'combo') {
7076 $formated_date = '';
7077 //print "e".$set_time." t ".$conf->format_date_short;
7078 if (strval($set_time) != '' && $set_time != -1) {
7079 //$formated_date=dol_print_date($set_time,$conf->format_date_short);
7080 $formated_date = dol_print_date($set_time, $langs->trans("FormatDateShortInput"), $gm); // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7081 }
7082
7083 // Calendrier popup version eldy
7084 if ($usecalendar == "eldy") {
7085 // Input area to enter date manually
7086 $retstring .= '<input id="' . $prefix . '" name="' . $prefix . '" type="text" class="maxwidthdate center" maxlength="11" value="' . $formated_date . '"';
7087 $retstring .= ($disabled ? ' disabled' : '');
7088 $retstring .= ' onChange="dpChangeDay(\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7089 $retstring .= ' autocomplete="off">';
7090
7091 // Icon calendar
7092 $retstringbuttom = '';
7093 if (!$disabled) {
7094 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons"';
7095 $base = DOL_URL_ROOT . '/core/';
7096 $retstringbuttom .= ' onClick="showDP(\'' . $base . '\',\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\',\'' . $langs->defaultlang . '\');"';
7097 $retstringbuttom .= '>' . img_object($langs->trans("SelectDate"), 'calendarday', 'class="datecallink"') . '</button>';
7098 } else {
7099 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
7100 }
7101 $retstring = $retstringbuttom . $retstring;
7102
7103 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
7104 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
7105 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
7106 } elseif ($usecalendar == 'jquery' || $usecalendar == 'html') {
7107 if (!$disabled && $usecalendar != 'html') {
7108 // Output javascript for datepicker
7109 $minYear = getDolGlobalInt('MIN_YEAR_SELECT_DATE', (idate('Y') - 100));
7110 $maxYear = getDolGlobalInt('MAX_YEAR_SELECT_DATE', (idate('Y') + 100));
7111
7112 $retstring .= '<script nonce="' . getNonce() . '" type="text/javascript">';
7113 $retstring .= "$(function(){ $('#" . $prefix . "').datepicker({
7114 dateFormat: '" . $langs->trans("FormatDateShortJQueryInput") . "',
7115 autoclose: true,
7116 todayHighlight: true,
7117 yearRange: '" . $minYear . ":" . $maxYear . "',";
7118 if (!empty($conf->dol_use_jmobile)) {
7119 $retstring .= "
7120 beforeShow: function (input, datePicker) {
7121 input.disabled = true;
7122 },
7123 onClose: function (dateText, datePicker) {
7124 this.disabled = false;
7125 },
7126 ";
7127 }
7128 // Note: We don't need monthNames, monthNamesShort, dayNames, dayNamesShort, dayNamesMin, they are set globally on datepicker component in lib_head.js.php
7129 if (!getDolGlobalString('MAIN_POPUP_CALENDAR_ON_FOCUS')) {
7130 $retstring .= "
7131 showOn: 'button', /* both has problem with autocompletion */
7132 buttonImage: '" . DOL_URL_ROOT . "/theme/" . dol_escape_js($conf->theme) . "/img/object_calendarday.png',
7133 buttonImageOnly: true";
7134 }
7135 $retstring .= "
7136 }) });";
7137 $retstring .= "</script>";
7138 }
7139
7140 // Input area to enter date manually
7141 $retstring .= '<div class="nowraponall inline-block divfordateinput">';
7142 $retstring .= '<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidthdate center" maxlength="11" value="'.$formated_date.'"';
7143 $retstring .= ($disabled ? ' disabled' : '');
7144 $retstring .= ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '');
7145 $retstring .= ' onChange="dpChangeDay(\'' . dol_escape_js($prefix) . '\',\'' . dol_escape_js($langs->trans("FormatDateShortJavaInput")) . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7146 $retstring .= ' autocomplete="off">';
7147
7148 // Icone calendrier
7149 if ($disabled) {
7150 $retstringbutton = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
7151 $retstring = $retstringbutton . $retstring;
7152 }
7153
7154 $retstring .= '</div>';
7155 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
7156 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
7157 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
7158 } else {
7159 $retstring .= "Bad value of MAIN_POPUP_CALENDAR";
7160 }
7161 } else {
7162 // Show date with combo selects
7163 // Day
7164 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50imp" id="' . $prefix . 'day" name="' . $prefix . 'day">';
7165
7166 if ($emptydate || $set_time == -1) {
7167 $retstring .= '<option value="0" selected>&nbsp;</option>';
7168 }
7169
7170 for ($day = 1; $day <= 31; $day++) {
7171 $retstring .= '<option value="' . $day . '"' . ($day == $sday ? ' selected' : '') . '>' . $day . '</option>';
7172 }
7173
7174 $retstring .= "</select>";
7175
7176 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'month" name="' . $prefix . 'month">';
7177 if ($emptydate || $set_time == -1) {
7178 $retstring .= '<option value="0" selected>&nbsp;</option>';
7179 }
7180
7181 // Month
7182 for ($month = 1; $month <= 12; $month++) {
7183 $retstring .= '<option value="' . $month . '"' . ($month == $smonth ? ' selected' : '') . '>';
7184 $retstring .= dol_print_date(mktime(12, 0, 0, $month, 1, 2000), "%b");
7185 $retstring .= "</option>";
7186 }
7187 $retstring .= "</select>";
7188
7189 // Year
7190 if ($emptydate || $set_time == -1) {
7191 $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 . '">';
7192 } else {
7193 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'year" name="' . $prefix . 'year">';
7194
7195 $syear = (int) $syear;
7196 for ($year = $syear - 10; $year < (int) $syear + 10; $year++) {
7197 $retstring .= '<option value="' . $year . '"' . ($year == $syear ? ' selected' : '') . '>' . $year . '</option>';
7198 }
7199 $retstring .= "</select>\n";
7200 }
7201 }
7202 }
7203
7204 if ($d && $h) {
7205 $retstring .= (($h == 2 || $h == 4) ? '<br>' : ' ');
7206 $retstring .= '<span class="nowraponall">';
7207 }
7208
7209 if ($h) {
7210 $hourstart = 0;
7211 $hourend = 24;
7212 if ($openinghours != '') {
7213 $openinghours = explode(',', $openinghours);
7214 $hourstart = $openinghours[0];
7215 $hourend = $openinghours[1];
7216 if ($hourend < $hourstart) {
7217 $hourend = $hourstart;
7218 }
7219 }
7220 // Show hour
7221 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'hour' : '') . '" id="' . $prefix . 'hour" name="' . $prefix . 'hour">';
7222 if ($emptyhours) {
7223 $retstring .= '<option value="-1">&nbsp;</option>';
7224 }
7225 for ($hour = $hourstart; $hour < $hourend; $hour++) {
7226 if (strlen($hour) < 2) {
7227 $hour = "0" . $hour;
7228 }
7229 $retstring .= '<option value="' . $hour . '"' . (($hour == $shour) ? ' selected' : '') . '>' . $hour;
7230 //$retstring .= (empty($conf->dol_optimize_smallscreen) ? '' : 'H');
7231 $retstring .= '</option>';
7232 }
7233 $retstring .= '</select>';
7234 //if ($m && empty($conf->dol_optimize_smallscreen)) $retstring .= ":";
7235 if ($m) {
7236 $retstring .= ":";
7237 }
7238 }
7239
7240 if ($m) {
7241 // Show minutes
7242 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'min' : '') . '" id="' . $prefix . 'min" name="' . $prefix . 'min">';
7243 if ($emptyhours) {
7244 $retstring .= '<option value="-1">&nbsp;</option>';
7245 }
7246 for ($min = 0; $min < 60; $min += $stepminutes) {
7247 $min_str = sprintf("%02d", $min);
7248 $retstring .= '<option value="' . $min_str . '"' . (($min_str == $smin) ? ' selected' : '') . '>' . $min_str . '</option>';
7249 }
7250 $retstring .= '</select>';
7251
7252 $retstring .= '<input type="hidden" name="' . $prefix . 'sec" value="' . $ssec . '">';
7253 }
7254
7255 if ($d && $h) {
7256 $retstring .= '</span>';
7257 }
7258
7259 // Add a "Now" link
7260 if (!empty($conf->use_javascript_ajax) && $addnowlink) {
7261 // Script which will be inserted in the onClick of the "Now" link
7262 $reset_scripts = "";
7263 if ($addnowlink == 2) { // local computer time
7264 // pad add leading 0 on numbers
7265 $reset_scripts .= "Number.prototype.pad = function(size) {
7266 var s = String(this);
7267 while (s.length < (size || 2)) {s = '0' + s;}
7268 return s;
7269 };
7270 var d = new Date();";
7271 }
7272
7273 // Generate the date part, depending on the use or not of the javascript calendar
7274 if ($addnowlink == 1) { // server time expressed in user time setup
7275 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7276 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7277 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7278 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7279 } elseif ($addnowlink == 2) {
7280 /* Disabled because the output does not use the string format defined by FormatDateShort key to forge the value into #prefix.
7281 * This break application for foreign languages.
7282 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(d.toLocaleDateString(\''.str_replace('_', '-', $langs->defaultlang).'\'));';
7283 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(d.getDate().pad());';
7284 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(parseInt(d.getMonth().pad()) + 1);';
7285 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(d.getFullYear());';
7286 */
7287 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7288 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7289 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7290 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7291 }
7292 /*if ($usecalendar == "eldy")
7293 {
7294 $base=DOL_URL_ROOT.'/core/';
7295 $reset_scripts .= 'resetDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');';
7296 }
7297 else
7298 {
7299 $reset_scripts .= 'this.form.elements[\''.$prefix.'day\'].value=formatDate(new Date(), \'d\'); ';
7300 $reset_scripts .= 'this.form.elements[\''.$prefix.'month\'].value=formatDate(new Date(), \'M\'); ';
7301 $reset_scripts .= 'this.form.elements[\''.$prefix.'year\'].value=formatDate(new Date(), \'yyyy\'); ';
7302 }*/
7303 // Update the hour part
7304 if ($h) {
7305 if ($fullday) {
7306 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7307 }
7308 //$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); ';
7309 if ($addnowlink == 1) {
7310 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7311 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7312 } elseif ($addnowlink == 2) {
7313 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(d.getHours().pad());';
7314 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7315 }
7316
7317 if ($fullday) {
7318 $reset_scripts .= ' } ';
7319 }
7320 }
7321 // Update the minute part
7322 if ($m) {
7323 if ($fullday) {
7324 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7325 }
7326 //$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); ';
7327 if ($addnowlink == 1) {
7328 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7329 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7330 } elseif ($addnowlink == 2) {
7331 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(d.getMinutes().pad());';
7332 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7333 }
7334 if ($fullday) {
7335 $reset_scripts .= ' } ';
7336 }
7337 }
7338 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7339 if ($reset_scripts && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7340 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonNow" type="button" name="_useless" value="now" onClick="' . $reset_scripts . '">';
7341 $retstring .= $langs->trans("Now");
7342 $retstring .= '</button> ';
7343 }
7344 }
7345
7346 // Add a "Plus one hour" link
7347 if ($conf->use_javascript_ajax && $addplusone) {
7348 // Script which will be inserted in the onClick of the "Add plusone" link
7349 $reset_scripts = "";
7350
7351 // Generate the date part, depending on the use or not of the javascript calendar
7352 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'dayinputnoreduce', 'tzuserrel') . '\');';
7353 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7354 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7355 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7356 // Update the hour part
7357 if ($h) {
7358 if ($fullday) {
7359 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7360 }
7361 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7362 if ($fullday) {
7363 $reset_scripts .= ' } ';
7364 }
7365 }
7366 // Update the minute part
7367 if ($m) {
7368 if ($fullday) {
7369 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7370 }
7371 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7372 if ($fullday) {
7373 $reset_scripts .= ' } ';
7374 }
7375 }
7376 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7377 if ($reset_scripts && empty($conf->dol_optimize_smallscreen)) {
7378 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonPlusOne" type="button" name="_useless2" value="plusone" onClick="' . $reset_scripts . '">';
7379 $retstring .= $langs->trans("DateStartPlusOne");
7380 $retstring .= '</button> ';
7381 }
7382 }
7383
7384 // Add a link to set data
7385 if ($conf->use_javascript_ajax && !empty($adddateof)) {
7386 if (!is_array($adddateof)) {
7387 $arrayofdateof = array(array('adddateof' => $adddateof, 'labeladddateof' => $labeladddateof));
7388 } else {
7389 $arrayofdateof = $adddateof;
7390 }
7391 foreach ($arrayofdateof as $valuedateof) {
7392 $tmpadddateof = empty($valuedateof['adddateof']) ? 0 : $valuedateof['adddateof'];
7393 $tmplabeladddateof = empty($valuedateof['labeladddateof']) ? '' : $valuedateof['labeladddateof'];
7394 $tmparray = dol_getdate($tmpadddateof);
7395 if (empty($tmplabeladddateof)) {
7396 $tmplabeladddateof = $langs->trans("DateInvoice");
7397 }
7398 $reset_scripts = 'console.log(\'Click on now link\'); ';
7399 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date($tmpadddateof, 'dayinputnoreduce').'\');';
7400 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.$tmparray['mday'].'\');';
7401 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.$tmparray['mon'].'\');';
7402 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.$tmparray['year'].'\');';
7403 $retstring .= ' - <button class="dpInvisibleButtons datenowlink" id="dateofinvoice" type="button" name="_dateofinvoice" value="now" onclick="'.$reset_scripts.'">'.$tmplabeladddateof.'</button>';
7404 }
7405 }
7406
7407 return $retstring;
7408 }
7409
7418 public function selectTypeDuration($prefix, $selected = 'i', $excludetypes = array())
7419 {
7420 global $langs;
7421
7422 $TDurationTypes = array(
7423 'y' => $langs->trans('Years'),
7424 'm' => $langs->trans('Month'),
7425 'w' => $langs->trans('Weeks'),
7426 'd' => $langs->trans('Days'),
7427 'h' => $langs->trans('Hours'),
7428 'i' => $langs->trans('Minutes')
7429 );
7430
7431 // Removed undesired duration types
7432 foreach ($excludetypes as $value) {
7433 unset($TDurationTypes[$value]);
7434 }
7435
7436 $retstring = '<select class="flat minwidth75 maxwidth100" id="select_' . $prefix . 'type_duration" name="' . $prefix . 'type_duration">';
7437 foreach ($TDurationTypes as $key => $typeduration) {
7438 $retstring .= '<option value="' . $key . '"';
7439 if ($key == $selected) {
7440 $retstring .= " selected";
7441 }
7442 $retstring .= ">" . $typeduration . "</option>";
7443 }
7444 $retstring .= "</select>";
7445
7446 $retstring .= ajax_combobox('select_' . $prefix . 'type_duration');
7447
7448 return $retstring;
7449 }
7450
7451 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
7452
7466 public function select_duration($prefix, $iSecond = '', $disabled = 0, $typehour = 'select', $minunderhours = 0, $nooutput = 0)
7467 {
7468 // phpcs:enable
7469 global $langs;
7470
7471 $retstring = '<span class="nowraponall">';
7472
7473 $hourSelected = '';
7474 $minSelected = '';
7475
7476 // Hours
7477 if ($iSecond != '') {
7478 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7479
7480 $hourSelected = convertSecondToTime($iSecond, 'allhour');
7481 $minSelected = convertSecondToTime($iSecond, 'min');
7482 }
7483
7484 if ($typehour == 'select') {
7485 $retstring .= '<select class="flat" id="select_' . $prefix . 'hour" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . '>';
7486 for ($hour = 0; $hour < 25; $hour++) { // For a duration, we allow 24 hours
7487 $retstring .= '<option value="' . $hour . '"';
7488 if (is_numeric($hourSelected) && $hourSelected == $hour) {
7489 $retstring .= " selected";
7490 }
7491 $retstring .= ">" . $hour . "</option>";
7492 }
7493 $retstring .= "</select>";
7494 } elseif ($typehour == 'text' || $typehour == 'textselect') {
7495 $retstring .= '<input placeholder="' . $langs->trans('HourShort') . '" type="number" min="0" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputhour right" value="' . (($hourSelected != '') ? ((int) $hourSelected) : '') . '">';
7496 } else {
7497 return 'BadValueForParameterTypeHour';
7498 }
7499
7500 if ($typehour != 'text') {
7501 $retstring .= ' ' . $langs->trans('HourShort');
7502 } else {
7503 $retstring .= '<span class="">:</span>';
7504 }
7505
7506 // Minutes
7507 if ($minunderhours) {
7508 $retstring .= '<br>';
7509 } else {
7510 if ($typehour != 'text') {
7511 $retstring .= '<span class="hideonsmartphone">&nbsp;</span>';
7512 }
7513 }
7514
7515 if ($typehour == 'select' || $typehour == 'textselect') {
7516 $retstring .= '<select class="flat" id="select_' . $prefix . 'min" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . '>';
7517 for ($min = 0; $min <= 55; $min += 5) {
7518 $retstring .= '<option value="' . $min . '"';
7519 if (is_numeric($minSelected) && $minSelected == $min) {
7520 $retstring .= ' selected';
7521 }
7522 $retstring .= '>' . $min . '</option>';
7523 }
7524 $retstring .= "</select>";
7525 } elseif ($typehour == 'text') {
7526 $retstring .= '<input placeholder="' . $langs->trans('MinuteShort') . '" type="number" min="0" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputminute right" value="' . (($minSelected != '') ? ((int) $minSelected) : '') . '">';
7527 }
7528
7529 if ($typehour != 'text') {
7530 $retstring .= ' ' . $langs->trans('MinuteShort');
7531 }
7532
7533 $retstring .= "</span>";
7534
7535 if (!empty($nooutput)) {
7536 return $retstring;
7537 }
7538
7539 print $retstring;
7540
7541 return '';
7542 }
7543
7563 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)
7564 {
7565 global $langs, $conf;
7566
7567 $out = '';
7568
7569 // check parameters
7570 if (is_null($ajaxoptions)) {
7571 $ajaxoptions = array();
7572 }
7573
7574 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7575 $placeholder = '';
7576
7577 if ($selected && empty($selected_input_value)) {
7578 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7579 $tickettmpselect = new Ticket($this->db);
7580 $tickettmpselect->fetch($selected);
7581 $selected_input_value = $tickettmpselect->ref;
7582 unset($tickettmpselect);
7583 }
7584
7585 $urloption = '';
7586 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/ticket/ajax/tickets.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7587
7588 if (empty($hidelabel)) {
7589 $out .= $langs->trans("RefOrLabel") . ' : ';
7590 } elseif ($hidelabel > 1) {
7591 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7592 if ($hidelabel == 2) {
7593 $out .= img_picto($langs->trans("Search"), 'search');
7594 }
7595 }
7596 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7597 if ($hidelabel == 3) {
7598 $out .= img_picto($langs->trans("Search"), 'search');
7599 }
7600 } else {
7601 $out .= $this->selectTicketsList($selected, $htmlname, $filtertype, $limit, '', $status, 0, $showempty, $forcecombo, $morecss);
7602 }
7603
7604 if (empty($nooutput)) {
7605 print $out;
7606 } else {
7607 return $out;
7608 }
7609 return '';
7610 }
7611
7612
7629 public function selectTicketsList($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7630 {
7631 global $langs, $conf;
7632
7633 $out = '';
7634 $outarray = array();
7635
7636 $selectFields = " p.rowid, p.ref, p.message";
7637
7638 $sql = "SELECT ";
7639 $sql .= $selectFields;
7640 $sql .= " FROM " . $this->db->prefix() . "ticket as p";
7641 $sql .= ' WHERE p.entity IN (' . getEntity('ticket') . ')';
7642
7643 // Add criteria on ref/label
7644 if ($filterkey != '') {
7645 $sql .= ' AND (';
7646 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7647 // For natural search
7648 $search_crit = explode(' ', $filterkey);
7649 $i = 0;
7650 if (count($search_crit) > 1) {
7651 $sql .= "(";
7652 }
7653 foreach ($search_crit as $crit) {
7654 if ($i > 0) {
7655 $sql .= " AND ";
7656 }
7657 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.subject LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7658 $sql .= ")";
7659 $i++;
7660 }
7661 if (count($search_crit) > 1) {
7662 $sql .= ")";
7663 }
7664 $sql .= ')';
7665 }
7666
7667 $sql .= $this->db->plimit($limit, 0);
7668
7669 // Build output string
7670 dol_syslog(get_class($this) . "::selectTicketsList search tickets", LOG_DEBUG);
7671 $result = $this->db->query($sql);
7672 if ($result) {
7673 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7674 require_once DOL_DOCUMENT_ROOT . '/core/lib/ticket.lib.php';
7675
7676 $num = $this->db->num_rows($result);
7677
7678 $events = array();
7679
7680 if (!$forcecombo) {
7681 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7682 $out .= ajax_combobox($htmlname, $events, $conf->global->TICKET_USE_SEARCH_TO_SELECT);
7683 }
7684
7685 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7686
7687 $textifempty = '';
7688 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7689 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7690 if (getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7691 if ($showempty && !is_numeric($showempty)) {
7692 $textifempty = $langs->trans($showempty);
7693 } else {
7694 $textifempty .= $langs->trans("All");
7695 }
7696 } else {
7697 if ($showempty && !is_numeric($showempty)) {
7698 $textifempty = $langs->trans($showempty);
7699 }
7700 }
7701 if ($showempty) {
7702 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7703 }
7704
7705 $i = 0;
7706 while ($num && $i < $num) {
7707 $opt = '';
7708 $optJson = array();
7709 $objp = $this->db->fetch_object($result);
7710
7711 $this->constructTicketListOption($objp, $opt, $optJson, $selected, $filterkey);
7712 // Add new entry
7713 // "key" value of json key array is used by jQuery automatically as selected value
7714 // "label" value of json key array is used by jQuery automatically as text for combo box
7715 $out .= $opt;
7716 array_push($outarray, $optJson);
7717
7718 $i++;
7719 }
7720
7721 $out .= '</select>';
7722
7723 $this->db->free($result);
7724
7725 if (empty($outputmode)) {
7726 return $out;
7727 }
7728 return $outarray;
7729 } else {
7730 dol_print_error($this->db);
7731 }
7732
7733 return array();
7734 }
7735
7747 protected function constructTicketListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7748 {
7749 $outkey = '';
7750 $outref = '';
7751 $outtype = '';
7752
7753 $outkey = $objp->rowid;
7754 $outref = $objp->ref;
7755 $outtype = $objp->fk_product_type;
7756
7757 $opt = '<option value="' . $objp->rowid . '"';
7758 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7759 $opt .= '>';
7760 $opt .= $objp->ref;
7761 $objRef = $objp->ref;
7762 if (!empty($filterkey) && $filterkey != '') {
7763 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
7764 }
7765
7766 $opt .= "</option>\n";
7767 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
7768 }
7769
7789 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)
7790 {
7791 global $langs, $conf;
7792
7793 $out = '';
7794
7795 // check parameters
7796 if (is_null($ajaxoptions)) {
7797 $ajaxoptions = array();
7798 }
7799
7800 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7801 $placeholder = '';
7802
7803 if ($selected && empty($selected_input_value)) {
7804 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7805 $projecttmpselect = new Project($this->db);
7806 $projecttmpselect->fetch($selected);
7807 $selected_input_value = $projecttmpselect->ref;
7808 unset($projecttmpselect);
7809 }
7810
7811 $urloption = '';
7812 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/projet/ajax/projects.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7813
7814 if (empty($hidelabel)) {
7815 $out .= $langs->trans("RefOrLabel") . ' : ';
7816 } elseif ($hidelabel > 1) {
7817 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7818 if ($hidelabel == 2) {
7819 $out .= img_picto($langs->trans("Search"), 'search');
7820 }
7821 }
7822 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7823 if ($hidelabel == 3) {
7824 $out .= img_picto($langs->trans("Search"), 'search');
7825 }
7826 } else {
7827 $out .= $this->selectProjectsList($selected, $htmlname, $filtertype, $limit, '', $status, 0, $showempty, $forcecombo, $morecss);
7828 }
7829
7830 if (empty($nooutput)) {
7831 print $out;
7832 } else {
7833 return $out;
7834 }
7835 return '';
7836 }
7837
7854 public function selectProjectsList($selected = '', $htmlname = 'projectid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7855 {
7856 global $langs, $conf;
7857
7858 $out = '';
7859 $outarray = array();
7860
7861 $selectFields = " p.rowid, p.ref";
7862
7863 $sql = "SELECT ";
7864 $sql .= $selectFields;
7865 $sql .= " FROM " . $this->db->prefix() . "projet as p";
7866 $sql .= ' WHERE p.entity IN (' . getEntity('project') . ')';
7867
7868 // Add criteria on ref/label
7869 if ($filterkey != '') {
7870 $sql .= ' AND (';
7871 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7872 // For natural search
7873 $search_crit = explode(' ', $filterkey);
7874 $i = 0;
7875 if (count($search_crit) > 1) {
7876 $sql .= "(";
7877 }
7878 foreach ($search_crit as $crit) {
7879 if ($i > 0) {
7880 $sql .= " AND ";
7881 }
7882 $sql .= "p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7883 $sql .= "";
7884 $i++;
7885 }
7886 if (count($search_crit) > 1) {
7887 $sql .= ")";
7888 }
7889 $sql .= ')';
7890 }
7891
7892 $sql .= $this->db->plimit($limit, 0);
7893
7894 // Build output string
7895 dol_syslog(get_class($this) . "::selectProjectsList search projects", LOG_DEBUG);
7896 $result = $this->db->query($sql);
7897 if ($result) {
7898 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7899 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
7900
7901 $num = $this->db->num_rows($result);
7902
7903 $events = array();
7904
7905 if (!$forcecombo) {
7906 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7907 $out .= ajax_combobox($htmlname, $events, $conf->global->PROJECT_USE_SEARCH_TO_SELECT);
7908 }
7909
7910 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7911
7912 $textifempty = '';
7913 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7914 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7915 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
7916 if ($showempty && !is_numeric($showempty)) {
7917 $textifempty = $langs->trans($showempty);
7918 } else {
7919 $textifempty .= $langs->trans("All");
7920 }
7921 } else {
7922 if ($showempty && !is_numeric($showempty)) {
7923 $textifempty = $langs->trans($showempty);
7924 }
7925 }
7926 if ($showempty) {
7927 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7928 }
7929
7930 $i = 0;
7931 while ($num && $i < $num) {
7932 $opt = '';
7933 $optJson = array();
7934 $objp = $this->db->fetch_object($result);
7935
7936 $this->constructProjectListOption($objp, $opt, $optJson, $selected, $filterkey);
7937 // Add new entry
7938 // "key" value of json key array is used by jQuery automatically as selected value
7939 // "label" value of json key array is used by jQuery automatically as text for combo box
7940 $out .= $opt;
7941 array_push($outarray, $optJson);
7942
7943 $i++;
7944 }
7945
7946 $out .= '</select>';
7947
7948 $this->db->free($result);
7949
7950 if (empty($outputmode)) {
7951 return $out;
7952 }
7953 return $outarray;
7954 } else {
7955 dol_print_error($this->db);
7956 }
7957
7958 return array();
7959 }
7960
7972 protected function constructProjectListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7973 {
7974 $outkey = '';
7975 $outref = '';
7976 $outtype = '';
7977
7978 $label = $objp->label;
7979
7980 $outkey = $objp->rowid;
7981 $outref = $objp->ref;
7982 $outlabel = $objp->label;
7983 $outtype = $objp->fk_product_type;
7984
7985 $opt = '<option value="' . $objp->rowid . '"';
7986 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7987 $opt .= '>';
7988 $opt .= $objp->ref;
7989 $objRef = $objp->ref;
7990 if (!empty($filterkey) && $filterkey != '') {
7991 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
7992 }
7993
7994 $opt .= "</option>\n";
7995 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
7996 }
7997
7998
8018 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)
8019 {
8020 global $langs, $conf;
8021
8022 $out = '';
8023
8024 // check parameters
8025 if (is_null($ajaxoptions)) {
8026 $ajaxoptions = array();
8027 }
8028
8029 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
8030 $placeholder = '';
8031
8032 if ($selected && empty($selected_input_value)) {
8033 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
8034 $adherenttmpselect = new Adherent($this->db);
8035 $adherenttmpselect->fetch($selected);
8036 $selected_input_value = $adherenttmpselect->ref;
8037 unset($adherenttmpselect);
8038 }
8039
8040 $urloption = '';
8041
8042 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/adherents/ajax/adherents.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
8043
8044 if (empty($hidelabel)) {
8045 $out .= $langs->trans("RefOrLabel") . ' : ';
8046 } elseif ($hidelabel > 1) {
8047 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
8048 if ($hidelabel == 2) {
8049 $out .= img_picto($langs->trans("Search"), 'search');
8050 }
8051 }
8052 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
8053 if ($hidelabel == 3) {
8054 $out .= img_picto($langs->trans("Search"), 'search');
8055 }
8056 } else {
8057 $filterkey = '';
8058
8059 $out .= $this->selectMembersList($selected, $htmlname, $filtertype, $limit, $filterkey, $status, 0, $showempty, $forcecombo, $morecss);
8060 }
8061
8062 if (empty($nooutput)) {
8063 print $out;
8064 } else {
8065 return $out;
8066 }
8067 return '';
8068 }
8069
8086 public function selectMembersList($selected = '', $htmlname = 'adherentid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
8087 {
8088 global $langs, $conf;
8089
8090 $out = '';
8091 $outarray = array();
8092
8093 $selectFields = " p.rowid, p.ref, p.firstname, p.lastname, p.fk_adherent_type";
8094
8095 $sql = "SELECT ";
8096 $sql .= $selectFields;
8097 $sql .= " FROM " . $this->db->prefix() . "adherent as p";
8098 $sql .= ' WHERE p.entity IN (' . getEntity('adherent') . ')';
8099
8100 // Add criteria on ref/label
8101 if ($filterkey != '') {
8102 $sql .= ' AND (';
8103 $prefix = !getDolGlobalString('MEMBER_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
8104 // For natural search
8105 $search_crit = explode(' ', $filterkey);
8106 $i = 0;
8107 if (count($search_crit) > 1) {
8108 $sql .= "(";
8109 }
8110 foreach ($search_crit as $crit) {
8111 if ($i > 0) {
8112 $sql .= " AND ";
8113 }
8114 $sql .= "(p.firstname LIKE '" . $this->db->escape($prefix . $crit) . "%'";
8115 $sql .= " OR p.lastname LIKE '" . $this->db->escape($prefix . $crit) . "%')";
8116 $i++;
8117 }
8118 if (count($search_crit) > 1) {
8119 $sql .= ")";
8120 }
8121 $sql .= ')';
8122 }
8123 if ($status != -1) {
8124 $sql .= ' AND statut = ' . ((int) $status);
8125 }
8126 $sql .= $this->db->plimit($limit, 0);
8127
8128 // Build output string
8129 dol_syslog(get_class($this) . "::selectMembersList search adherents", LOG_DEBUG);
8130 $result = $this->db->query($sql);
8131 if ($result) {
8132 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
8133 require_once DOL_DOCUMENT_ROOT . '/core/lib/member.lib.php';
8134
8135 $num = $this->db->num_rows($result);
8136
8137 $events = array();
8138
8139 if (!$forcecombo) {
8140 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8141 $out .= ajax_combobox($htmlname, $events, getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT') ? $conf->global->PROJECT_USE_SEARCH_TO_SELECT : '');
8142 }
8143
8144 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
8145
8146 $textifempty = '';
8147 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
8148 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8149 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
8150 if ($showempty && !is_numeric($showempty)) {
8151 $textifempty = $langs->trans($showempty);
8152 } else {
8153 $textifempty .= $langs->trans("All");
8154 }
8155 } else {
8156 if ($showempty && !is_numeric($showempty)) {
8157 $textifempty = $langs->trans($showempty);
8158 }
8159 }
8160 if ($showempty) {
8161 $out .= '<option value="-1" selected>' . $textifempty . '</option>';
8162 }
8163
8164 $i = 0;
8165 while ($num && $i < $num) {
8166 $opt = '';
8167 $optJson = array();
8168 $objp = $this->db->fetch_object($result);
8169
8170 $this->constructMemberListOption($objp, $opt, $optJson, $selected, $filterkey);
8171
8172 // Add new entry
8173 // "key" value of json key array is used by jQuery automatically as selected value
8174 // "label" value of json key array is used by jQuery automatically as text for combo box
8175 $out .= $opt;
8176 array_push($outarray, $optJson);
8177
8178 $i++;
8179 }
8180
8181 $out .= '</select>';
8182
8183 $this->db->free($result);
8184
8185 if (empty($outputmode)) {
8186 return $out;
8187 }
8188 return $outarray;
8189 } else {
8190 dol_print_error($this->db);
8191 }
8192
8193 return array();
8194 }
8195
8207 protected function constructMemberListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
8208 {
8209 $outkey = '';
8210 $outlabel = '';
8211 $outtype = '';
8212
8213 $outkey = $objp->rowid;
8214 $outlabel = dolGetFirstLastname($objp->firstname, $objp->lastname);
8215 $outtype = $objp->fk_adherent_type;
8216
8217 $opt = '<option value="' . $objp->rowid . '"';
8218 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
8219 $opt .= '>';
8220 if (!empty($filterkey) && $filterkey != '') {
8221 $outlabel = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $outlabel, 1);
8222 }
8223 $opt .= $outlabel;
8224 $opt .= "</option>\n";
8225
8226 $optJson = array('key' => $outkey, 'value' => $outlabel, 'type' => $outtype);
8227 }
8228
8249 public function selectForForms($objectdesc, $htmlname, $preSelectedValue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '', $objectfield = '')
8250 {
8251 global $conf, $extrafields, $user;
8252
8253 // Example of common usage for a link to a thirdparty
8254
8255 // We got this in a modulebuilder form of "MyObject" of module "mymodule".
8256 // ->fields is array( ... "fk_soc" => array("type"=>"integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))" ...)
8257 // $objectdesc = 'Societe'
8258 // $objectfield = 'myobject@mymodule:fk_soc' ('fk_soc' is code to retrieve myobject->fields['fk_soc'])
8259
8260 // We got this when showing an extrafields on resource that is a link to societe
8261 // extrafields 'link_to_societe' of Resource is 'link' to 'Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))" ...)'
8262 // $objectdesc = 'Societe'
8263 // $objectfield = 'resource:options_link_to_societe'
8264
8265 // With old usage:
8266 // $objectdesc = 'Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))'
8267 // $objectfield = ''
8268
8269 //var_dump($objectdesc.' '.$objectfield);
8270 //debug_print_backtrace();
8271
8272 $objectdescorig = $objectdesc;
8273 $objecttmp = null;
8274 $InfoFieldList = array();
8275 $classname = '';
8276 $filter = ''; // Ensure filter has value (for static analysis)
8277 $sortfield = ''; // Ensure filter has value (for static analysis)
8278
8279 if ($objectfield) { // We must retrieve the objectdesc from the field or extrafield
8280 // Example: $objectfield = 'product:options_package' or 'myobject@mymodule:options_myfield'
8281 $tmparray = explode(':', $objectfield);
8282
8283 // Get instance of object from $element
8284 $objectforfieldstmp = fetchObjectByElement(0, strtolower($tmparray[0]));
8285
8286 if (is_object($objectforfieldstmp)) {
8287 $objectdesc = '';
8288
8289 $reg = array();
8290 if (preg_match('/^options_(.*)$/', $tmparray[1], $reg)) {
8291 // For a property in extrafields
8292 $key = $reg[1];
8293 // fetch optionals attributes and labels
8294 $extrafields->fetch_name_optionals_label($objectforfieldstmp->table_element);
8295
8296 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key]) && $extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key] == 'link') {
8297 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options'])) {
8298 $tmpextrafields = array_keys($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options']);
8299 $objectdesc = $tmpextrafields[0];
8300 }
8301 }
8302 } else {
8303 // For a property in ->fields
8304 if (array_key_exists($tmparray[1], $objectforfieldstmp->fields)) {
8305 $objectdesc = $objectforfieldstmp->fields[$tmparray[1]]['type'];
8306 $objectdesc = preg_replace('/^integer[^:]*:/', '', $objectdesc);
8307 }
8308 }
8309 }
8310 }
8311
8312 if ($objectdesc) {
8313 // Example of value for $objectdesc:
8314 // Bom:bom/class/bom.class.php:0:t.status=1
8315 // Bom:bom/class/bom.class.php:0:t.status=1:ref
8316 // Bom:bom/class/bom.class.php:0:(t.status:=:1) OR (t.field2:=:2):ref
8317 $InfoFieldList = explode(":", $objectdesc, 4);
8318 $vartmp = (empty($InfoFieldList[3]) ? '' : $InfoFieldList[3]);
8319 $reg = array();
8320 if (preg_match('/^.*:(\w*)$/', $vartmp, $reg)) {
8321 $InfoFieldList[4] = $reg[1]; // take the sort field
8322 }
8323 $InfoFieldList[3] = preg_replace('/:\w*$/', '', $vartmp); // take the filter field
8324
8325 $classname = $InfoFieldList[0];
8326 $classpath = empty($InfoFieldList[1]) ? '' : $InfoFieldList[1];
8327 //$addcreatebuttonornot = empty($InfoFieldList[2]) ? 0 : $InfoFieldList[2];
8328 $filter = empty($InfoFieldList[3]) ? '' : $InfoFieldList[3];
8329 $sortfield = empty($InfoFieldList[4]) ? '' : $InfoFieldList[4];
8330
8331 // Load object according to $id and $element
8332 $objecttmp = fetchObjectByElement(0, strtolower($InfoFieldList[0]));
8333
8334 // Fallback to another solution to get $objecttmp
8335 if (empty($objecttmp) && !empty($classpath)) {
8336 dol_include_once($classpath);
8337
8338 if ($classname && class_exists($classname)) {
8339 $objecttmp = new $classname($this->db);
8340 }
8341 }
8342 }
8343
8344 // Make some replacement in $filter. May not be used if we used the ajax mode with $objectfield. In such a case
8345 // we propagate the $objectfield and not the filter and replacement is done by the ajax/selectobject.php component.
8346 $sharedentities = (is_object($objecttmp) && property_exists($objecttmp, 'element')) ? getEntity($objecttmp->element) : strtolower($classname);
8347 $filter = str_replace(
8348 array('__ENTITY__', '__SHARED_ENTITIES__', '__USER_ID__'),
8349 array($conf->entity, $sharedentities, $user->id),
8350 $filter
8351 );
8352
8353 if (!is_object($objecttmp)) {
8354 dol_syslog('selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc, LOG_WARNING);
8355 return 'selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc;
8356 }
8357 '@phan-var-force CommonObject $objecttmp';
8358
8359 //var_dump($filter);
8360 $prefixforautocompletemode = $objecttmp->element;
8361 if ($prefixforautocompletemode == 'societe') {
8362 $prefixforautocompletemode = 'company';
8363 }
8364 if ($prefixforautocompletemode == 'product') {
8365 $prefixforautocompletemode = 'produit';
8366 }
8367 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8368
8369 dol_syslog(get_class($this) . "::selectForForms filter=" . $filter, LOG_DEBUG);
8370
8371 // Generate the combo HTML component
8372 $out = '';
8373 if (!empty($conf->use_javascript_ajax) && getDolGlobalString($confkeyforautocompletemode) && !$forcecombo) {
8374 // No immediate load of all database
8375 $placeholder = '';
8376
8377 if ($preSelectedValue && empty($selected_input_value)) {
8378 $objecttmp->fetch($preSelectedValue);
8379 $selected_input_value = ($prefixforautocompletemode == 'company' ? $objecttmp->name : $objecttmp->ref);
8380
8381 $oldValueForShowOnCombobox = 0;
8382 foreach ($objecttmp->fields as $fieldK => $fielV) {
8383 if (!array_key_exists('showoncombobox', $fielV) || !$fielV['showoncombobox'] || empty($objecttmp->$fieldK)) {
8384 continue;
8385 }
8386
8387 if (!$oldValueForShowOnCombobox) {
8388 $selected_input_value = '';
8389 }
8390
8391 $selected_input_value .= $oldValueForShowOnCombobox ? ' - ' : '';
8392 $selected_input_value .= $objecttmp->$fieldK;
8393 $oldValueForShowOnCombobox = empty($fielV['showoncombobox']) ? 0 : $fielV['showoncombobox'];
8394 }
8395 }
8396
8397 // Set url and param to call to get json of the search results
8398 $urlforajaxcall = DOL_URL_ROOT . '/core/ajax/selectobject.php';
8399 $urloption = 'htmlname=' . urlencode($htmlname) . '&outjson=1&objectdesc=' . urlencode($objectdescorig) . '&objectfield='.urlencode($objectfield) . ($sortfield ? '&sortfield=' . urlencode($sortfield) : '');
8400
8401 // Activate the auto complete using ajax call.
8402 $out .= ajax_autocompleter($preSelectedValue, $htmlname, $urlforajaxcall, $urloption, getDolGlobalString($confkeyforautocompletemode), 0);
8403 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
8404 $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) . '"' : '') . ' />';
8405 } else {
8406 // Immediate load of table record.
8407 $out .= $this->selectForFormsList($objecttmp, $htmlname, $preSelectedValue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, 0, $disabled, $sortfield, $filter);
8408 }
8409
8410 return $out;
8411 }
8412
8413
8434 public function selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $outputmode = 0, $disabled = 0, $sortfield = '', $filter = '')
8435 {
8436 global $langs, $user, $hookmanager;
8437
8438 //print "$htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, $outputmode, $disabled";
8439
8440 $prefixforautocompletemode = $objecttmp->element;
8441 if ($prefixforautocompletemode == 'societe') {
8442 $prefixforautocompletemode = 'company';
8443 }
8444 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8445
8446 if (!empty($objecttmp->fields)) { // For object that declare it, it is better to use declared fields (like societe, contact, ...)
8447 $tmpfieldstoshow = '';
8448 foreach ($objecttmp->fields as $key => $val) {
8449 if (! (int) dol_eval($val['enabled'], 1, 1, '1')) {
8450 continue;
8451 }
8452 if (!empty($val['showoncombobox'])) {
8453 $tmpfieldstoshow .= ($tmpfieldstoshow ? ',' : '') . 't.' . $key;
8454 }
8455 }
8456 if ($tmpfieldstoshow) {
8457 $fieldstoshow = $tmpfieldstoshow;
8458 }
8459 } else {
8460 // For backward compatibility
8461 $objecttmp->fields['ref'] = array('type' => 'varchar(30)', 'label' => 'Ref', 'showoncombobox' => 1);
8462 }
8463
8464 if (empty($fieldstoshow)) {
8465 if (isset($objecttmp->fields['ref'])) {
8466 $fieldstoshow = 't.ref';
8467 } else {
8468 $langs->load("errors");
8469 $this->error = $langs->trans("ErrorNoFieldWithAttributeShowoncombobox");
8470 return $langs->trans('ErrorNoFieldWithAttributeShowoncombobox');
8471 }
8472 }
8473
8474 $out = '';
8475 $outarray = array();
8476 $tmparray = array();
8477
8478 $num = 0;
8479
8480 // Search data
8481 $sql = "SELECT t.rowid, " . $fieldstoshow . " FROM " . $this->db->prefix() . $objecttmp->table_element . " as t";
8482 if (!empty($objecttmp->isextrafieldmanaged)) {
8483 $sql .= " LEFT JOIN " . $this->db->prefix() . $objecttmp->table_element . "_extrafields as e ON t.rowid=e.fk_object";
8484 }
8485 if (isset($objecttmp->ismultientitymanaged)) {
8486 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8487 $tmparray = explode('@', $objecttmp->ismultientitymanaged);
8488 $sql .= " INNER JOIN " . $this->db->prefix() . $tmparray[1] . " as parenttable ON parenttable.rowid = t." . $tmparray[0];
8489 }
8490 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8491 if (!$user->hasRight('societe', 'client', 'voir')) {
8492 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
8493 }
8494 }
8495 }
8496
8497 // Add where from hooks
8498 $parameters = array(
8499 'object' => $objecttmp,
8500 'htmlname' => $htmlname,
8501 'filter' => $filter,
8502 'searchkey' => $searchkey
8503 );
8504
8505 $reshook = $hookmanager->executeHooks('selectForFormsListWhere', $parameters); // Note that $action and $object may have been modified by hook
8506 if (!empty($hookmanager->resPrint)) {
8507 $sql .= $hookmanager->resPrint;
8508 } else {
8509 $sql .= " WHERE 1=1";
8510 if (isset($objecttmp->ismultientitymanaged)) {
8511 if ($objecttmp->ismultientitymanaged == 1) {
8512 $sql .= " AND t.entity IN (" . getEntity($objecttmp->table_element) . ")";
8513 }
8514 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8515 $sql .= " AND parenttable.entity = t." . $tmparray[0];
8516 }
8517 if ($objecttmp->ismultientitymanaged == 1 && !empty($user->socid)) {
8518 if ($objecttmp->element == 'societe') {
8519 $sql .= " AND t.rowid = " . ((int) $user->socid);
8520 } else {
8521 $sql .= " AND t.fk_soc = " . ((int) $user->socid);
8522 }
8523 }
8524 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8525 if (!$user->hasRight('societe', 'client', 'voir')) {
8526 $sql .= " AND t.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
8527 }
8528 }
8529 }
8530 if ($searchkey != '') {
8531 $sql .= natural_search(explode(',', $fieldstoshow), $searchkey);
8532 }
8533
8534 if ($filter) { // Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
8535 $errormessage = '';
8536 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
8537 if ($errormessage) {
8538 return 'Error forging a SQL request from an universal criteria: ' . $errormessage;
8539 }
8540 }
8541 }
8542 $sql .= $this->db->order($sortfield ? $sortfield : $fieldstoshow, "ASC");
8543 //$sql.=$this->db->plimit($limit, 0);
8544 //print $sql;
8545
8546 // Build output string
8547 $resql = $this->db->query($sql);
8548 if ($resql) {
8549 // Construct $out and $outarray
8550 $out .= '<select id="' . $htmlname . '" class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ($moreparams ? ' ' . $moreparams : '') . ' name="' . $htmlname . '">' . "\n";
8551
8552 // 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
8553 $textifempty = '&nbsp;';
8554
8555 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8556 if (getDolGlobalInt($confkeyforautocompletemode)) {
8557 if ($showempty && !is_numeric($showempty)) {
8558 $textifempty = $langs->trans($showempty);
8559 } else {
8560 $textifempty .= $langs->trans("All");
8561 }
8562 }
8563 if ($showempty) {
8564 $out .= '<option value="-1">' . $textifempty . '</option>' . "\n";
8565 }
8566
8567 $num = $this->db->num_rows($resql);
8568 $i = 0;
8569 if ($num) {
8570 while ($i < $num) {
8571 $obj = $this->db->fetch_object($resql);
8572 $label = '';
8573 $labelhtml = '';
8574 $tmparray = explode(',', $fieldstoshow);
8575 $oldvalueforshowoncombobox = 0;
8576 foreach ($tmparray as $key => $val) {
8577 $val = preg_replace('/t\./', '', $val);
8578 $label .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8579 $labelhtml .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8580 $label .= $obj->$val;
8581 $labelhtml .= $obj->$val;
8582
8583 $oldvalueforshowoncombobox = empty($objecttmp->fields[$val]['showoncombobox']) ? 0 : $objecttmp->fields[$val]['showoncombobox'];
8584 }
8585 if (empty($outputmode)) {
8586 if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid) {
8587 $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>';
8588 } else {
8589 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
8590 }
8591 } else {
8592 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label));
8593 }
8594
8595 $i++;
8596 if (($i % 10) == 0) {
8597 $out .= "\n";
8598 }
8599 }
8600 }
8601
8602 $out .= '</select>' . "\n";
8603
8604 if (!$forcecombo) {
8605 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8606 $out .= ajax_combobox($htmlname, array(), getDolGlobalInt($confkeyforautocompletemode, 0));
8607 }
8608 } else {
8609 dol_print_error($this->db);
8610 }
8611
8612 $this->result = array('nbofelement' => $num);
8613
8614 if ($outputmode) {
8615 return $outarray;
8616 }
8617 return $out;
8618 }
8619
8620
8644 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)
8645 {
8646 global $conf, $langs;
8647
8648 // Do we want a multiselect ?
8649 //$jsbeautify = 0;
8650 //if (preg_match('/^multi/',$htmlname)) $jsbeautify = 1;
8651 $jsbeautify = 1;
8652
8653 if ($value_as_key) {
8654 $array = array_combine($array, $array);
8655 }
8656
8657 '@phan-var-force array{label:string,data-html:string,disable?:int<0,1>,css?:string} $array'; // Array combine breaks information
8658
8659 $out = '';
8660
8661 if ($addjscombo < 0) {
8662 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8663 $addjscombo = 1;
8664 } else {
8665 $addjscombo = 0;
8666 }
8667 }
8668 $idname = str_replace(array('[', ']'), array('', ''), $htmlname);
8669 $out .= '<select id="' . preg_replace('/^\./', '', $idname) . '" ' . ($disabled ? 'disabled="disabled" ' : '') . 'class="flat ' . (preg_replace('/^\./', '', $htmlname)) . ($morecss ? ' ' . $morecss : '') . ' selectformat"';
8670 $out .= ' name="' . preg_replace('/^\./', '', $htmlname) . '" ' . ($moreparam ? $moreparam : '');
8671 $out .= '>'."\n";
8672
8673 if ($show_empty) {
8674 $textforempty = ' ';
8675 if (!empty($conf->use_javascript_ajax)) {
8676 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
8677 }
8678 if (!is_numeric($show_empty)) {
8679 $textforempty = $show_empty;
8680 }
8681 $out .= '<option class="optiongrey" ' . ($moreparamonempty ? $moreparamonempty . ' ' : '') . 'value="' . (((int) $show_empty) < 0 ? $show_empty : -1) . '"' . ($id == $show_empty ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
8682 }
8683 if (is_array($array)) {
8684 // Translate
8685 if ($translate) {
8686 foreach ($array as $key => $value) {
8687 if (!is_array($value)) {
8688 $array[$key] = $langs->trans($value);
8689 } else {
8690 $array[$key]['label'] = $langs->trans($value['label']);
8691 }
8692 }
8693 }
8694 // Sort
8695 if ($sort == 'ASC') {
8696 asort($array);
8697 } elseif ($sort == 'DESC') {
8698 arsort($array);
8699 }
8700
8701 foreach ($array as $key => $tmpvalue) {
8702 if (is_array($tmpvalue)) {
8703 $value = $tmpvalue['label'];
8704 //$valuehtml = empty($tmpvalue['data-html']) ? $value : $tmpvalue['data-html'];
8705 $disabled = empty($tmpvalue['disabled']) ? '' : ' disabled';
8706 $style = empty($tmpvalue['css']) ? '' : ' class="' . $tmpvalue['css'] . '"';
8707 } else {
8708 $value = $tmpvalue;
8709 //$valuehtml = $tmpvalue;
8710 $disabled = '';
8711 $style = '';
8712 }
8713 if (!empty($disablebademail)) {
8714 if (($disablebademail == 1 && !preg_match('/&lt;.+@.+&gt;/', $value))
8715 || ($disablebademail == 2 && preg_match('/---/', $value))) {
8716 $disabled = ' disabled';
8717 $style = ' class="warning"';
8718 }
8719 }
8720 if ($key_in_label) {
8721 if (empty($nohtmlescape)) {
8722 $selectOptionValue = dol_escape_htmltag($key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value));
8723 } else {
8724 $selectOptionValue = $key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value);
8725 }
8726 } else {
8727 if (empty($nohtmlescape)) {
8728 $selectOptionValue = dol_escape_htmltag($maxlen ? dol_trunc($value, $maxlen) : $value);
8729 } else {
8730 $selectOptionValue = $maxlen ? dol_trunc($value, $maxlen) : $value;
8731 }
8732 if ($value == '' || $value == '-') {
8733 $selectOptionValue = '&nbsp;';
8734 }
8735 }
8736 $out .= '<option value="' . $key . '"';
8737 $out .= $style . $disabled;
8738 if (is_array($id)) {
8739 if (in_array($key, $id) && !$disabled) {
8740 $out .= ' selected'; // To preselect a value
8741 }
8742 } else {
8743 $id = (string) $id; // if $id = 0, then $id = '0'
8744 if ($id != '' && (($id == (string) $key) || ($id == 'ifone' && count($array) == 1)) && !$disabled) {
8745 $out .= ' selected'; // To preselect a value
8746 }
8747 }
8748 if (!empty($nohtmlescape)) { // deprecated. Use instead the key 'data-html' into input $array, managed at next step to use HTML content.
8749 $out .= ' data-html="' . dol_escape_htmltag($selectOptionValue) . '"';
8750 }
8751
8752 if (is_array($tmpvalue)) {
8753 foreach ($tmpvalue as $keyforvalue => $valueforvalue) {
8754 if (preg_match('/^data-/', $keyforvalue)) { // The best solution if you want to use HTML values into the list is to use data-html.
8755 $out .= ' '.dol_escape_htmltag($keyforvalue).'="'.dol_escape_htmltag($valueforvalue).'"';
8756 }
8757 }
8758 }
8759 $out .= '>';
8760 $out .= $selectOptionValue;
8761 $out .= "</option>\n";
8762 }
8763 }
8764 $out .= "</select>";
8765
8766 // Add code for jquery to use multiselect
8767 if ($addjscombo && $jsbeautify) {
8768 // Enhance with select2
8769 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8770 $out .= ajax_combobox($idname, array(), 0, 0, 'resolve', (((int) $show_empty) < 0 ? (string) $show_empty : '-1'), $morecss);
8771 }
8772
8773 return $out;
8774 }
8775
8794 public static function selectArrayAjax($htmlname, $url, $id = '', $moreparam = '', $moreparamtourl = '', $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0)
8795 {
8796 global $conf, $langs;
8797 global $delayedhtmlcontent; // Will be used later outside of this function
8798
8799 // TODO Use an internal dolibarr component instead of select2
8800 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8801 return '';
8802 }
8803
8804 $out = '<select type="text" class="' . $htmlname . ($morecss ? ' ' . $morecss : '') . '" ' . ($moreparam ? $moreparam . ' ' : '') . 'name="' . $htmlname . '"></select>';
8805
8806 $outdelayed = '';
8807 if (!empty($conf->use_javascript_ajax)) {
8808 $tmpplugin = 'select2';
8809 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8810 <script nonce="' . getNonce() . '">
8811 $(document).ready(function () {
8812
8813 ' . ($callurlonselect ? 'var saveRemoteData = [];' : '') . '
8814
8815 $(".' . $htmlname . '").select2({
8816 ajax: {
8817 dir: "ltr",
8818 url: "' . $url . '",
8819 dataType: \'json\',
8820 delay: 250,
8821 data: function (params) {
8822 return {
8823 q: params.term, // search term
8824 page: params.page
8825 }
8826 },
8827 processResults: function (data) {
8828 // parse the results into the format expected by Select2.
8829 // since we are using custom formatting functions we do not need to alter the remote JSON data
8830 //console.log(data);
8831 saveRemoteData = data;
8832 /* format json result for select2 */
8833 result = []
8834 $.each( data, function( key, value ) {
8835 result.push({id: key, text: value.text});
8836 });
8837 //return {results:[{id:\'none\', text:\'aa\'}, {id:\'rrr\', text:\'Red\'},{id:\'bbb\', text:\'Search a into projects\'}], more:false}
8838 //console.log(result);
8839 return {results: result, more: false}
8840 },
8841 cache: true
8842 },
8843 language: select2arrayoflanguage,
8844 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8845 placeholder: "' . dol_escape_js($placeholder) . '",
8846 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8847 minimumInputLength: ' . ((int) $minimumInputLength) . ',
8848 formatResult: function (result, container, query, escapeMarkup) {
8849 return escapeMarkup(result.text);
8850 },
8851 });
8852
8853 ' . ($callurlonselect ? '
8854 /* Code to execute a GET when we select a value */
8855 $(".' . $htmlname . '").change(function() {
8856 var selected = $(".' . $htmlname . '").val();
8857 console.log("We select in selectArrayAjax the entry "+selected)
8858 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8859 $.each( saveRemoteData, function( key, value ) {
8860 if (key == selected)
8861 {
8862 console.log("selectArrayAjax - Do a redirect to "+value.url)
8863 location.assign(value.url);
8864 }
8865 });
8866 });' : '') . '
8867
8868 });
8869 </script>';
8870 }
8871
8872 if ($acceptdelayedhtml) {
8873 $delayedhtmlcontent .= $outdelayed;
8874 } else {
8875 $out .= $outdelayed;
8876 }
8877 return $out;
8878 }
8879
8899 public static function selectArrayFilter($htmlname, $array, $id = '', $moreparam = '', $disableFiltering = 0, $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0, $textfortitle = '')
8900 {
8901 global $conf, $langs;
8902 global $delayedhtmlcontent; // Will be used later outside of this function
8903
8904 // TODO Use an internal dolibarr component instead of select2
8905 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8906 return '';
8907 }
8908
8909 $out = '<select type="text"'.($textfortitle ? ' title="'.dol_escape_htmltag($textfortitle).'"' : '').' id="'.$htmlname.'" class="'.$htmlname.($morecss ? ' ' . $morecss : '').'"'.($moreparam ? ' '.$moreparam : '').' name="'.$htmlname.'"><option></option></select>';
8910
8911 $formattedarrayresult = array();
8912
8913 foreach ($array as $key => $value) {
8914 $o = new stdClass();
8915 $o->id = $key;
8916 $o->text = $value['text'];
8917 $o->url = $value['url'];
8918 $formattedarrayresult[] = $o;
8919 }
8920
8921 $outdelayed = '';
8922 if (!empty($conf->use_javascript_ajax)) {
8923 $tmpplugin = 'select2';
8924 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8925 <script nonce="' . getNonce() . '">
8926 $(document).ready(function () {
8927 var data = ' . json_encode($formattedarrayresult) . ';
8928
8929 ' . ($callurlonselect ? 'var saveRemoteData = ' . json_encode($array) . ';' : '') . '
8930
8931 $(".' . $htmlname . '").select2({
8932 data: data,
8933 language: select2arrayoflanguage,
8934 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8935 placeholder: "' . dol_escape_js($placeholder) . '",
8936 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8937 minimumInputLength: ' . $minimumInputLength . ',
8938 formatResult: function (result, container, query, escapeMarkup) {
8939 return escapeMarkup(result.text);
8940 },
8941 matcher: function (params, data) {
8942
8943 if(! data.id) return null;';
8944
8945 if ($callurlonselect) {
8946 // We forge the url with 'sall='
8947 $outdelayed .= '
8948
8949 var urlBase = data.url;
8950 var separ = urlBase.indexOf("?") >= 0 ? "&" : "?";
8951 /* console.log("params.term="+params.term); */
8952 /* console.log("params.term encoded="+encodeURIComponent(params.term)); */
8953 saveRemoteData[data.id].url = urlBase + separ + "search_all=" + encodeURIComponent(params.term.replace(/\"/g, ""));';
8954 }
8955
8956 if (!$disableFiltering) {
8957 $outdelayed .= '
8958
8959 if(data.text.match(new RegExp(params.term))) {
8960 return data;
8961 }
8962
8963 return null;';
8964 } else {
8965 $outdelayed .= '
8966
8967 return data;';
8968 }
8969
8970 $outdelayed .= '
8971 }
8972 });
8973
8974 ' . ($callurlonselect ? '
8975 /* Code to execute a GET when we select a value */
8976 $(".' . $htmlname . '").change(function() {
8977 var selected = $(".' . $htmlname . '").val();
8978 console.log("We select "+selected)
8979
8980 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8981 $.each( saveRemoteData, function( key, value ) {
8982 if (key == selected)
8983 {
8984 console.log("selectArrayFilter - Do a redirect to "+value.url)
8985 location.assign(value.url);
8986 }
8987 });
8988 });' : '') . '
8989
8990 });
8991 </script>';
8992 }
8993
8994 if ($acceptdelayedhtml) {
8995 $delayedhtmlcontent .= $outdelayed;
8996 } else {
8997 $out .= $outdelayed;
8998 }
8999 return $out;
9000 }
9001
9020 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)
9021 {
9022 global $conf, $langs;
9023
9024 $out = '';
9025
9026 if ($addjscombo < 0) {
9027 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
9028 $addjscombo = 1;
9029 } else {
9030 $addjscombo = 0;
9031 }
9032 }
9033
9034 $useenhancedmultiselect = 0;
9035 if (!empty($conf->use_javascript_ajax) && !defined('MAIN_DO_NOT_USE_JQUERY_MULTISELECT') && (getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT'))) {
9036 if ($addjscombo) {
9037 $useenhancedmultiselect = 1; // Use the js multiselect in one line. Possible only if $addjscombo not 0.
9038 }
9039 }
9040
9041 // We need a hidden field because when using the multiselect, if we unselect all, there is no
9042 // variable submitted at all, so no way to make a difference between variable not submitted and variable
9043 // submitted to nothing.
9044 $out .= '<input type="hidden" name="'.$htmlname.'_multiselect" value="1">';
9045 // Output select component
9046 $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";
9047 if (is_array($array) && !empty($array)) {
9048 if ($value_as_key) {
9049 $array = array_combine($array, $array);
9050 }
9051
9052 if (!empty($array)) {
9053 foreach ($array as $key => $value) {
9054 $tmpkey = $key;
9055 $tmpvalue = $value;
9056 $tmpcolor = '';
9057 $tmppicto = '';
9058 $tmplabelhtml = '';
9059 if (is_array($value) && array_key_exists('id', $value) && array_key_exists('label', $value)) {
9060 $tmpkey = $value['id'];
9061 $tmpvalue = empty($value['label']) ? '' : $value['label'];
9062 $tmpcolor = empty($value['color']) ? '' : $value['color'];
9063 $tmppicto = empty($value['picto']) ? '' : $value['picto'];
9064 $tmplabelhtml = empty($value['labelhtml']) ? (empty($value['data-html']) ? '' : $value['data-html']): $value['labelhtml'];
9065 }
9066 $newval = ($translate ? $langs->trans($tmpvalue) : $tmpvalue);
9067 $newval = ($key_in_label ? $tmpkey . ' - ' . $newval : $newval);
9068
9069 $out .= '<option value="' . $tmpkey . '"';
9070 if (is_array($selected) && !empty($selected) && in_array((string) $tmpkey, $selected) && ((string) $tmpkey != '')) {
9071 $out .= ' selected';
9072 }
9073 if (!empty($tmplabelhtml)) {
9074 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
9075 } else {
9076 $tmplabelhtml = ($tmppicto ? img_picto('', $tmppicto, 'class="pictofixedwidth" style="color: #' . $tmpcolor . '"') : '') . $newval;
9077 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
9078 }
9079 $out .= '>';
9080 $out .= dol_htmlentitiesbr($newval);
9081 $out .= '</option>' . "\n";
9082 }
9083 }
9084 }
9085 $out .= '</select>' . "\n";
9086
9087 // Add code for jquery to use multiselect
9088 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT')) {
9089 $out .= "\n" . '<!-- JS CODE TO ENABLE select for id ' . $htmlname . ', addjscombo=' . $addjscombo . ' -->';
9090 $out .= "\n" . '<script nonce="' . getNonce() . '">' . "\n";
9091 if ($addjscombo == 1) {
9092 $tmpplugin = !getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT;
9093 $out .= 'function formatResult(record, container) {' . "\n";
9094 // If property data-html set, we decode html entities and use this.
9095 // Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, '', 0, 1) when building the select option.
9096 $out .= ' if ($(record.element).attr("data-html") != undefined && typeof htmlEntityDecodeJs === "function") {';
9097 //$out .= ' console.log("aaa");';
9098 $out .= ' return htmlEntityDecodeJs($(record.element).attr("data-html"));';
9099 $out .= ' }'."\n";
9100 $out .= ' return record.text;';
9101 $out .= '}' . "\n";
9102 $out .= 'function formatSelection(record) {' . "\n";
9103 if ($elemtype == 'category') {
9104 $out .= 'return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';';
9105 } else {
9106 $out .= 'return record.text;';
9107 }
9108 $out .= '}' . "\n";
9109 $out .= '$(document).ready(function () {
9110 $(\'#' . $htmlname . '\').' . $tmpplugin . '({';
9111 if ($placeholder) {
9112 $out .= '
9113 placeholder: {
9114 id: \'-1\',
9115 text: \'' . dol_escape_js($placeholder) . '\'
9116 },';
9117 }
9118 $out .= ' dir: \'ltr\',
9119 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag (ko with multiselect) */
9120 dropdownCssClass: \'' . $morecss . '\', /* Line to add class on the new <span class="select2-selection...> tag (ok with multiselect). Need full version of select2. */
9121 // Specify format function for dropdown item
9122 formatResult: formatResult,
9123 templateResult: formatResult, /* For 4.0 */
9124 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
9125 // Specify format function for selected item
9126 formatSelection: formatSelection,
9127 templateSelection: formatSelection /* For 4.0 */
9128 });
9129
9130 /* Add also morecss to the css .select2 that is after the #htmlname, for component that are show dynamically after load, because select2 set
9131 the size only if component is not hidden by default on load */
9132 $(\'#' . $htmlname . ' + .select2\').addClass(\'' . $morecss . '\');
9133 });' . "\n";
9134 } elseif ($addjscombo == 2 && !defined('DISABLE_MULTISELECT')) {
9135 // Add other js lib
9136 // TODO external lib multiselect/jquery.multi-select.js must have been loaded to use this multiselect plugin
9137 // ...
9138 $out .= 'console.log(\'addjscombo=2 for htmlname=' . $htmlname . '\');';
9139 $out .= '$(document).ready(function () {
9140 $(\'#' . $htmlname . '\').multiSelect({
9141 containerHTML: \'<div class="multi-select-container">\',
9142 menuHTML: \'<div class="multi-select-menu">\',
9143 buttonHTML: \'<span class="multi-select-button ' . $morecss . '">\',
9144 menuItemHTML: \'<label class="multi-select-menuitem">\',
9145 activeClass: \'multi-select-container--open\',
9146 noneText: \'' . $placeholder . '\'
9147 });
9148 })';
9149 }
9150 $out .= '</script>';
9151 }
9152
9153 return $out;
9154 }
9155
9156
9168 public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage, $pos = '')
9169 {
9170 global $langs, $user;
9171
9172 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
9173 return '';
9174 }
9175 if (empty($array)) {
9176 return '';
9177 }
9178
9179 $tmpvar = "MAIN_SELECTEDFIELDS_" . $varpage; // To get list of saved selected fields to show
9180
9181 if (!empty($user->conf->$tmpvar)) { // A list of fields was already customized for user
9182 $tmparray = explode(',', $user->conf->$tmpvar);
9183 foreach ($array as $key => $val) {
9184 //var_dump($key);
9185 //var_dump($tmparray);
9186 if (in_array($key, $tmparray)) {
9187 $array[$key]['checked'] = 1;
9188 } else {
9189 $array[$key]['checked'] = 0;
9190 }
9191 }
9192 } else { // There is no list of fields already customized for user
9193 foreach ($array as $key => $val) {
9194 if (!empty($array[$key]['checked']) && $array[$key]['checked'] < 0) {
9195 $array[$key]['checked'] = 0;
9196 }
9197 }
9198 }
9199
9200 $listoffieldsforselection = '';
9201 $listcheckedstring = '';
9202
9203 foreach ($array as $key => $val) {
9204 // var_dump($val);
9205 // var_dump(array_key_exists('enabled', $val));
9206 // var_dump(!$val['enabled']);
9207 if (array_key_exists('enabled', $val) && isset($val['enabled']) && !$val['enabled']) {
9208 unset($array[$key]); // We don't want this field
9209 continue;
9210 }
9211 if (!empty($val['type']) && $val['type'] == 'separate') {
9212 // Field remains in array but we don't add it into $listoffieldsforselection
9213 //$listoffieldsforselection .= '<li>-----</li>';
9214 continue;
9215 }
9216 if (!empty($val['label']) && $val['label']) {
9217 if (!empty($val['langfile']) && is_object($langs)) {
9218 $langs->load($val['langfile']);
9219 }
9220
9221 // Note: $val['checked'] <> 0 means we must show the field into the combo list @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset
9222 $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>';
9223 $listcheckedstring .= (empty($val['checked']) ? '' : $key . ',');
9224 }
9225 }
9226
9227 $out = '<!-- Component multiSelectArrayWithCheckbox ' . $htmlname . ' -->
9228
9229 <dl class="dropdown">
9230 <dt>
9231 <a href="#' . $htmlname . '">
9232 ' . img_picto('', 'list') . '
9233 </a>
9234 <input type="hidden" class="' . $htmlname . '" name="' . $htmlname . '" value="' . $listcheckedstring . '">
9235 </dt>
9236 <dd class="dropdowndd">
9237 <div class="multiselectcheckbox'.$htmlname.'">
9238 <ul class="'.$htmlname.($pos == '1' ? 'left' : '').'">
9239 <li><input class="inputsearch_dropdownselectedfields width90p minwidth200imp" style="width:90%;" type="text" placeholder="'.$langs->trans('Search').'"></li>
9240 '.$listoffieldsforselection.'
9241 </ul>
9242 </div>
9243 </dd>
9244 </dl>
9245
9246 <script nonce="' . getNonce() . '" type="text/javascript">
9247 jQuery(document).ready(function () {
9248 $(\'.multiselectcheckbox' . $htmlname . ' input[type="checkbox"]\').on(\'click\', function () {
9249 console.log("A new field was added/removed, we edit field input[name=formfilteraction]");
9250
9251 $("input:hidden[name=formfilteraction]").val(\'listafterchangingselectedfields\'); // Update field so we know we changed something on selected fields after POST
9252
9253 var title = $(this).val() + ",";
9254 if ($(this).is(\':checked\')) {
9255 $(\'.' . $htmlname . '\').val(title + $(\'.' . $htmlname . '\').val());
9256 }
9257 else {
9258 $(\'.' . $htmlname . '\').val( $(\'.' . $htmlname . '\').val().replace(title, \'\') )
9259 }
9260 // Now, we submit page
9261 //$(this).parents(\'form:first\').submit();
9262 });
9263 $("input.inputsearch_dropdownselectedfields").on("keyup", function() {
9264 var value = $(this).val().toLowerCase();
9265 $(\'.multiselectcheckbox'.$htmlname.' li > label\').filter(function() {
9266 $(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
9267 });
9268 });
9269
9270
9271 });
9272 </script>
9273
9274 ';
9275 return $out;
9276 }
9277
9287 public function showCategories($id, $type, $rendermode = 0, $nolink = 0)
9288 {
9289 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
9290
9291 $cat = new Categorie($this->db);
9292 $categories = $cat->containing($id, $type);
9293
9294 if ($rendermode == 1) {
9295 $toprint = array();
9296 foreach ($categories as $c) {
9297 $ways = $c->print_all_ways(' &gt;&gt; ', ($nolink ? 'none' : ''), 0, 1); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
9298 foreach ($ways as $way) {
9299 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . $way . '</li>';
9300 }
9301 }
9302 if (empty($toprint)) {
9303 return '';
9304 } else {
9305 return '<div class="select2-container-multi-dolibarr"><ul class="select2-choices-dolibarr">' . implode(' ', $toprint) . '</ul></div>';
9306 }
9307 }
9308
9309 if ($rendermode == 0) {
9310 $arrayselected = array();
9311 $cate_arbo = $this->select_all_categories($type, '', 'parent', 64, 0, 3);
9312 foreach ($categories as $c) {
9313 $arrayselected[] = $c->id;
9314 }
9315
9316 return $this->multiselectarray('categories', $cate_arbo, $arrayselected, 0, 0, '', 0, '100%', 'disabled', 'category');
9317 }
9318
9319 return 'ErrorBadValueForParameterRenderMode'; // Should not happened
9320 }
9321
9331 public function showLinkedObjectBlock($object, $morehtmlright = '', $compatibleImportElementsList = array(), $title = 'RelatedObjects')
9332 {
9333 global $conf, $langs, $hookmanager;
9334 global $bc, $action;
9335
9336 $object->fetchObjectLinked();
9337
9338 // Bypass the default method
9339 $hookmanager->initHooks(array('commonobject'));
9340 $parameters = array(
9341 'morehtmlright' => $morehtmlright,
9342 'compatibleImportElementsList' => &$compatibleImportElementsList,
9343 );
9344 $reshook = $hookmanager->executeHooks('showLinkedObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9345
9346 $nbofdifferenttypes = count($object->linkedObjects);
9347
9348 if (empty($reshook)) {
9349 print '<!-- showLinkedObjectBlock -->';
9350 print load_fiche_titre($langs->trans($title), $morehtmlright, '', 0, 0, 'showlinkedobjectblock');
9351
9352
9353 print '<div class="div-table-responsive-no-min">';
9354 print '<table class="noborder allwidth" data-block="showLinkedObject" data-element="' . $object->element . '" data-elementid="' . $object->id . '" >';
9355
9356 print '<tr class="liste_titre">';
9357 print '<td>' . $langs->trans("Type") . '</td>';
9358 print '<td>' . $langs->trans("Ref") . '</td>';
9359 print '<td class="center"></td>';
9360 print '<td class="center">' . $langs->trans("Date") . '</td>';
9361 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9362 print '<td class="right">' . $langs->trans("Status") . '</td>';
9363 print '<td></td>';
9364 print '</tr>';
9365
9366 $nboftypesoutput = 0;
9367
9368 foreach ($object->linkedObjects as $objecttype => $objects) {
9369 $tplpath = $element = $subelement = $objecttype;
9370
9371 // to display import button on tpl
9372 $showImportButton = false;
9373 if (!empty($compatibleImportElementsList) && in_array($element, $compatibleImportElementsList)) {
9374 $showImportButton = true;
9375 }
9376
9377 $regs = array();
9378 if ($objecttype != 'supplier_proposal' && preg_match('/^([^_]+)_([^_]+)/i', $objecttype, $regs)) {
9379 $element = $regs[1];
9380 $subelement = $regs[2];
9381 $tplpath = $element . '/' . $subelement;
9382 }
9383 $tplname = 'linkedobjectblock';
9384
9385 // To work with non standard path
9386 if ($objecttype == 'facture') {
9387 $tplpath = 'compta/' . $element;
9388 if (!isModEnabled('invoice')) {
9389 continue; // Do not show if module disabled
9390 }
9391 } elseif ($objecttype == 'facturerec') {
9392 $tplpath = 'compta/facture';
9393 $tplname = 'linkedobjectblockForRec';
9394 if (!isModEnabled('invoice')) {
9395 continue; // Do not show if module disabled
9396 }
9397 } elseif ($objecttype == 'propal') {
9398 $tplpath = 'comm/' . $element;
9399 if (!isModEnabled('propal')) {
9400 continue; // Do not show if module disabled
9401 }
9402 } elseif ($objecttype == 'supplier_proposal') {
9403 if (!isModEnabled('supplier_proposal')) {
9404 continue; // Do not show if module disabled
9405 }
9406 } elseif ($objecttype == 'shipping' || $objecttype == 'shipment' || $objecttype == 'expedition') {
9407 $tplpath = 'expedition';
9408 if (!isModEnabled('shipping')) {
9409 continue; // Do not show if module disabled
9410 }
9411 } elseif ($objecttype == 'reception') {
9412 $tplpath = 'reception';
9413 if (!isModEnabled('reception')) {
9414 continue; // Do not show if module disabled
9415 }
9416 } elseif ($objecttype == 'delivery') {
9417 $tplpath = 'delivery';
9418 if (!getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) {
9419 continue; // Do not show if sub module disabled
9420 }
9421 } elseif ($objecttype == 'ficheinter') {
9422 $tplpath = 'fichinter';
9423 if (!isModEnabled('intervention')) {
9424 continue; // Do not show if module disabled
9425 }
9426 } elseif ($objecttype == 'invoice_supplier') {
9427 $tplpath = 'fourn/facture';
9428 } elseif ($objecttype == 'order_supplier') {
9429 $tplpath = 'fourn/commande';
9430 } elseif ($objecttype == 'expensereport') {
9431 $tplpath = 'expensereport';
9432 } elseif ($objecttype == 'subscription') {
9433 $tplpath = 'adherents';
9434 } elseif ($objecttype == 'conferenceorbooth') {
9435 $tplpath = 'eventorganization';
9436 } elseif ($objecttype == 'conferenceorboothattendee') {
9437 $tplpath = 'eventorganization';
9438 } elseif ($objecttype == 'mo') {
9439 $tplpath = 'mrp';
9440 if (!isModEnabled('mrp')) {
9441 continue; // Do not show if module disabled
9442 }
9443 }
9444
9445 global $linkedObjectBlock;
9446 $linkedObjectBlock = $objects;
9447
9448 // Output template part (modules that overwrite templates must declare this into descriptor)
9449 $dirtpls = array_merge($conf->modules_parts['tpl'], array('/' . $tplpath . '/tpl'));
9450 foreach ($dirtpls as $reldir) {
9451 $reldir = rtrim($reldir, '/');
9452 if ($nboftypesoutput == ($nbofdifferenttypes - 1)) { // No more type to show after
9453 global $noMoreLinkedObjectBlockAfter;
9454 $noMoreLinkedObjectBlockAfter = 1;
9455 }
9456
9457 $res = @include dol_buildpath($reldir . '/' . $tplname . '.tpl.php');
9458 if ($res) {
9459 $nboftypesoutput++;
9460 break;
9461 }
9462 }
9463 }
9464
9465 if (!$nboftypesoutput) {
9466 print '<tr><td class="impair" colspan="7"><span class="opacitymedium">' . $langs->trans("None") . '</span></td></tr>';
9467 }
9468
9469 print '</table>';
9470
9471 if (!empty($compatibleImportElementsList)) {
9472 $res = @include dol_buildpath('core/tpl/objectlinked_lineimport.tpl.php');
9473 }
9474
9475 print '</div>';
9476 }
9477
9478 return $nbofdifferenttypes;
9479 }
9480
9489 public function showLinkToObjectBlock($object, $restrictlinksto = array(), $excludelinksto = array())
9490 {
9491 global $conf, $langs, $hookmanager;
9492 global $action;
9493
9494 $linktoelem = '';
9495 $linktoelemlist = '';
9496 $listofidcompanytoscan = '';
9497
9498 if (!is_object($object->thirdparty)) {
9499 $object->fetch_thirdparty();
9500 }
9501
9502 $possiblelinks = array();
9503 if (is_object($object->thirdparty) && !empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
9504 $listofidcompanytoscan = $object->thirdparty->id;
9505 if (($object->thirdparty->parent > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PARENT_IN_LINKTO')) {
9506 $listofidcompanytoscan .= ',' . $object->thirdparty->parent;
9507 }
9508 if (($object->fk_project > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PROJECT_THIRDPARY_IN_LINKTO')) {
9509 include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
9510 $tmpproject = new Project($this->db);
9511 $tmpproject->fetch($object->fk_project);
9512 if ($tmpproject->socid > 0 && ($tmpproject->socid != $object->thirdparty->id)) {
9513 $listofidcompanytoscan .= ',' . $tmpproject->socid;
9514 }
9515 unset($tmpproject);
9516 }
9517
9518 $possiblelinks = array(
9519 'propal' => array(
9520 'enabled' => isModEnabled('propal'),
9521 'perms' => 1,
9522 'label' => 'LinkToProposal',
9523 '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') . ')'),
9524 'shipping' => array(
9525 'enabled' => isModEnabled('shipping'),
9526 'perms' => 1,
9527 'label' => 'LinkToExpedition',
9528 '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') . ')'),
9529 'order' => array(
9530 'enabled' => isModEnabled('order'),
9531 'perms' => 1,
9532 'label' => 'LinkToOrder',
9533 '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') . ')'),
9534 'invoice' => array(
9535 'enabled' => isModEnabled('invoice'),
9536 'perms' => 1,
9537 'label' => 'LinkToInvoice',
9538 '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') . ')'),
9539 'invoice_template' => array(
9540 'enabled' => isModEnabled('invoice'),
9541 'perms' => 1,
9542 'label' => 'LinkToTemplateInvoice',
9543 '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') . ')'),
9544 'contrat' => array(
9545 'enabled' => isModEnabled('contract'),
9546 'perms' => 1,
9547 'label' => 'LinkToContract',
9548 '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
9549 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'
9550 ),
9551 'fichinter' => array(
9552 'enabled' => isModEnabled('intervention'),
9553 'perms' => 1,
9554 'label' => 'LinkToIntervention',
9555 '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') . ')'),
9556 'supplier_proposal' => array(
9557 'enabled' => isModEnabled('supplier_proposal'),
9558 'perms' => 1,
9559 'label' => 'LinkToSupplierProposal',
9560 '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') . ')'),
9561 'order_supplier' => array(
9562 'enabled' => isModEnabled("supplier_order"),
9563 'perms' => 1,
9564 'label' => 'LinkToSupplierOrder',
9565 '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') . ')'),
9566 'invoice_supplier' => array(
9567 'enabled' => isModEnabled("supplier_invoice"),
9568 'perms' => 1, 'label' => 'LinkToSupplierInvoice',
9569 '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') . ')'),
9570 'ticket' => array(
9571 'enabled' => isModEnabled('ticket'),
9572 'perms' => 1,
9573 'label' => 'LinkToTicket',
9574 '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') . ')'),
9575 'mo' => array(
9576 'enabled' => isModEnabled('mrp'),
9577 'perms' => 1,
9578 'label' => 'LinkToMo',
9579 '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') . ')')
9580 );
9581 }
9582
9583 if ($object->table_element == 'commande_fournisseur') {
9584 $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').')';
9585 } elseif ($object->table_element == 'mrp_mo') {
9586 $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').')';
9587 }
9588
9589 $reshook = 0; // Ensure $reshook is defined for static analysis
9590 if (!empty($listofidcompanytoscan)) { // If empty, we don't have criteria to scan the object we can link to
9591 // Can complete the possiblelink array
9592 $hookmanager->initHooks(array('commonobject'));
9593 $parameters = array('listofidcompanytoscan' => $listofidcompanytoscan, 'possiblelinks' => $possiblelinks);
9594 $reshook = $hookmanager->executeHooks('showLinkToObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9595 }
9596
9597 if (empty($reshook)) {
9598 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9599 $possiblelinks = array_merge($possiblelinks, $hookmanager->resArray);
9600 }
9601 } elseif ($reshook > 0) {
9602 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9603 $possiblelinks = $hookmanager->resArray;
9604 }
9605 }
9606
9607 foreach ($possiblelinks as $key => $possiblelink) {
9608 $num = 0;
9609
9610 if (empty($possiblelink['enabled'])) {
9611 continue;
9612 }
9613
9614 if (!empty($possiblelink['perms']) && (empty($restrictlinksto) || in_array($key, $restrictlinksto)) && (empty($excludelinksto) || !in_array($key, $excludelinksto))) {
9615 print '<div id="' . $key . 'list"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display:none"') . '>';
9616
9617 if (getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9618 print '<br>'."\n";
9619 print '<!-- form to add a link from anywhere -->'."\n";
9620 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinkedbyref' . $key . '">';
9621 print '<input type="hidden" name="id" value="' . $object->id . '">';
9622 print '<input type="hidden" name="action" value="addlinkbyref">';
9623 print '<input type="hidden" name="token" value="' . newToken() . '">';
9624 print '<input type="hidden" name="addlink" value="' . $key . '">';
9625 print '<table class="noborder">';
9626 print '<tr>';
9627 //print '<td>' . $langs->trans("Ref") . '</td>';
9628 print '<td class="center"><input type="text" placeholder="'.dol_escape_htmltag($langs->trans("Ref")).'" name="reftolinkto" value="' . dol_escape_htmltag(GETPOST('reftolinkto', 'alpha')) . '">&nbsp;';
9629 print '<input type="submit" class="button small valignmiddle" value="' . $langs->trans('ToLink') . '">&nbsp;';
9630 print '<input type="submit" class="button small" name="cancel" value="' . $langs->trans('Cancel') . '"></td>';
9631 print '</tr>';
9632 print '</table>';
9633 print '</form>';
9634 }
9635
9636 $sql = $possiblelink['sql'];
9637
9638 $resqllist = $this->db->query($sql);
9639 if ($resqllist) {
9640 $num = $this->db->num_rows($resqllist);
9641 $i = 0;
9642
9643 print '<br>';
9644 print '<!-- form to add a link from object to same thirdparty -->'."\n";
9645 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinked' . $key . '">';
9646 print '<input type="hidden" name="action" value="addlink">';
9647 print '<input type="hidden" name="token" value="' . newToken() . '">';
9648 print '<input type="hidden" name="id" value="' . $object->id . '">';
9649 print '<input type="hidden" name="addlink" value="' . $key . '">';
9650 print '<table class="noborder">';
9651 print '<tr class="liste_titre">';
9652 print '<td class="nowrap"></td>';
9653 print '<td class="center">' . $langs->trans("Ref") . '</td>';
9654 print '<td class="left">' . $langs->trans("RefCustomer") . '</td>';
9655 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9656 print '<td class="left">' . $langs->trans("Company") . '</td>';
9657 print '</tr>';
9658 while ($i < $num) {
9659 $objp = $this->db->fetch_object($resqllist);
9660
9661 print '<tr class="oddeven">';
9662 print '<td class="left">';
9663 print '<input type="radio" name="idtolinkto" id="' . $key . '_' . $objp->rowid . '" value="' . $objp->rowid . '">';
9664 print '</td>';
9665 print '<td class="center"><label for="' . $key . '_' . $objp->rowid . '">' . $objp->ref . '</label></td>';
9666 print '<td>' . (!empty($objp->ref_client) ? $objp->ref_client : (!empty($objp->ref_supplier) ? $objp->ref_supplier : '')) . '</td>';
9667 print '<td class="right">';
9668 if ($possiblelink['label'] == 'LinkToContract') {
9669 $form = new Form($this->db);
9670 print $form->textwithpicto('', $langs->trans("InformationOnLinkToContract")) . ' ';
9671 }
9672 print '<span class="amount">' . (isset($objp->total_ht) ? price($objp->total_ht) : '') . '</span>';
9673 print '</td>';
9674 print '<td>' . $objp->name . '</td>';
9675 print '</tr>';
9676 $i++;
9677 }
9678 print '</table>';
9679 print '<div class="center">';
9680 if ($num) {
9681 print '<input type="submit" class="button valignmiddle marginleftonly marginrightonly small" value="' . $langs->trans('ToLink') . '">';
9682 }
9683 if (empty($conf->use_javascript_ajax)) {
9684 print '<input type="submit" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9685 } else {
9686 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>';
9687 }
9688 print '</form>';
9689 $this->db->free($resqllist);
9690 } else {
9691 dol_print_error($this->db);
9692 }
9693 print '</div>';
9694
9695 //$linktoelem.=($linktoelem?' &nbsp; ':'');
9696 if ($num > 0 || getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9697 $linktoelemlist .= '<li><a href="#linkto' . $key . '" class="linkto dropdowncloseonclick" rel="' . $key . '">' . $langs->trans($possiblelink['label']) . ' (' . $num . ')</a></li>';
9698 // } else $linktoelem.=$langs->trans($possiblelink['label']);
9699 } else {
9700 $linktoelemlist .= '<li><span class="linktodisabled">' . $langs->trans($possiblelink['label']) . ' (0)</span></li>';
9701 }
9702 }
9703 }
9704
9705 if ($linktoelemlist) {
9706 $linktoelem = '
9707 <dl class="dropdown" id="linktoobjectname">
9708 ';
9709 if (!empty($conf->use_javascript_ajax)) {
9710 $linktoelem .= '<dt><a href="#linktoobjectname"><span class="fas fa-link paddingrightonly"></span>' . $langs->trans("LinkTo") . '...</a></dt>';
9711 }
9712 $linktoelem .= '<dd>
9713 <div class="multiselectlinkto">
9714 <ul class="ulselectedfields">' . $linktoelemlist . '
9715 </ul>
9716 </div>
9717 </dd>
9718 </dl>';
9719 } else {
9720 $linktoelem = '';
9721 }
9722
9723 if (!empty($conf->use_javascript_ajax)) {
9724 print '<!-- Add js to show linkto box -->
9725 <script nonce="' . getNonce() . '">
9726 jQuery(document).ready(function() {
9727 jQuery(".linkto").click(function() {
9728 console.log("We choose to show/hide links for rel="+jQuery(this).attr(\'rel\')+" so #"+jQuery(this).attr(\'rel\')+"list");
9729 jQuery("#"+jQuery(this).attr(\'rel\')+"list").toggle();
9730 });
9731 });
9732 </script>
9733 ';
9734 }
9735
9736 return $linktoelem;
9737 }
9738
9753 public function selectyesno($htmlname, $value = '', $option = 0, $disabled = false, $useempty = 0, $addjscombo = 0, $morecss = '', $labelyes = 'Yes', $labelno = 'No')
9754 {
9755 global $langs;
9756
9757 $yes = "yes";
9758 $no = "no";
9759 if ($option) {
9760 $yes = "1";
9761 $no = "0";
9762 }
9763
9764 $disabled = ($disabled ? ' disabled' : '');
9765
9766 $resultyesno = '<select class="flat width75' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '"' . $disabled . '>' . "\n";
9767 if ($useempty) {
9768 $resultyesno .= '<option value="-1"' . (($value < 0) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
9769 }
9770 if (("$value" == 'yes') || ($value == 1)) {
9771 $resultyesno .= '<option value="' . $yes . '" selected>' . $langs->trans($labelyes) . '</option>' . "\n";
9772 $resultyesno .= '<option value="' . $no . '">' . $langs->trans($labelno) . '</option>' . "\n";
9773 } else {
9774 $selected = (($useempty && $value != '0' && $value != 'no') ? '' : ' selected');
9775 $resultyesno .= '<option value="' . $yes . '">' . $langs->trans($labelyes) . '</option>' . "\n";
9776 $resultyesno .= '<option value="' . $no . '"' . $selected . '>' . $langs->trans($labelno) . '</option>' . "\n";
9777 }
9778 $resultyesno .= '</select>' . "\n";
9779
9780 if ($addjscombo) {
9781 $resultyesno .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($useempty < 0 ? (string) $useempty : '-1'), $morecss);
9782 }
9783
9784 return $resultyesno;
9785 }
9786
9787 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
9788
9798 public function select_export_model($selected = '', $htmlname = 'exportmodelid', $type = '', $useempty = 0)
9799 {
9800 // phpcs:enable
9801 $sql = "SELECT rowid, label";
9802 $sql .= " FROM " . $this->db->prefix() . "export_model";
9803 $sql .= " WHERE type = '" . $this->db->escape($type) . "'";
9804 $sql .= " ORDER BY rowid";
9805 $result = $this->db->query($sql);
9806 if ($result) {
9807 print '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
9808 if ($useempty) {
9809 print '<option value="-1">&nbsp;</option>';
9810 }
9811
9812 $num = $this->db->num_rows($result);
9813 $i = 0;
9814 while ($i < $num) {
9815 $obj = $this->db->fetch_object($result);
9816 if ($selected == $obj->rowid) {
9817 print '<option value="' . $obj->rowid . '" selected>';
9818 } else {
9819 print '<option value="' . $obj->rowid . '">';
9820 }
9821 print $obj->label;
9822 print '</option>';
9823 $i++;
9824 }
9825 print "</select>";
9826 } else {
9827 dol_print_error($this->db);
9828 }
9829 }
9830
9849 public function showrefnav($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $morehtmlright = '')
9850 {
9851 global $conf, $langs, $hookmanager, $extralanguages;
9852
9853 $ret = '';
9854 if (empty($fieldid)) {
9855 $fieldid = 'rowid';
9856 }
9857 if (empty($fieldref)) {
9858 $fieldref = 'ref';
9859 }
9860
9861 // Preparing gender's display if there is one
9862 $addgendertxt = '';
9863 if (property_exists($object, 'gender') && !empty($object->gender)) {
9864 $addgendertxt = ' ';
9865 switch ($object->gender) {
9866 case 'man':
9867 $addgendertxt .= '<i class="fas fa-mars"></i>';
9868 break;
9869 case 'woman':
9870 $addgendertxt .= '<i class="fas fa-venus"></i>';
9871 break;
9872 case 'other':
9873 $addgendertxt .= '<i class="fas fa-transgender"></i>';
9874 break;
9875 }
9876 }
9877
9878 // Add where from hooks
9879 if (is_object($hookmanager)) {
9880 $parameters = array('showrefnav' => true);
9881 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
9882 $object->next_prev_filter .= $hookmanager->resPrint;
9883 }
9884
9885 $previous_ref = $next_ref = '';
9886 if ($shownav) {
9887 //print "paramid=$paramid,morehtml=$morehtml,shownav=$shownav,$fieldid,$fieldref,$morehtmlref,$moreparam";
9888 $object->load_previous_next_ref((isset($object->next_prev_filter) ? $object->next_prev_filter : ''), $fieldid, $nodbprefix);
9889
9890 $navurl = $_SERVER["PHP_SELF"];
9891 // Special case for project/task page
9892 if ($paramid == 'project_ref') {
9893 if (preg_match('/\/tasks\/(task|contact|note|document)\.php/', $navurl)) { // TODO Remove this when nav with project_ref on task pages are ok
9894 $navurl = preg_replace('/\/tasks\/(task|contact|time|note|document)\.php/', '/tasks.php', $navurl);
9895 $paramid = 'ref';
9896 }
9897 }
9898
9899 // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox
9900 // accesskey is for Mac: CTRL + key for all browsers
9901 $stringforfirstkey = $langs->trans("KeyboardShortcut");
9902 if ($conf->browser->name == 'chrome') {
9903 $stringforfirstkey .= ' ALT +';
9904 } elseif ($conf->browser->name == 'firefox') {
9905 $stringforfirstkey .= ' ALT + SHIFT +';
9906 } else {
9907 $stringforfirstkey .= ' CTL +';
9908 }
9909
9910 $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>';
9911 $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>';
9912 }
9913
9914 //print "xx".$previous_ref."x".$next_ref;
9915 $ret .= '<!-- Start banner content --><div style="vertical-align: middle">';
9916
9917 // Right part of banner
9918 if ($morehtmlright) {
9919 $ret .= '<div class="inline-block floatleft">' . $morehtmlright . '</div>';
9920 }
9921
9922 if ($previous_ref || $next_ref || $morehtml) {
9923 $ret .= '<div class="pagination paginationref"><ul class="right">';
9924 }
9925 if ($morehtml && getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2) {
9926 $ret .= '<!-- morehtml --><li class="noborder litext' . (($shownav && $previous_ref && $next_ref) ? ' clearbothonsmartphone' : '') . '">' . $morehtml . '</li>';
9927 }
9928 if ($shownav && ($previous_ref || $next_ref)) {
9929 $ret .= '<li class="pagination">' . $previous_ref . '</li>';
9930 $ret .= '<li class="pagination">' . $next_ref . '</li>';
9931 }
9932 if ($previous_ref || $next_ref || $morehtml) {
9933 $ret .= '</ul></div>';
9934 }
9935
9936 // Status
9937 $parameters = array('morehtmlstatus' => $morehtmlstatus);
9938 $reshook = $hookmanager->executeHooks('moreHtmlStatus', $parameters, $object); // Note that $action and $object may have been modified by hook
9939 if (empty($reshook)) {
9940 $morehtmlstatus .= $hookmanager->resPrint;
9941 } else {
9942 $morehtmlstatus = $hookmanager->resPrint;
9943 }
9944 if ($morehtmlstatus) {
9945 $ret .= '<div class="statusref">' . $morehtmlstatus . '</div>';
9946 }
9947
9948 $parameters = array();
9949 $reshook = $hookmanager->executeHooks('moreHtmlRef', $parameters, $object); // Note that $action and $object may have been modified by hook
9950 if (empty($reshook)) {
9951 $morehtmlref .= $hookmanager->resPrint;
9952 } elseif ($reshook > 0) {
9953 $morehtmlref = $hookmanager->resPrint;
9954 }
9955
9956 // Left part of banner
9957 if ($morehtmlleft) {
9958 if ($conf->browser->layout == 'phone') {
9959 $ret .= '<!-- morehtmlleft --><div class="floatleft">' . $morehtmlleft . '</div>';
9960 } else {
9961 $ret .= '<!-- morehtmlleft --><div class="inline-block floatleft">' . $morehtmlleft . '</div>';
9962 }
9963 }
9964
9965 //if ($conf->browser->layout == 'phone') $ret.='<div class="clearboth"></div>';
9966 $ret .= '<div class="inline-block floatleft valignmiddle maxwidth750 marginbottomonly refid' . (($shownav && ($previous_ref || $next_ref)) ? ' refidpadding' : '') . '">';
9967
9968 // For thirdparty, contact, user, member, the ref is the id, so we show something else
9969 if ($object->element == 'societe') {
9970 $ret .= dol_htmlentities($object->name);
9971
9972 // List of extra languages
9973 $arrayoflangcode = array();
9974 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
9975 $arrayoflangcode[] = getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE');
9976 }
9977
9978 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
9979 if (!is_object($extralanguages)) {
9980 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
9981 $extralanguages = new ExtraLanguages($this->db);
9982 }
9983 $extralanguages->fetch_name_extralanguages('societe');
9984
9985 if (!empty($extralanguages->attributes['societe']['name'])) {
9986 $object->fetchValuesForExtraLanguages();
9987
9988 $htmltext = '';
9989 // If there is extra languages
9990 foreach ($arrayoflangcode as $extralangcode) {
9991 $htmltext .= picto_from_langcode($extralangcode, 'class="pictoforlang paddingright"');
9992 if ($object->array_languages['name'][$extralangcode]) {
9993 $htmltext .= $object->array_languages['name'][$extralangcode];
9994 } else {
9995 $htmltext .= '<span class="opacitymedium">' . $langs->trans("SwitchInEditModeToAddTranslation") . '</span>';
9996 }
9997 }
9998 $ret .= '<!-- Show translations of name -->' . "\n";
9999 $ret .= $this->textwithpicto('', $htmltext, -1, 'language', 'opacitymedium paddingleft');
10000 }
10001 }
10002 } elseif ($object->element == 'member') {
10003 '@phan-var-force Adherent $object';
10004 $ret .= $object->ref . '<br>';
10005 $fullname = $object->getFullName($langs);
10006 if ($object->morphy == 'mor' && $object->societe) {
10007 $ret .= dol_htmlentities($object->societe) . ((!empty($fullname) && $object->societe != $fullname) ? ' (' . dol_htmlentities($fullname) . $addgendertxt . ')' : '');
10008 } else {
10009 $ret .= dol_htmlentities($fullname) . $addgendertxt . ((!empty($object->societe) && $object->societe != $fullname) ? ' (' . dol_htmlentities($object->societe) . ')' : '');
10010 }
10011 } elseif (in_array($object->element, array('contact', 'user'))) {
10012 $ret .= dol_htmlentities($object->getFullName($langs)) . $addgendertxt;
10013 } elseif ($object->element == 'usergroup') {
10014 $ret .= dol_htmlentities($object->name);
10015 } elseif (in_array($object->element, array('action', 'agenda'))) {
10016 '@phan-var-force ActionComm $object';
10017 $ret .= $object->ref . '<br>' . $object->label;
10018 } elseif (in_array($object->element, array('adherent_type'))) {
10019 $ret .= $object->label;
10020 } elseif ($object->element == 'ecm_directories') {
10021 $ret .= '';
10022 } elseif ($fieldref != 'none') {
10023 $ret .= dol_htmlentities(!empty($object->$fieldref) ? $object->$fieldref : "");
10024 }
10025 if ($morehtmlref) {
10026 // don't add a additional space, when "$morehtmlref" starts with a HTML div tag
10027 if (substr($morehtmlref, 0, 4) != '<div') {
10028 $ret .= ' ';
10029 }
10030
10031 $ret .= $morehtmlref;
10032 }
10033
10034 $ret .= '</div>';
10035
10036 $ret .= '</div><!-- End banner content -->';
10037
10038 return $ret;
10039 }
10040
10041
10050 public function showbarcode(&$object, $width = 100, $morecss = '')
10051 {
10052 global $conf;
10053
10054 //Check if barcode is filled in the card
10055 if (empty($object->barcode)) {
10056 return '';
10057 }
10058
10059 // Complete object if not complete
10060 if (empty($object->barcode_type_code) || empty($object->barcode_type_coder)) {
10061 // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
10062 $result = $object->fetch_barcode();
10063 //Check if fetch_barcode() failed
10064 if ($result < 1) {
10065 return '<!-- ErrorFetchBarcode -->';
10066 }
10067 }
10068
10069 // Barcode image @phan-suppress-next-line PhanUndeclaredProperty
10070 $url = DOL_URL_ROOT . '/viewimage.php?modulepart=barcode&generator=' . urlencode($object->barcode_type_coder) . '&code=' . urlencode($object->barcode) . '&encoding=' . urlencode($object->barcode_type_code);
10071 $out = '<!-- url barcode = ' . $url . ' -->';
10072 $out .= '<img src="' . $url . '"' . ($morecss ? ' class="' . $morecss . '"' : '') . '>';
10073
10074 return $out;
10075 }
10076
10094 public static function showphoto($modulepart, $object, $width = 100, $height = 0, $caneditfield = 0, $cssclass = 'photowithmargin', $imagesize = '', $addlinktofullsize = 1, $cache = 0, $forcecapture = '', $noexternsourceoverwrite = 0)
10095 {
10096 global $conf, $langs;
10097
10098 $entity = (empty($object->entity) ? $conf->entity : $object->entity);
10099 $id = (empty($object->id) ? $object->rowid : $object->id); // @phan-suppress-current-line PhanUndeclaredProperty (->rowid)
10100
10101 $dir = '';
10102 $file = '';
10103 $originalfile = '';
10104 $altfile = '';
10105 $email = '';
10106 $capture = '';
10107 if ($modulepart == 'societe') {
10108 $dir = $conf->societe->multidir_output[$entity];
10109 if (!empty($object->logo)) {
10110 if (dolIsAllowedForPreview($object->logo)) {
10111 if ((string) $imagesize == 'mini') {
10112 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_mini'); // getImageFileNameForSize include the thumbs
10113 } elseif ((string) $imagesize == 'small') {
10114 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_small');
10115 } else {
10116 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
10117 }
10118 $originalfile = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
10119 }
10120 }
10121 $email = $object->email;
10122 } elseif ($modulepart == 'contact') {
10123 $dir = $conf->societe->multidir_output[$entity] . '/contact';
10124 if (!empty($object->photo)) {
10125 if (dolIsAllowedForPreview($object->photo)) {
10126 if ((string) $imagesize == 'mini') {
10127 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10128 } elseif ((string) $imagesize == 'small') {
10129 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10130 } else {
10131 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
10132 }
10133 $originalfile = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
10134 }
10135 }
10136 $email = $object->email;
10137 $capture = 'user';
10138 } elseif ($modulepart == 'userphoto') {
10139 $dir = $conf->user->dir_output;
10140 if (!empty($object->photo)) {
10141 if (dolIsAllowedForPreview($object->photo)) {
10142 if ((string) $imagesize == 'mini') {
10143 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10144 } elseif ((string) $imagesize == 'small') {
10145 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10146 } else {
10147 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
10148 }
10149 $originalfile = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
10150 }
10151 }
10152 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
10153 $altfile = $object->id . ".jpg"; // For backward compatibility
10154 }
10155 $email = $object->email;
10156 $capture = 'user';
10157 } elseif ($modulepart == 'memberphoto') {
10158 $dir = $conf->adherent->dir_output;
10159 if (!empty($object->photo)) {
10160 if (dolIsAllowedForPreview($object->photo)) {
10161 if ((string) $imagesize == 'mini') {
10162 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10163 } elseif ((string) $imagesize == 'small') {
10164 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10165 } else {
10166 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
10167 }
10168 $originalfile = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
10169 }
10170 }
10171 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
10172 $altfile = $object->id . ".jpg"; // For backward compatibility
10173 }
10174 $email = $object->email;
10175 $capture = 'user';
10176 } else {
10177 // Generic case to show photos
10178 // TODO Implement this method in previous objects so we can always use this generic method.
10179 if ($modulepart != "unknown" && method_exists($object, 'getDataToShowPhoto')) {
10180 $tmpdata = $object->getDataToShowPhoto($modulepart, $imagesize);
10181
10182 $dir = $tmpdata['dir'];
10183 $file = $tmpdata['file'];
10184 $originalfile = $tmpdata['originalfile'];
10185 $altfile = $tmpdata['altfile'];
10186 $email = $tmpdata['email'];
10187 $capture = $tmpdata['capture'];
10188 }
10189 }
10190
10191 if ($forcecapture) {
10192 $capture = $forcecapture;
10193 }
10194
10195 $ret = '';
10196
10197 if ($dir) {
10198 if ($file && file_exists($dir . "/" . $file)) {
10199 if ($addlinktofullsize) {
10200 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
10201 if ($urladvanced) {
10202 $ret .= '<a href="' . $urladvanced . '">';
10203 } else {
10204 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
10205 }
10206 }
10207 $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 . '">';
10208 if ($addlinktofullsize) {
10209 $ret .= '</a>';
10210 }
10211 } elseif ($altfile && file_exists($dir . "/" . $altfile)) {
10212 if ($addlinktofullsize) {
10213 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
10214 if ($urladvanced) {
10215 $ret .= '<a href="' . $urladvanced . '">';
10216 } else {
10217 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
10218 }
10219 }
10220 $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 . '">';
10221 if ($addlinktofullsize) {
10222 $ret .= '</a>';
10223 }
10224 } else {
10225 $nophoto = '/public/theme/common/nophoto.png';
10226 $defaultimg = 'identicon'; // For gravatar
10227 if (in_array($modulepart, array('societe', 'userphoto', 'contact', 'memberphoto'))) { // For modules that need a special image when photo not found
10228 if ($modulepart == 'societe' || ($modulepart == 'memberphoto' && !empty($object->morphy) && strpos($object->morphy, 'mor') !== false)) {
10229 $nophoto = 'company';
10230 } else {
10231 $nophoto = '/public/theme/common/user_anonymous.png';
10232 if (!empty($object->gender) && $object->gender == 'man') {
10233 $nophoto = '/public/theme/common/user_man.png';
10234 }
10235 if (!empty($object->gender) && $object->gender == 'woman') {
10236 $nophoto = '/public/theme/common/user_woman.png';
10237 }
10238 }
10239 }
10240
10241 if (isModEnabled('gravatar') && $email && empty($noexternsourceoverwrite)) {
10242 // see https://gravatar.com/site/implement/images/php/
10243 $ret .= '<!-- Put link to gravatar -->';
10244 $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
10245 } else {
10246 if ($nophoto == 'company') {
10247 $ret .= '<div class="divforspanimg valignmiddle center photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . '>' . img_picto('', 'company') . '</div>';
10248 //$ret .= '<div class="difforspanimgright"></div>';
10249 } else {
10250 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . $nophoto . '">';
10251 }
10252 }
10253 }
10254
10255 if ($caneditfield) {
10256 if ($object->photo) {
10257 $ret .= "<br>\n";
10258 }
10259 $ret .= '<table class="nobordernopadding centpercent">';
10260 if ($object->photo) {
10261 $ret .= '<tr><td><input type="checkbox" class="flat photodelete" name="deletephoto" id="photodelete"> <label for="photodelete">' . $langs->trans("Delete") . '</label><br><br></td></tr>';
10262 }
10263 $ret .= '<tr><td class="tdoverflow">';
10264 $maxfilesizearray = getMaxFileSizeArray();
10265 $maxmin = $maxfilesizearray['maxmin'];
10266 if ($maxmin > 0) {
10267 $ret .= '<input type="hidden" name="MAX_FILE_SIZE" value="' . ($maxmin * 1024) . '">'; // MAX_FILE_SIZE must precede the field type=file
10268 }
10269 $ret .= '<input type="file" class="flat maxwidth200onsmartphone" name="photo" id="photoinput" accept="image/*"' . ($capture ? ' capture="' . $capture . '"' : '') . '>';
10270 $ret .= '</td></tr>';
10271 $ret .= '</table>';
10272 }
10273 }
10274
10275 return $ret;
10276 }
10277
10278 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
10279
10296 public function select_dolgroups($selected = 0, $htmlname = 'groupid', $show_empty = 0, $exclude = '', $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0', $multiple = false, $morecss = 'minwidth200')
10297 {
10298 // phpcs:enable
10299 global $conf, $user, $langs;
10300
10301 // Allow excluding groups
10302 $excludeGroups = null;
10303 if (is_array($exclude)) {
10304 $excludeGroups = implode(",", $exclude);
10305 }
10306 // Allow including groups
10307 $includeGroups = null;
10308 if (is_array($include)) {
10309 $includeGroups = implode(",", $include);
10310 }
10311
10312 if (!is_array($selected)) {
10313 $selected = array($selected);
10314 }
10315
10316 $out = '';
10317
10318 // Build sql to search groups
10319 $sql = "SELECT ug.rowid, ug.nom as name";
10320 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10321 $sql .= ", e.label";
10322 }
10323 $sql .= " FROM " . $this->db->prefix() . "usergroup as ug ";
10324 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10325 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid=ug.entity";
10326 if ($force_entity) {
10327 $sql .= " WHERE ug.entity IN (0, " . $force_entity . ")";
10328 } else {
10329 $sql .= " WHERE ug.entity IS NOT NULL";
10330 }
10331 } else {
10332 $sql .= " WHERE ug.entity IN (0, " . $conf->entity . ")";
10333 }
10334 if (is_array($exclude) && $excludeGroups) {
10335 $sql .= " AND ug.rowid NOT IN (" . $this->db->sanitize($excludeGroups) . ")";
10336 }
10337 if (is_array($include) && $includeGroups) {
10338 $sql .= " AND ug.rowid IN (" . $this->db->sanitize($includeGroups) . ")";
10339 }
10340 $sql .= " ORDER BY ug.nom ASC";
10341
10342 dol_syslog(get_class($this) . "::select_dolgroups", LOG_DEBUG);
10343 $resql = $this->db->query($sql);
10344 if ($resql) {
10345 // Enhance with select2
10346 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10347
10348 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
10349
10350 $num = $this->db->num_rows($resql);
10351 $i = 0;
10352 if ($num) {
10353 if ($show_empty && !$multiple) {
10354 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
10355 }
10356
10357 while ($i < $num) {
10358 $obj = $this->db->fetch_object($resql);
10359 $disableline = 0;
10360 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
10361 $disableline = 1;
10362 }
10363
10364 $label = $obj->name;
10365 $labelhtml = $obj->name;
10366 if (isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1) {
10367 $label .= " (" . $obj->label . ")";
10368 $labelhtml .= ' <span class="opacitymedium">(' . $obj->label . ')</span>';
10369 }
10370
10371 $out .= '<option value="' . $obj->rowid . '"';
10372 if ($disableline) {
10373 $out .= ' disabled';
10374 }
10375 if ((isset($selected[0]) && is_object($selected[0]) && $selected[0]->id == $obj->rowid)
10376 || ((!isset($selected[0]) || !is_object($selected[0])) && !empty($selected) && in_array($obj->rowid, $selected))) {
10377 $out .= ' selected';
10378 }
10379 $out .= ' data-html="'.dol_escape_htmltag($labelhtml).'"';
10380 $out .= '>';
10381 $out .= $label;
10382 $out .= '</option>';
10383 $i++;
10384 }
10385 } else {
10386 if ($show_empty) {
10387 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '></option>' . "\n";
10388 }
10389 $out .= '<option value="" disabled>' . $langs->trans("NoUserGroupDefined") . '</option>';
10390 }
10391 $out .= '</select>';
10392
10393 $out .= ajax_combobox($htmlname);
10394 } else {
10395 dol_print_error($this->db);
10396 }
10397
10398 return $out;
10399 }
10400
10401
10408 public function showFilterButtons($pos = '')
10409 {
10410 $out = '<div class="nowraponall">';
10411 $out .= '<button type="submit" class="liste_titre button_search reposition" name="button_search_x" value="x"><span class="fas fa-search"></span></button>';
10412 $out .= '<button type="submit" class="liste_titre button_removefilter reposition" name="button_removefilter_x" value="x"><span class="fas fa-times"></span></button>';
10413 $out .= '</div>';
10414
10415 return $out;
10416 }
10417
10426 public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10427 {
10428 global $conf;
10429
10430 $out = '';
10431
10432 if (!empty($conf->use_javascript_ajax)) {
10433 $out .= '<div class="inline-block checkallactions"><input type="checkbox" id="' . $cssclass . 's" name="' . $cssclass . 's" class="checkallactions"></div>';
10434 }
10435 $out .= '<script nonce="' . getNonce() . '">
10436 $(document).ready(function() {
10437 $("#' . $cssclass . 's").click(function() {
10438 if($(this).is(\':checked\')){
10439 console.log("We check all ' . $cssclass . ' and trigger the change method");
10440 $(".' . $cssclass . '").prop(\'checked\', true).trigger(\'change\');
10441 }
10442 else
10443 {
10444 console.log("We uncheck all");
10445 $(".' . $cssclass . '").prop(\'checked\', false).trigger(\'change\');
10446 }' . "\n";
10447 if ($calljsfunction) {
10448 $out .= 'if (typeof initCheckForSelect == \'function\') { initCheckForSelect(0, "' . $massactionname . '", "' . $cssclass . '"); } else { console.log("No function initCheckForSelect found. Call won\'t be done."); }';
10449 }
10450 $out .= ' });
10451 $(".' . $cssclass . '").change(function() {
10452 $(this).closest("tr").toggleClass("highlight", this.checked);
10453 });
10454 });
10455 </script>';
10456
10457 return $out;
10458 }
10459
10469 public function showFilterAndCheckAddButtons($addcheckuncheckall = 0, $cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10470 {
10471 $out = $this->showFilterButtons();
10472 if ($addcheckuncheckall) {
10473 $out .= $this->showCheckAddButtons($cssclass, $calljsfunction, $massactionname);
10474 }
10475 return $out;
10476 }
10477
10491 public function selectExpenseCategories($selected = '', $htmlname = 'fk_c_exp_tax_cat', $useempty = 0, $excludeid = array(), $target = '', $default_selected = 0, $params = array(), $info_admin = 1)
10492 {
10493 global $langs, $user;
10494
10495 $out = '';
10496 $sql = "SELECT rowid, label FROM " . $this->db->prefix() . "c_exp_tax_cat WHERE active = 1";
10497 $sql .= " AND entity IN (0," . getEntity('exp_tax_cat') . ")";
10498 if (!empty($excludeid)) {
10499 $sql .= " AND rowid NOT IN (" . $this->db->sanitize(implode(',', $excludeid)) . ")";
10500 }
10501 $sql .= " ORDER BY label";
10502
10503 $resql = $this->db->query($sql);
10504 if ($resql) {
10505 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp maxwidth200">';
10506 if ($useempty) {
10507 $out .= '<option value="0">&nbsp;</option>';
10508 }
10509
10510 while ($obj = $this->db->fetch_object($resql)) {
10511 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . $langs->trans($obj->label) . '</option>';
10512 }
10513 $out .= '</select>';
10514 $out .= ajax_combobox('select_' . $htmlname);
10515
10516 if (!empty($htmlname) && $user->admin && $info_admin) {
10517 $out .= ' ' . info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
10518 }
10519
10520 if (!empty($target)) {
10521 $sql = "SELECT c.id FROM " . $this->db->prefix() . "c_type_fees as c WHERE c.code = 'EX_KME' AND c.active = 1";
10522 $resql = $this->db->query($sql);
10523 if ($resql) {
10524 if ($this->db->num_rows($resql) > 0) {
10525 $obj = $this->db->fetch_object($resql);
10526 $out .= '<script nonce="' . getNonce() . '">
10527 $(function() {
10528 $("select[name=' . $target . ']").on("change", function() {
10529 var current_val = $(this).val();
10530 if (current_val == ' . $obj->id . ') {';
10531 if (!empty($default_selected) || !empty($selected)) {
10532 $out .= '$("select[name=' . $htmlname . ']").val("' . ($default_selected > 0 ? $default_selected : $selected) . '");';
10533 }
10534
10535 $out .= '
10536 $("select[name=' . $htmlname . ']").change();
10537 }
10538 });
10539
10540 $("select[name=' . $htmlname . ']").change(function() {
10541
10542 if ($("select[name=' . $target . ']").val() == ' . $obj->id . ') {
10543 // get price of kilometer to fill the unit price
10544 $.ajax({
10545 method: "POST",
10546 dataType: "json",
10547 data: { fk_c_exp_tax_cat: $(this).val(), token: \'' . currentToken() . '\' },
10548 url: "' . (DOL_URL_ROOT . '/expensereport/ajax/ajaxik.php?' . implode('&', $params)) . '",
10549 }).done(function( data, textStatus, jqXHR ) {
10550 console.log(data);
10551 if (typeof data.up != "undefined") {
10552 $("input[name=value_unit]").val(data.up);
10553 $("select[name=' . $htmlname . ']").attr("title", data.title);
10554 } else {
10555 $("input[name=value_unit]").val("");
10556 $("select[name=' . $htmlname . ']").attr("title", "");
10557 }
10558 });
10559 }
10560 });
10561 });
10562 </script>';
10563 }
10564 }
10565 }
10566 } else {
10567 dol_print_error($this->db);
10568 }
10569
10570 return $out;
10571 }
10572
10581 public function selectExpenseRanges($selected = '', $htmlname = 'fk_range', $useempty = 0)
10582 {
10583 global $conf, $langs;
10584
10585 $out = '';
10586 $sql = "SELECT rowid, range_ik FROM " . $this->db->prefix() . "c_exp_tax_range";
10587 $sql .= " WHERE entity = " . $conf->entity . " AND active = 1";
10588
10589 $resql = $this->db->query($sql);
10590 if ($resql) {
10591 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10592 if ($useempty) {
10593 $out .= '<option value="0"></option>';
10594 }
10595
10596 while ($obj = $this->db->fetch_object($resql)) {
10597 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . price($obj->range_ik, 0, $langs, 1, 0) . '</option>';
10598 }
10599 $out .= '</select>';
10600 } else {
10601 dol_print_error($this->db);
10602 }
10603
10604 return $out;
10605 }
10606
10617 public function selectExpense($selected = '', $htmlname = 'fk_c_type_fees', $useempty = 0, $allchoice = 1, $useid = 0)
10618 {
10619 global $langs;
10620
10621 $out = '';
10622 $sql = "SELECT id, code, label";
10623 $sql .= " FROM ".$this->db->prefix()."c_type_fees";
10624 $sql .= " WHERE active = 1";
10625
10626 $resql = $this->db->query($sql);
10627 if ($resql) {
10628 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10629 if ($useempty) {
10630 $out .= '<option value="0"></option>';
10631 }
10632 if ($allchoice) {
10633 $out .= '<option value="-1">' . $langs->trans('AllExpenseReport') . '</option>';
10634 }
10635
10636 $field = 'code';
10637 if ($useid) {
10638 $field = 'id';
10639 }
10640
10641 while ($obj = $this->db->fetch_object($resql)) {
10642 $key = $langs->trans($obj->code);
10643 $out .= '<option ' . ($selected == $obj->{$field} ? 'selected="selected"' : '') . ' value="' . $obj->{$field} . '">' . ($key != $obj->code ? $key : $obj->label) . '</option>';
10644 }
10645 $out .= '</select>';
10646
10647 $out .= ajax_combobox('select_'.$htmlname);
10648 } else {
10649 dol_print_error($this->db);
10650 }
10651
10652 return $out;
10653 }
10654
10673 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)
10674 {
10675 global $user, $conf, $langs;
10676
10677 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
10678
10679 if (is_null($usertofilter)) {
10680 $usertofilter = $user;
10681 }
10682
10683 $out = '';
10684
10685 $hideunselectables = false;
10686 if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
10687 $hideunselectables = true;
10688 }
10689
10690 if (empty($projectsListId)) {
10691 if (!$usertofilter->hasRight('projet', 'all', 'lire')) {
10692 $projectstatic = new Project($this->db);
10693 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertofilter, 0, 1);
10694 }
10695 }
10696
10697 // Search all projects
10698 $sql = "SELECT f.rowid, f.ref as fref, 'nolabel' as flabel, p.rowid as pid, f.ref,
10699 p.title, p.fk_soc, p.fk_statut, p.public,";
10700 $sql .= ' s.nom as name';
10701 $sql .= ' FROM ' . $this->db->prefix() . 'projet as p';
10702 $sql .= ' LEFT JOIN ' . $this->db->prefix() . 'societe as s ON s.rowid = p.fk_soc,';
10703 $sql .= ' ' . $this->db->prefix() . 'facture as f';
10704 $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
10705 $sql .= " AND f.fk_projet = p.rowid AND f.fk_statut=0"; //Brouillons seulement
10706 //if ($projectsListId) $sql.= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")";
10707 //if ($socid == 0) $sql.= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
10708 //if ($socid > 0) $sql.= " AND (p.fk_soc=".((int) $socid)." OR p.fk_soc IS NULL)";
10709 $sql .= " ORDER BY p.ref, f.ref ASC";
10710
10711 $resql = $this->db->query($sql);
10712 if ($resql) {
10713 // Use select2 selector
10714 if (!empty($conf->use_javascript_ajax)) {
10715 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10716 $comboenhancement = ajax_combobox($htmlname, array(), 0, $forcefocus);
10717 $out .= $comboenhancement;
10718 $morecss = 'minwidth200imp maxwidth500';
10719 }
10720
10721 if (empty($option_only)) {
10722 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10723 }
10724 if (!empty($show_empty)) {
10725 $out .= '<option value="0" class="optiongrey">';
10726 if (!is_numeric($show_empty)) {
10727 $out .= $show_empty;
10728 } else {
10729 $out .= '&nbsp;';
10730 }
10731 $out .= '</option>';
10732 }
10733 $num = $this->db->num_rows($resql);
10734 $i = 0;
10735 if ($num) {
10736 while ($i < $num) {
10737 $obj = $this->db->fetch_object($resql);
10738 // 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.
10739 if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$usertofilter->hasRight('societe', 'lire')) {
10740 // Do nothing
10741 } else {
10742 if ($discard_closed == 1 && $obj->fk_statut == Project::STATUS_CLOSED) {
10743 $i++;
10744 continue;
10745 }
10746
10747 $labeltoshow = '';
10748
10749 if ($showproject == 'all') {
10750 $labeltoshow .= dol_trunc($obj->ref, 18); // Invoice ref
10751 if ($obj->name) {
10752 $labeltoshow .= ' - ' . $obj->name; // Soc name
10753 }
10754
10755 $disabled = 0;
10756 if ($obj->fk_statut == Project::STATUS_DRAFT) {
10757 $disabled = 1;
10758 $labeltoshow .= ' - ' . $langs->trans("Draft");
10759 } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
10760 if ($discard_closed == 2) {
10761 $disabled = 1;
10762 }
10763 $labeltoshow .= ' - ' . $langs->trans("Closed");
10764 } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
10765 $disabled = 1;
10766 $labeltoshow .= ' - ' . $langs->trans("LinkedToAnotherCompany");
10767 }
10768 }
10769
10770 if (!empty($selected) && $selected == $obj->rowid) {
10771 $out .= '<option value="' . $obj->rowid . '" selected';
10772 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10773 $out .= '>' . $labeltoshow . '</option>';
10774 } else {
10775 if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
10776 $resultat = '';
10777 } else {
10778 $resultat = '<option value="' . $obj->rowid . '"';
10779 if ($disabled) {
10780 $resultat .= ' disabled';
10781 }
10782 //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
10783 //else $labeltoshow.=' ('.$langs->trans("Private").')';
10784 $resultat .= '>';
10785 $resultat .= $labeltoshow;
10786 $resultat .= '</option>';
10787 }
10788 $out .= $resultat;
10789 }
10790 }
10791 $i++;
10792 }
10793 }
10794 if (empty($option_only)) {
10795 $out .= '</select>';
10796 }
10797
10798 $this->db->free($resql);
10799
10800 return $out;
10801 } else {
10802 dol_print_error($this->db);
10803 return '';
10804 }
10805 }
10806
10820 public function selectInvoiceRec($selected = '', $htmlname = 'facrecid', $maxlength = 24, $option_only = 0, $show_empty = '1', $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500')
10821 {
10822 global $conf, $langs;
10823
10824 $out = '';
10825
10826 dol_syslog('FactureRec::fetch', LOG_DEBUG);
10827
10828 $sql = 'SELECT f.rowid, f.entity, f.titre as title, f.suspended, f.fk_soc';
10829 //$sql.= ', el.fk_source';
10830 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_rec as f';
10831 $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
10832 $sql .= " ORDER BY f.titre ASC";
10833
10834 $resql = $this->db->query($sql);
10835 if ($resql) {
10836 // Use select2 selector
10837 if (!empty($conf->use_javascript_ajax)) {
10838 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10839 $comboenhancement = ajax_combobox($htmlname, array(), 0, $forcefocus);
10840 $out .= $comboenhancement;
10841 $morecss = 'minwidth200imp maxwidth500';
10842 }
10843
10844 if (empty($option_only)) {
10845 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10846 }
10847 if (!empty($show_empty)) {
10848 $out .= '<option value="0" class="optiongrey">';
10849 if (!is_numeric($show_empty)) {
10850 $out .= $show_empty;
10851 } else {
10852 $out .= '&nbsp;';
10853 }
10854 $out .= '</option>';
10855 }
10856 $num = $this->db->num_rows($resql);
10857 if ($num) {
10858 while ($obj = $this->db->fetch_object($resql)) {
10859 $labeltoshow = dol_trunc($obj->title, 18); // Invoice ref
10860
10861 $disabled = 0;
10862 if (!empty($obj->suspended)) {
10863 $disabled = 1;
10864 $labeltoshow .= ' - ' . $langs->trans("Closed");
10865 }
10866
10867
10868 if (!empty($selected) && $selected == $obj->rowid) {
10869 $out .= '<option value="' . $obj->rowid . '" selected';
10870 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10871 $out .= '>' . $labeltoshow . '</option>';
10872 } else {
10873 if ($disabled && ($selected != $obj->rowid)) {
10874 $resultat = '';
10875 } else {
10876 $resultat = '<option value="' . $obj->rowid . '"';
10877 if ($disabled) {
10878 $resultat .= ' disabled';
10879 }
10880 $resultat .= '>';
10881 $resultat .= $labeltoshow;
10882 $resultat .= '</option>';
10883 }
10884 $out .= $resultat;
10885 }
10886 }
10887 }
10888 if (empty($option_only)) {
10889 $out .= '</select>';
10890 }
10891
10892 print $out;
10893
10894 $this->db->free($resql);
10895 return $num;
10896 } else {
10897 $this->errors[] = $this->db->lasterror;
10898 return -1;
10899 }
10900 }
10901
10911 public function searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput = array(), $search_component_params_hidden = '')
10912 {
10913 global $langs;
10914
10915 if ($search_component_params_hidden != '' && !preg_match('/^\‍(.*\‍)$/', $search_component_params_hidden)) { // If $search_component_params_hidden does not start and end with ()
10916 $search_component_params_hidden = '(' . $search_component_params_hidden . ')';
10917 }
10918
10919 $ret = '';
10920
10921 $ret .= '<div class="divadvancedsearchfieldcomp centpercent inline-block">';
10922 $ret .= '<a href="#" class="dropdownsearch-toggle unsetcolor">';
10923 $ret .= '<span class="fas fa-filter linkobject boxfilter paddingright pictofixedwidth" title="' . dol_escape_htmltag($langs->trans("Filters")) . '" id="idsubimgproductdistribution"></span>';
10924 $ret .= '</a>';
10925
10926 $ret .= '<div class="divadvancedsearchfieldcompinput inline-block minwidth500 maxwidth300onsmartphone">';
10927
10928 // Show select fields as tags.
10929 $ret .= '<div id="divsearch_component_params" name="divsearch_component_params" class="noborderbottom search_component_params inline-block valignmiddle">';
10930
10931 if ($search_component_params_hidden) {
10932 // Split the criteria on each AND
10933 //var_dump($search_component_params_hidden);
10934
10935 $arrayofandtags = dolForgeExplodeAnd($search_component_params_hidden);
10936
10937 // $arrayofandtags is now array( '...' , '...', ...)
10938 // Show each AND part
10939 foreach ($arrayofandtags as $tmpkey => $tmpval) {
10940 $errormessage = '';
10941 $searchtags = forgeSQLFromUniversalSearchCriteria($tmpval, $errormessage, 1, 1);
10942 if ($errormessage) {
10943 $this->error = 'ERROR in parsing search string: '.$errormessage;
10944 }
10945 // Remove first and last parenthesis but only if first is the opening and last the closing of the same group
10946 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
10947 $searchtags = removeGlobalParenthesis($searchtags);
10948
10949 $ret .= '<span class="marginleftonlyshort valignmiddle tagsearch" data-ufilterid="'.($tmpkey + 1).'" data-ufilter="'.dol_escape_htmltag($tmpval).'">';
10950 $ret .= '<span class="tagsearchdelete select2-selection__choice__remove" data-ufilterid="'.($tmpkey + 1).'">x</span> ';
10951 $ret .= dol_escape_htmltag($searchtags);
10952 $ret .= '</span>';
10953 }
10954 }
10955
10956 //$ret .= '<button type="submit" class="liste_titre button_search paddingleftonly" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
10957
10958 //$ret .= search_component_params
10959 //$texttoshow = '<div class="opacitymedium inline-block search_component_searchtext">'.$langs->trans("Search").'</div>';
10960 //$ret .= '<div class="search_component inline-block valignmiddle">'.$texttoshow.'</div>';
10961
10962 $show_search_component_params_hidden = 1;
10963 if ($show_search_component_params_hidden) {
10964 $ret .= '<input type="hidden" name="show_search_component_params_hidden" value="1">';
10965 }
10966 $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%')) -->";
10967 $ret .= '<input type="hidden" id="search_component_params_hidden" name="search_component_params_hidden" value="' . dol_escape_htmltag($search_component_params_hidden) . '">';
10968 // $ret .= "<!-- sql= ".forgeSQLFromUniversalSearchCriteria($search_component_params_hidden, $errormessage)." -->";
10969
10970 // For compatibility with forms that show themself the search criteria in addition of this component, we output these fields
10971 foreach ($arrayofcriterias as $criteria) {
10972 foreach ($criteria as $criteriafamilykey => $criteriafamilyval) {
10973 if (in_array('search_' . $criteriafamilykey, $arrayofinputfieldsalreadyoutput)) {
10974 continue;
10975 }
10976 if (in_array($criteriafamilykey, array('rowid', 'ref_ext', 'entity', 'extraparams'))) {
10977 continue;
10978 }
10979 if (in_array($criteriafamilyval['type'], array('date', 'datetime', 'timestamp'))) {
10980 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_start">';
10981 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startyear">';
10982 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startmonth">';
10983 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startday">';
10984 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_end">';
10985 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endyear">';
10986 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endmonth">';
10987 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endday">';
10988 } else {
10989 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '">';
10990 }
10991 }
10992 }
10993
10994 $ret .= '</div>';
10995
10996 $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";
10997 $ret .= '<input type="text" placeholder="' . $langs->trans("Filters") . '" id="search_component_params_input" name="search_component_params_input" class="noborderbottom search_component_input" value="">';
10998
10999 $ret .= '</div>';
11000 $ret .= '</div>';
11001
11002 $ret .= '<script>
11003 jQuery(".tagsearchdelete").click(function(e) {
11004 var filterid = $(this).parents().attr("data-ufilterid");
11005 console.log("We click to delete the criteria nb "+filterid);
11006
11007 // Regenerate the search_component_params_hidden with all data-ufilter except the one to delete, and post the page
11008 var newparamstring = \'\';
11009 $(\'.tagsearch\').each(function(index, element) {
11010 tmpfilterid = $(this).attr("data-ufilterid");
11011 if (tmpfilterid != filterid) {
11012 // We keep this criteria
11013 if (newparamstring == \'\') {
11014 newparamstring = $(this).attr("data-ufilter");
11015 } else {
11016 newparamstring = newparamstring + \' AND \' + $(this).attr("data-ufilter");
11017 }
11018 }
11019 });
11020 console.log("newparamstring = "+newparamstring);
11021
11022 jQuery("#search_component_params_hidden").val(newparamstring);
11023
11024 // We repost the form
11025 $(this).closest(\'form\').submit();
11026 });
11027
11028 jQuery("#search_component_params_input").keydown(function(e) {
11029 console.log("We press a key on the filter field that is "+jQuery("#search_component_params_input").val());
11030 console.log(e.which);
11031 if (jQuery("#search_component_params_input").val() == "" && e.which == 8) {
11032 /* We click on back when the input field is already empty */
11033 event.preventDefault();
11034 jQuery("#divsearch_component_params .tagsearch").last().remove();
11035 /* Regenerate content of search_component_params_hidden from remaining .tagsearch */
11036 var s = "";
11037 jQuery("#divsearch_component_params .tagsearch").each(function( index ) {
11038 if (s != "") {
11039 s = s + " AND ";
11040 }
11041 s = s + $(this).attr("data-ufilter");
11042 });
11043 console.log("New value for search_component_params_hidden = "+s);
11044 jQuery("#search_component_params_hidden").val(s);
11045 }
11046 });
11047
11048 </script>
11049 ';
11050
11051 return $ret;
11052 }
11053
11063 public function selectModelMail($prefix, $modelType = '', $default = 0, $addjscombo = 0)
11064 {
11065 global $langs, $user;
11066
11067 $retstring = '';
11068
11069 $TModels = array();
11070
11071 include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
11072 $formmail = new FormMail($this->db);
11073 $result = $formmail->fetchAllEMailTemplate($modelType, $user, $langs);
11074
11075 if ($default) {
11076 $TModels[0] = $langs->trans('DefaultMailModel');
11077 }
11078 if ($result > 0) {
11079 foreach ($formmail->lines_model as $model) {
11080 $TModels[$model->id] = $model->label;
11081 }
11082 }
11083
11084 $retstring .= '<select class="flat" id="select_' . $prefix . 'model_mail" name="' . $prefix . 'model_mail">';
11085
11086 foreach ($TModels as $id_model => $label_model) {
11087 $retstring .= '<option value="' . $id_model . '"';
11088 $retstring .= ">" . $label_model . "</option>";
11089 }
11090
11091 $retstring .= "</select>";
11092
11093 if ($addjscombo) {
11094 $retstring .= ajax_combobox('select_' . $prefix . 'model_mail');
11095 }
11096
11097 return $retstring;
11098 }
11099
11111 public function buttonsSaveCancel($save_label = 'Save', $cancel_label = 'Cancel', $morebuttons = array(), $withoutdiv = false, $morecss = '', $dol_openinpopup = '')
11112 {
11113 global $langs;
11114
11115 $buttons = array();
11116
11117 $save = array(
11118 'name' => 'save',
11119 'label_key' => $save_label,
11120 );
11121
11122 if ($save_label == 'Create' || $save_label == 'Add') {
11123 $save['name'] = 'add';
11124 } elseif ($save_label == 'Modify') {
11125 $save['name'] = 'edit';
11126 }
11127
11128 $cancel = array(
11129 'name' => 'cancel',
11130 'label_key' => 'Cancel',
11131 );
11132
11133 !empty($save_label) ? $buttons[] = $save : '';
11134
11135 if (!empty($morebuttons)) {
11136 $buttons[] = $morebuttons;
11137 }
11138
11139 !empty($cancel_label) ? $buttons[] = $cancel : '';
11140
11141 $retstring = $withoutdiv ? '' : '<div class="center">';
11142
11143 foreach ($buttons as $button) {
11144 $addclass = empty($button['addclass']) ? '' : $button['addclass'];
11145 $retstring .= '<input type="submit" class="button button-' . $button['name'] . ($morecss ? ' ' . $morecss : '') . ' ' . $addclass . '" name="' . $button['name'] . '" value="' . dol_escape_htmltag($langs->trans($button['label_key'])) . '">';
11146 }
11147 $retstring .= $withoutdiv ? '' : '</div>';
11148
11149 if ($dol_openinpopup) {
11150 $retstring .= '<!-- buttons are shown into a $dol_openinpopup=' . dol_escape_htmltag($dol_openinpopup) . ' context, so we enable the close of dialog on cancel -->' . "\n";
11151 $retstring .= '<script nonce="' . getNonce() . '">';
11152 $retstring .= 'jQuery(".button-cancel").click(function(e) {
11153 e.preventDefault(); console.log(\'We click on cancel in iframe popup ' . dol_escape_js($dol_openinpopup) . '\');
11154 window.parent.jQuery(\'#idfordialog' . dol_escape_js($dol_openinpopup) . '\').dialog(\'close\');
11155 });';
11156 $retstring .= '</script>';
11157 }
11158
11159 return $retstring;
11160 }
11161
11162
11163 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
11164
11171 {
11172 // phpcs:enable
11173 global $langs;
11174
11175 $num = count($this->cache_invoice_subtype);
11176 if ($num > 0) {
11177 return 0; // Cache already loaded
11178 }
11179
11180 dol_syslog(__METHOD__, LOG_DEBUG);
11181
11182 $sql = "SELECT rowid, code, label as label";
11183 $sql .= " FROM " . MAIN_DB_PREFIX . 'c_invoice_subtype';
11184 $sql .= " WHERE active = 1";
11185
11186 $resql = $this->db->query($sql);
11187 if ($resql) {
11188 $num = $this->db->num_rows($resql);
11189 $i = 0;
11190 while ($i < $num) {
11191 $obj = $this->db->fetch_object($resql);
11192
11193 // If translation exists, we use it, otherwise we take the default wording
11194 $label = ($langs->trans("InvoiceSubtype" . $obj->rowid) != "InvoiceSubtype" . $obj->rowid) ? $langs->trans("InvoiceSubtype" . $obj->rowid) : (($obj->label != '-') ? $obj->label : '');
11195 $this->cache_invoice_subtype[$obj->rowid]['rowid'] = $obj->rowid;
11196 $this->cache_invoice_subtype[$obj->rowid]['code'] = $obj->code;
11197 $this->cache_invoice_subtype[$obj->rowid]['label'] = $label;
11198 $i++;
11199 }
11200
11201 $this->cache_invoice_subtype = dol_sort_array($this->cache_invoice_subtype, 'code', 'asc', 0, 0, 1);
11202
11203 return $num;
11204 } else {
11205 dol_print_error($this->db);
11206 return -1;
11207 }
11208 }
11209
11210
11221 public function getSelectInvoiceSubtype($selected = 0, $htmlname = 'subtypeid', $addempty = 0, $noinfoadmin = 0, $morecss = '')
11222 {
11223 global $langs, $user;
11224
11225 $out = '';
11226 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
11227
11229
11230 $out .= '<select id="' . $htmlname . '" class="flat selectsubtype' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
11231 if ($addempty) {
11232 $out .= '<option value="0">&nbsp;</option>';
11233 }
11234
11235 foreach ($this->cache_invoice_subtype as $rowid => $subtype) {
11236 $label = $subtype['label'];
11237 $out .= '<option value="' . $subtype['rowid'] . '"';
11238 if ($selected == $subtype['rowid']) {
11239 $out .= ' selected="selected"';
11240 }
11241 $out .= '>';
11242 $out .= $label;
11243 $out .= '</option>';
11244 }
11245
11246 $out .= '</select>';
11247 if ($user->admin && empty($noinfoadmin)) {
11248 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
11249 }
11250 $out .= ajax_combobox($htmlname);
11251
11252 return $out;
11253 }
11254}
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...
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_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
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.