dolibarr 21.0.0-alpha
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 * Copyright (C) 2024 William Mead <william.mead@manchenumerique.fr>
28 *
29 * This program is free software; you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by
31 * the Free Software Foundation; either version 3 of the License, or
32 * (at your option) any later version.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program. If not, see <https://www.gnu.org/licenses/>.
41 */
42
56class Form
57{
61 public $db;
62
66 public $error = '';
67
71 public $errors = array();
72
73 // Some properties used to return data by some methods
75 public $result;
77 public $num;
78
79 // Cache arrays
80 public $cache_types_paiements = array();
81 public $cache_conditions_paiements = array();
82 public $cache_transport_mode = array();
83 public $cache_availability = array();
84 public $cache_demand_reason = array();
85 public $cache_types_fees = array();
86 public $cache_vatrates = array();
87 public $cache_invoice_subtype = array();
88
89
95 public function __construct($db)
96 {
97 $this->db = $db;
98 }
99
116 public function editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata = 'string', $moreparam = '', $fieldrequired = 0, $notabletag = 0, $paramid = 'id', $help = '')
117 {
118 global $langs;
119
120 $ret = '';
121
122 // TODO change for compatibility
123 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;/', $typeofdata)) {
124 if (!empty($perm)) {
125 $tmp = explode(':', $typeofdata);
126 $ret .= '<div class="editkey_' . $tmp[0] . (!empty($tmp[1]) ? ' ' . $tmp[1] : '') . '" id="' . $htmlname . '">';
127 if ($fieldrequired) {
128 $ret .= '<span class="fieldrequired">';
129 }
130 if ($help) {
131 $ret .= $this->textwithpicto($langs->trans($text), $help);
132 } else {
133 $ret .= $langs->trans($text);
134 }
135 if ($fieldrequired) {
136 $ret .= '</span>';
137 }
138 $ret .= '</div>' . "\n";
139 } else {
140 if ($fieldrequired) {
141 $ret .= '<span class="fieldrequired">';
142 }
143 if ($help) {
144 $ret .= $this->textwithpicto($langs->trans($text), $help);
145 } else {
146 $ret .= $langs->trans($text);
147 }
148 if ($fieldrequired) {
149 $ret .= '</span>';
150 }
151 }
152 } else {
153 if (empty($notabletag) && $perm) {
154 $ret .= '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
155 }
156 if ($fieldrequired) {
157 $ret .= '<span class="fieldrequired">';
158 }
159 if ($help) {
160 $ret .= $this->textwithpicto($langs->trans($text), $help);
161 } else {
162 $ret .= $langs->trans($text);
163 }
164 if ($fieldrequired) {
165 $ret .= '</span>';
166 }
167 if (!empty($notabletag)) {
168 $ret .= ' ';
169 }
170 if (empty($notabletag) && $perm) {
171 $ret .= '</td>';
172 }
173 if (empty($notabletag) && $perm) {
174 $ret .= '<td class="right">';
175 }
176 if ($htmlname && GETPOST('action', 'aZ09') != 'edit' . $htmlname && $perm) {
177 $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>';
178 }
179 if (!empty($notabletag) && $notabletag == 1) {
180 if ($text) {
181 $ret .= ' : ';
182 } else {
183 $ret .= ' ';
184 }
185 }
186 if (!empty($notabletag) && $notabletag == 3) {
187 $ret .= ' ';
188 }
189 if (empty($notabletag) && $perm) {
190 $ret .= '</td>';
191 }
192 if (empty($notabletag) && $perm) {
193 $ret .= '</tr></table>';
194 }
195 }
196
197 return $ret;
198 }
199
223 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 = '')
224 {
225 global $conf, $langs;
226
227 $ret = '';
228
229 // Check parameters
230 if (empty($typeofdata)) {
231 return 'ErrorBadParameter typeofdata is empty';
232 }
233 // Clean parameter $typeofdata
234 if ($typeofdata == 'datetime') {
235 $typeofdata = 'dayhour';
236 }
237 $reg = array();
238 if (preg_match('/^(\w+)\‍((\d+)\‍)$/', $typeofdata, $reg)) {
239 if ($reg[1] == 'varchar') {
240 $typeofdata = 'string';
241 } elseif ($reg[1] == 'int') {
242 $typeofdata = 'numeric';
243 } else {
244 return 'ErrorBadParameter ' . $typeofdata;
245 }
246 }
247
248 // When option to edit inline is activated
249 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;|day|datepicker|dayhour|datehourpicker/', $typeofdata)) { // TODO add jquery timepicker and support select
250 $ret .= $this->editInPlace($object, $value, $htmlname, ($perm ? 1 : 0), $typeofdata, $editvalue, $extObject, $custommsg);
251 } else {
252 if ($editaction == '') {
253 $editaction = GETPOST('action', 'aZ09');
254 }
255 $editmode = ($editaction == 'edit' . $htmlname);
256 if ($editmode) { // edit mode
257 $ret .= "\n";
258 $ret .= '<form method="post" action="' . $_SERVER["PHP_SELF"] . ($moreparam ? '?' . $moreparam : '') . '">';
259 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
260 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
261 $ret .= '<input type="hidden" name="' . $paramid . '" value="' . $object->id . '">';
262 if (empty($notabletag)) {
263 $ret .= '<table class="nobordernopadding centpercent">';
264 }
265 if (empty($notabletag)) {
266 $ret .= '<tr><td>';
267 }
268 if (preg_match('/^(string|safehtmlstring|email|phone|url)/', $typeofdata)) {
269 $tmp = explode(':', $typeofdata);
270 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($editvalue ? $editvalue : $value) . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
271 } elseif (preg_match('/^(integer)/', $typeofdata)) {
272 $tmp = explode(':', $typeofdata);
273 $valuetoshow = price2num($editvalue ? $editvalue : $value, 0);
274 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . $valuetoshow . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
275 } elseif (preg_match('/^(numeric|amount)/', $typeofdata)) {
276 $tmp = explode(':', $typeofdata);
277 $valuetoshow = price2num($editvalue ? $editvalue : $value);
278 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($valuetoshow != '' ? price($valuetoshow) : '') . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
279 } elseif (preg_match('/^(checkbox)/', $typeofdata)) {
280 $tmp = explode(':', $typeofdata);
281 $ret .= '<input type="checkbox" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($value ? $value : 'on') . '"' . ($value ? ' checked' : '') . (empty($tmp[1]) ? '' : $tmp[1]) . '/>';
282 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) { // if wysiwyg is enabled $typeofdata = 'ckeditor'
283 $tmp = explode(':', $typeofdata);
284 $cols = (empty($tmp[2]) ? '' : $tmp[2]);
285 $morealt = '';
286 if (preg_match('/%/', $cols)) {
287 $morealt = ' style="width: ' . $cols . '"';
288 $cols = '';
289 }
290 $valuetoshow = ($editvalue ? $editvalue : $value);
291 $ret .= '<textarea id="' . $htmlname . '" name="' . $htmlname . '" wrap="soft" rows="' . (empty($tmp[1]) ? '20' : $tmp[1]) . '"' . ($cols ? ' cols="' . $cols . '"' : 'class="quatrevingtpercent"') . $morealt . '" autofocus>';
292 // textarea convert automatically entities chars into simple chars.
293 // 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.
294 $valuetoshow = str_replace('&', '&amp;', $valuetoshow);
295 $ret .= dol_htmlwithnojs(dol_string_neverthesehtmltags($valuetoshow, array('textarea')));
296 $ret .= '</textarea><div class="clearboth"></div>';
297 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
298 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
299 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
300 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
301 $ret .= $this->selectDate($value, $htmlname, 0, 0, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
302 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
303 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
304 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
305 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
306 $ret .= $this->selectDate($value, $htmlname, 1, 1, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
307 } elseif (preg_match('/^select;/', $typeofdata)) {
308 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
309 $arraylist = array();
310 foreach ($arraydata as $val) {
311 $tmp = explode(':', $val);
312 $tmpkey = str_replace('|', ':', $tmp[0]);
313 $arraylist[$tmpkey] = $tmp[1];
314 }
315 $ret .= $this->selectarray($htmlname, $arraylist, $value);
316 } elseif (preg_match('/^link/', $typeofdata)) {
317 // TODO Not yet implemented. See code for extrafields
318 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
319 $tmp = explode(':', $typeofdata); // Example: ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols:uselocalbrowser
320 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
321 $doleditor = new DolEditor($htmlname, ($editvalue ? $editvalue : $value), (empty($tmp[2]) ? '' : $tmp[2]), (empty($tmp[3]) ? 100 : (int) $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 : (int) $tmp[6]), (empty($tmp[7]) ? '100' : $tmp[7]));
322 $ret .= $doleditor->Create(1);
323 } elseif ($typeofdata == 'asis') {
324 $ret .= ($editvalue ? $editvalue : $value);
325 }
326 if (empty($notabletag)) {
327 $ret .= '</td>';
328 }
329
330 // Button save-cancel
331 if (empty($notabletag)) {
332 $ret .= '<td>';
333 }
334 //else $ret.='<div class="clearboth"></div>';
335 $ret .= '<input type="submit" class="smallpaddingimp button' . (empty($notabletag) ? '' : ' ') . '" name="modify" value="' . $langs->trans("Modify") . '">';
336 if (preg_match('/ckeditor|textarea/', $typeofdata) && empty($notabletag)) {
337 $ret .= '<br>' . "\n";
338 }
339 $ret .= '<input type="submit" class="smallpaddingimp button button-cancel' . (empty($notabletag) ? '' : ' ') . '" name="cancel" value="' . $langs->trans("Cancel") . '">';
340 if (empty($notabletag)) {
341 $ret .= '</td>';
342 }
343
344 if (empty($notabletag)) {
345 $ret .= '</tr></table>' . "\n";
346 }
347 $ret .= '</form>' . "\n";
348 } else { // view mode
349 if (preg_match('/^email/', $typeofdata)) {
350 $ret .= dol_print_email($value, 0, 0, 0, 0, 1);
351 } elseif (preg_match('/^phone/', $typeofdata)) {
352 $ret .= dol_print_phone($value, '_blank', 32, 1);
353 } elseif (preg_match('/^url/', $typeofdata)) {
354 $ret .= dol_print_url($value, '_blank', 32, 1);
355 } elseif (preg_match('/^(amount|numeric)/', $typeofdata)) {
356 $ret .= ($value != '' ? price($value, 0, $langs, 0, -1, -1, $conf->currency) : '');
357 } elseif (preg_match('/^checkbox/', $typeofdata)) {
358 $tmp = explode(':', $typeofdata);
359 $ret .= '<input type="checkbox" disabled id="' . $htmlname . '" name="' . $htmlname . '" value="' . $value . '"' . ($value ? ' checked' : '') . ($tmp[1] ? $tmp[1] : '') . '/>';
360 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) {
362 } elseif (preg_match('/^(safehtmlstring|restricthtml)/', $typeofdata)) { // 'restricthtml' is not an allowed type for editfieldval. Value is 'safehtmlstring'
364 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
365 $ret .= '<span class="valuedate">' . dol_print_date($value, 'day', $gm) . '</span>';
366 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
367 $ret .= '<span class="valuedate">' . dol_print_date($value, 'dayhour', $gm) . '</span>';
368 } elseif (preg_match('/^select;/', $typeofdata)) {
369 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
370 $arraylist = array();
371 foreach ($arraydata as $val) {
372 $tmp = explode(':', $val);
373 $arraylist[$tmp[0]] = $tmp[1];
374 }
375 $ret .= $arraylist[$value];
376 if ($htmlname == 'fk_product_type') {
377 if ($value == 0) {
378 $ret = img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
379 } else {
380 $ret = img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
381 }
382 }
383 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
384 $tmpcontent = dol_htmlentitiesbr($value);
385 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
386 $firstline = preg_replace('/<br>.*/', '', $tmpcontent);
387 $firstline = preg_replace('/[\n\r].*/', '', $firstline);
388 $tmpcontent = $firstline . ((strlen($firstline) != strlen($tmpcontent)) ? '...' : '');
389 }
390 // We don't use dol_escape_htmltag to get the html formatting active, but this need we must also
391 // clean data from some dangerous html
393 } else {
394 if (empty($moreoptions['valuealreadyhtmlescaped'])) {
395 $ret .= dol_escape_htmltag($value);
396 } else {
397 $ret .= $value; // $value must be already html escaped.
398 }
399 }
400
401 // Custom format if parameter $formatfunc has been provided
402 if ($formatfunc && method_exists($object, $formatfunc)) {
403 $ret = $object->$formatfunc($ret);
404 }
405 }
406 }
407 return $ret;
408 }
409
421 public function widgetForTranslation($fieldname, $object, $perm, $typeofdata = 'string', $check = '', $morecss = '')
422 {
423 global $conf, $langs, $extralanguages;
424
425 $result = '';
426
427 // List of extra languages
428 $arrayoflangcode = array();
429 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
430 $arrayoflangcode[] = getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE');
431 }
432
433 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
434 if (!is_object($extralanguages)) {
435 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
436 $extralanguages = new ExtraLanguages($this->db);
437 }
438 $extralanguages->fetch_name_extralanguages('societe');
439
440 if (!is_array($extralanguages->attributes[$object->element]) || empty($extralanguages->attributes[$object->element][$fieldname])) {
441 return ''; // No extralang field to show
442 }
443
444 $result .= '<!-- Widget for translation -->' . "\n";
445 $result .= '<div class="inline-block paddingleft image-' . $object->element . '-' . $fieldname . '">';
446 $s = img_picto($langs->trans("ShowOtherLanguages"), 'language', '', 0, 0, 0, '', 'fa-15 editfieldlang');
447 $result .= $s;
448 $result .= '</div>';
449
450 $result .= '<div class="inline-block hidden field-' . $object->element . '-' . $fieldname . '">';
451
452 $resultforextrlang = '';
453 foreach ($arrayoflangcode as $langcode) {
454 $valuetoshow = GETPOSTISSET('field-' . $object->element . "-" . $fieldname . "-" . $langcode) ? GETPOST('field-' . $object->element . '-' . $fieldname . "-" . $langcode, $check) : '';
455 if (empty($valuetoshow)) {
456 $object->fetchValuesForExtraLanguages();
457 //var_dump($object->array_languages);
458 $valuetoshow = $object->array_languages[$fieldname][$langcode];
459 }
460
461 $s = picto_from_langcode($langcode, 'class="pictoforlang paddingright"');
462 $resultforextrlang .= $s;
463
464 // TODO Use the showInputField() method of ExtraLanguages object
465 if ($typeofdata == 'textarea') {
466 $resultforextrlang .= '<textarea name="field-' . $object->element . "-" . $fieldname . "-" . $langcode . '" id="' . $fieldname . "-" . $langcode . '" class="' . $morecss . '" rows="' . ROWS_2 . '" wrap="soft">';
467 $resultforextrlang .= $valuetoshow;
468 $resultforextrlang .= '</textarea>';
469 } else {
470 $resultforextrlang .= '<input type="text" class="inputfieldforlang ' . ($morecss ? ' ' . $morecss : '') . '" name="field-' . $object->element . '-' . $fieldname . '-' . $langcode . '" value="' . $valuetoshow . '">';
471 }
472 }
473 $result .= $resultforextrlang;
474
475 $result .= '</div>';
476 $result .= '<script nonce="' . getNonce() . '">$(".image-' . $object->element . '-' . $fieldname . '").click(function() { console.log("Toggle lang widget"); jQuery(".field-' . $object->element . '-' . $fieldname . '").toggle(); });</script>';
477 }
478
479 return $result;
480 }
481
495 protected function editInPlace($object, $value, $htmlname, $condition, $inputType = 'textarea', $editvalue = null, $extObject = null, $custommsg = null)
496 {
497 $out = '';
498
499 // Check parameters
500 if (preg_match('/^text/', $inputType)) {
501 $value = dol_nl2br($value);
502 } elseif (preg_match('/^numeric/', $inputType)) {
503 $value = price($value);
504 } elseif ($inputType == 'day' || $inputType == 'datepicker') {
505 $value = dol_print_date($value, 'day');
506 }
507
508 if ($condition) {
509 $element = false;
510 $table_element = false;
511 $fk_element = false;
512 $loadmethod = false;
513 $savemethod = false;
514 $ext_element = false;
515 $button_only = false;
516 $inputOption = '';
517 $rows = '';
518 $cols = '';
519
520 if (is_object($object)) {
521 $element = $object->element;
522 $table_element = $object->table_element;
523 $fk_element = $object->id;
524 }
525
526 if (is_object($extObject)) {
527 $ext_element = $extObject->element;
528 }
529
530 if (preg_match('/^(string|email|numeric)/', $inputType)) {
531 $tmp = explode(':', $inputType);
532 $inputType = $tmp[0];
533 if (!empty($tmp[1])) {
534 $inputOption = $tmp[1];
535 }
536 if (!empty($tmp[2])) {
537 $savemethod = $tmp[2];
538 }
539 $out .= '<input id="width_' . $htmlname . '" value="' . $inputOption . '" type="hidden"/>' . "\n";
540 } elseif ((preg_match('/^day$/', $inputType)) || (preg_match('/^datepicker/', $inputType)) || (preg_match('/^datehourpicker/', $inputType))) {
541 $tmp = explode(':', $inputType);
542 $inputType = $tmp[0];
543 if (!empty($tmp[1])) {
544 $inputOption = $tmp[1];
545 }
546 if (!empty($tmp[2])) {
547 $savemethod = $tmp[2];
548 }
549
550 $out .= '<input id="timestamp" type="hidden"/>' . "\n"; // Use for timestamp format
551 } elseif (preg_match('/^(select|autocomplete)/', $inputType)) {
552 $tmp = explode(':', $inputType);
553 $inputType = $tmp[0];
554 $loadmethod = $tmp[1];
555 if (!empty($tmp[2])) {
556 $savemethod = $tmp[2];
557 }
558 if (!empty($tmp[3])) {
559 $button_only = true;
560 }
561 } elseif (preg_match('/^textarea/', $inputType)) {
562 $tmp = explode(':', $inputType);
563 $inputType = $tmp[0];
564 $rows = (empty($tmp[1]) ? '8' : $tmp[1]);
565 $cols = (empty($tmp[2]) ? '80' : $tmp[2]);
566 } elseif (preg_match('/^ckeditor/', $inputType)) {
567 $tmp = explode(':', $inputType);
568 $inputType = $tmp[0];
569 $toolbar = $tmp[1];
570 if (!empty($tmp[2])) {
571 $width = $tmp[2];
572 }
573 if (!empty($tmp[3])) {
574 $height = $tmp[3];
575 }
576 if (!empty($tmp[4])) {
577 $savemethod = $tmp[4];
578 }
579
580 if (isModEnabled('fckeditor')) {
581 $out .= '<input id="ckeditor_toolbar" value="' . $toolbar . '" type="hidden"/>' . "\n";
582 } else {
583 $inputType = 'textarea';
584 }
585 }
586
587 $out .= '<input id="element_' . $htmlname . '" value="' . $element . '" type="hidden"/>' . "\n";
588 $out .= '<input id="table_element_' . $htmlname . '" value="' . $table_element . '" type="hidden"/>' . "\n";
589 $out .= '<input id="fk_element_' . $htmlname . '" value="' . $fk_element . '" type="hidden"/>' . "\n";
590 $out .= '<input id="loadmethod_' . $htmlname . '" value="' . $loadmethod . '" type="hidden"/>' . "\n";
591 if (!empty($savemethod)) {
592 $out .= '<input id="savemethod_' . $htmlname . '" value="' . $savemethod . '" type="hidden"/>' . "\n";
593 }
594 if (!empty($ext_element)) {
595 $out .= '<input id="ext_element_' . $htmlname . '" value="' . $ext_element . '" type="hidden"/>' . "\n";
596 }
597 if (!empty($custommsg)) {
598 if (is_array($custommsg)) {
599 if (!empty($custommsg['success'])) {
600 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg['success'] . '" type="hidden"/>' . "\n";
601 }
602 if (!empty($custommsg['error'])) {
603 $out .= '<input id="errormsg_' . $htmlname . '" value="' . $custommsg['error'] . '" type="hidden"/>' . "\n";
604 }
605 } else {
606 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg . '" type="hidden"/>' . "\n";
607 }
608 }
609 if ($inputType == 'textarea') {
610 $out .= '<input id="textarea_' . $htmlname . '_rows" value="' . $rows . '" type="hidden"/>' . "\n";
611 $out .= '<input id="textarea_' . $htmlname . '_cols" value="' . $cols . '" type="hidden"/>' . "\n";
612 }
613 $out .= '<span id="viewval_' . $htmlname . '" class="viewval_' . $inputType . ($button_only ? ' inactive' : ' active') . '">' . $value . '</span>' . "\n";
614 $out .= '<span id="editval_' . $htmlname . '" class="editval_' . $inputType . ($button_only ? ' inactive' : ' active') . ' hideobject">' . (!empty($editvalue) ? $editvalue : $value) . '</span>' . "\n";
615 } else {
616 $out = $value;
617 }
618
619 return $out;
620 }
621
640 public function textwithtooltip($text, $htmltext, $tooltipon = 1, $direction = 0, $img = '', $extracss = '', $notabs = 3, $incbefore = '', $noencodehtmltext = 0, $tooltiptrigger = '', $forcenowrap = 0)
641 {
642 if ($incbefore) {
643 $text = $incbefore . $text;
644 }
645 if (!$htmltext) {
646 return $text;
647 }
648 $direction = (int) $direction; // For backward compatibility when $direction was set to '' instead of 0
649
650 $tag = 'td';
651 if ($notabs == 2) {
652 $tag = 'div';
653 }
654 if ($notabs == 3) {
655 $tag = 'span';
656 }
657 // Sanitize tooltip
658 $htmltext = str_replace(array("\r", "\n"), '', $htmltext);
659
660 $extrastyle = '';
661 if ($direction < 0) {
662 $extracss = ($extracss ? $extracss : '') . ($notabs != 3 ? ' inline-block' : '');
663 $extrastyle = 'padding: 0px; padding-left: 2px;';
664 }
665 if ($direction > 0) {
666 $extracss = ($extracss ? $extracss : '') . ($notabs != 3 ? ' inline-block' : '');
667 $extrastyle = 'padding: 0px; padding-right: 2px;';
668 }
669
670 $classfortooltip = 'classfortooltip';
671
672 $s = '';
673 $textfordialog = '';
674
675 if ($tooltiptrigger == '') {
676 $htmltext = str_replace('"', '&quot;', $htmltext);
677 } else {
678 $classfortooltip = 'classfortooltiponclick';
679 $textfordialog .= '<div style="display: none;" id="idfortooltiponclick_' . $tooltiptrigger . '" class="classfortooltiponclicktext">' . $htmltext . '</div>';
680 }
681 if ($tooltipon == 2 || $tooltipon == 3) {
682 $paramfortooltipimg = ' class="' . $classfortooltip . ($notabs != 3 ? ' inline-block' : '') . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '"';
683 if ($tooltiptrigger == '') {
684 $paramfortooltipimg .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribute to put on img tag to store tooltip
685 } else {
686 $paramfortooltipimg .= ' dolid="' . $tooltiptrigger . '"';
687 }
688 } else {
689 $paramfortooltipimg = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribute to put on td text tag
690 }
691 if ($tooltipon == 1 || $tooltipon == 3) {
692 $paramfortooltiptd = ' class="' . ($tooltipon == 3 ? 'cursorpointer ' : '') . $classfortooltip . ' inline-block' . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '" ';
693 if ($tooltiptrigger == '') {
694 $paramfortooltiptd .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribute to put on td tag to store tooltip
695 } else {
696 $paramfortooltiptd .= ' dolid="' . $tooltiptrigger . '"';
697 }
698 } else {
699 $paramfortooltiptd = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribute to put on td text tag
700 }
701 if (empty($notabs)) {
702 $s .= '<table class="nobordernopadding"><tr style="height: auto;">';
703 } elseif ($notabs == 2) {
704 $s .= '<div class="inline-block' . ($forcenowrap ? ' nowrap' : '') . '">';
705 }
706 // Define value if value is before
707 if ($direction < 0) {
708 $s .= '<' . $tag . $paramfortooltipimg;
709 if ($tag == 'td') {
710 $s .= ' class="valigntop" width="14"';
711 }
712 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
713 }
714 // Use another method to help avoid having a space in value in order to use this value with jquery
715 // Define label
716 if ((string) $text != '') {
717 $s .= '<' . $tag . $paramfortooltiptd . '>' . $text . '</' . $tag . '>';
718 }
719 // Define value if value is after
720 if ($direction > 0) {
721 $s .= '<' . $tag . $paramfortooltipimg;
722 if ($tag == 'td') {
723 $s .= ' class="valignmiddle" width="14"';
724 }
725 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
726 }
727 if (empty($notabs)) {
728 $s .= '</tr></table>';
729 } elseif ($notabs == 2) {
730 $s .= '</div>';
731 }
732
733 return $s;
734 }
735
750 public function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = 'valignmiddle', $noencodehtmltext = 0, $notabs = 3, $tooltiptrigger = '', $forcenowrap = 0)
751 {
752 global $conf, $langs;
753
754 //For backwards compatibility
755 if ($type == '0') {
756 $type = 'info';
757 } elseif ($type == '1') {
758 $type = 'help';
759 }
760 // Clean parameters
761 $tooltiptrigger = preg_replace('/[^a-z0-9]/i', '', $tooltiptrigger);
762
763 if (preg_match('/onsmartphone$/', $tooltiptrigger) && empty($conf->dol_no_mouse_hover)) {
764 $tooltiptrigger = preg_replace('/^.*onsmartphone$/', '', $tooltiptrigger);
765 }
766 $alt = '';
767 if ($tooltiptrigger) {
768 $alt = $langs->transnoentitiesnoconv("ClickToShowHelp");
769 }
770
771 // If info or help with no javascript, show only text
772 if (empty($conf->use_javascript_ajax)) {
773 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
774 return $text;
775 } else {
776 $alt = $htmltext;
777 $htmltext = '';
778 }
779 }
780
781 // If info or help with smartphone, show only text (tooltip hover can't works)
782 if (!empty($conf->dol_no_mouse_hover) && empty($tooltiptrigger)) {
783 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
784 return $text;
785 }
786 }
787 // If info or help with smartphone, show only text (tooltip on click does not works with dialog on smaprtphone)
788 //if (!empty($conf->dol_no_mouse_hover) && !empty($tooltiptrigger))
789 //{
790 //if ($type == 'info' || $type == 'help') return '<a href="'..'">'.$text.'</a>';
791 //}
792
793 $img = '';
794 if ($type == 'info') {
795 $img = img_help(0, $alt);
796 } elseif ($type == 'help') {
797 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
798 } elseif ($type == 'helpclickable') {
799 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
800 } elseif ($type == 'superadmin') {
801 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
802 $img = img_picto($alt, 'redstar');
803 } elseif ($type == 'admin') {
804 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
805 $img = img_picto($alt, 'star');
806 } elseif ($type == 'warning') {
807 $img = img_warning($alt);
808 } elseif ($type != 'none') {
809 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
810 $img = img_picto($alt, $type); // $type can be an image path
811 }
812
813 return $this->textwithtooltip($text, $htmltext, ((($tooltiptrigger && !$img) || strpos($type, 'clickable')) ? 3 : 2), $direction, $img, $extracss, $notabs, '', $noencodehtmltext, $tooltiptrigger, $forcenowrap);
814 }
815
826 public function selectMassAction($selected, $arrayofaction, $alwaysvisible = 0, $name = 'massaction', $cssclass = 'checkforselect')
827 {
828 global $conf, $langs, $hookmanager;
829
830 $disabled = 0;
831 $ret = '<div class="centpercent center">';
832 $ret .= '<select class="flat' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'select valignmiddle alignstart" id="' . $name . '" name="' . $name . '"' . ($disabled ? ' disabled="disabled"' : '') . '>';
833
834 // 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.
835 $parameters = array();
836 $reshook = $hookmanager->executeHooks('addMoreMassActions', $parameters); // Note that $action and $object may have been modified by hook
837 // check if there is a mass action
838
839 if (is_array($arrayofaction) && count($arrayofaction) == 0 && empty($hookmanager->resPrint)) {
840 return;
841 }
842 if (empty($reshook)) {
843 $ret .= '<option value="0"' . ($disabled ? ' disabled="disabled"' : '') . '>-- ' . $langs->trans("SelectAction") . ' --</option>';
844 if (is_array($arrayofaction)) {
845 foreach ($arrayofaction as $code => $label) {
846 $ret .= '<option value="' . $code . '"' . ($disabled ? ' disabled="disabled"' : '') . ' data-html="' . dol_escape_htmltag($label) . '">' . $label . '</option>';
847 }
848 }
849 }
850 $ret .= $hookmanager->resPrint;
851
852 $ret .= '</select>';
853
854 if (empty($conf->dol_optimize_smallscreen)) {
855 $ret .= ajax_combobox('.' . $name . 'select');
856 }
857
858 // 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
859 $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.
860 $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")) . '">';
861 $ret .= '</div>';
862
863 if (!empty($conf->use_javascript_ajax)) {
864 $ret .= '<!-- JS CODE TO ENABLE mass action select -->
865 <script nonce="' . getNonce() . '">
866 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 */
867 {
868 atleastoneselected=0;
869 jQuery("."+cssclass).each(function( index ) {
870 /* console.log( index + ": " + $( this ).text() ); */
871 if ($(this).is(\':checked\')) atleastoneselected++;
872 });
873
874 console.log("initCheckForSelect mode="+mode+" name="+name+" cssclass="+cssclass+" atleastoneselected="+atleastoneselected);
875
876 if (atleastoneselected || ' . $alwaysvisible . ')
877 {
878 jQuery("."+name).show();
879 ' . ($selected ? 'if (atleastoneselected) { jQuery("."+name+"select").val("' . $selected . '").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', false); }' : '') . '
880 ' . ($selected ? 'if (! atleastoneselected) { jQuery("."+name+"select").val("0").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', true); } ' : '') . '
881 }
882 else
883 {
884 jQuery("."+name).hide();
885 jQuery("."+name+"other").hide();
886 }
887 }
888
889 jQuery(document).ready(function () {
890 initCheckForSelect(0, "' . $name . '", "' . $cssclass . '");
891 jQuery(".' . $cssclass . '").click(function() {
892 initCheckForSelect(1, "' . $name . '", "' . $cssclass . '");
893 });
894 jQuery(".' . $name . 'select").change(function() {
895 var massaction = $( this ).val();
896 var urlform = $( this ).closest("form").attr("action").replace("#show_files","");
897 if (massaction == "builddoc") {
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 jQuery(".' . $name . 'confirmed").prop(\'disabled\', false);
905 jQuery(".' . $name . 'other").hide(); /* To disable if another div was open */
906 jQuery(".' . $name . '"+massaction).show();
907 } else {
908 jQuery(".' . $name . 'confirmed").prop(\'disabled\', true);
909 jQuery(".' . $name . 'other").hide(); /* To disable any div open */
910 }
911 });
912 });
913 </script>
914 ';
915 }
916
917 return $ret;
918 }
919
920 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
921
938 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)
939 {
940 // phpcs:enable
941 global $conf, $langs, $mysoc;
942
943 $langs->load("dict");
944
945 $out = '';
946 $countryArray = array();
947 $favorite = array();
948 $label = array();
949 $atleastonefavorite = 0;
950
951 $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite, eec";
952 $sql .= " FROM " . $this->db->prefix() . "c_country";
953 $sql .= " WHERE active > 0";
954 //$sql.= " ORDER BY code ASC";
955
956 dol_syslog(get_class($this) . "::select_country", LOG_DEBUG);
957 $resql = $this->db->query($sql);
958 if ($resql) {
959 $out .= '<select id="select' . $htmlname . '" class="flat maxwidth200onsmartphone selectcountry' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" ' . $htmloption . '>';
960 $num = $this->db->num_rows($resql);
961 $i = 0;
962 if ($num) {
963 while ($i < $num) {
964 $obj = $this->db->fetch_object($resql);
965
966 $countryArray[$i]['rowid'] = $obj->rowid;
967 $countryArray[$i]['code_iso'] = $obj->code_iso;
968 $countryArray[$i]['code_iso3'] = $obj->code_iso3;
969 $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 : ''));
970 $countryArray[$i]['favorite'] = $obj->favorite;
971 $countryArray[$i]['eec'] = $obj->eec;
972 $favorite[$i] = $obj->favorite;
973 $label[$i] = dol_string_unaccent($countryArray[$i]['label']);
974 $i++;
975 }
976
977 if (empty($disablefavorites)) {
978 $array1_sort_order = SORT_DESC;
979 $array2_sort_order = SORT_ASC;
980 array_multisort($favorite, $array1_sort_order, $label, $array2_sort_order, $countryArray);
981 } else {
982 $countryArray = dol_sort_array($countryArray, 'label');
983 }
984
985 if ($showempty) {
986 if (is_numeric($showempty)) {
987 $out .= '<option value="">&nbsp;</option>' . "\n";
988 } else {
989 $out .= '<option value="-1">' . $langs->trans($showempty) . '</option>' . "\n";
990 }
991 }
992
993 if ($addspecialentries) { // Add dedicated entries for groups of countries
994 //if ($showempty) $out.= '<option value="" disabled class="selectoptiondisabledwhite">--------------</option>';
995 $out .= '<option value="special_allnotme"' . ($selected == 'special_allnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
996 $out .= '<option value="special_eec"' . ($selected == 'special_eec' ? ' selected' : '') . '>' . $langs->trans("CountriesInEEC") . '</option>';
997 if ($mysoc->isInEEC()) {
998 $out .= '<option value="special_eecnotme"' . ($selected == 'special_eecnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesInEECExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
999 }
1000 $out .= '<option value="special_noteec"' . ($selected == 'special_noteec' ? ' selected' : '') . '>' . $langs->trans("CountriesNotInEEC") . '</option>';
1001 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1002 }
1003
1004 foreach ($countryArray as $row) {
1005 //if (empty($showempty) && empty($row['rowid'])) continue;
1006 if (empty($row['rowid'])) {
1007 continue;
1008 }
1009 if (is_array($exclude_country_code) && count($exclude_country_code) && in_array($row['code_iso'], $exclude_country_code)) {
1010 continue; // exclude some countries
1011 }
1012
1013 if (empty($disablefavorites) && $row['favorite'] && $row['code_iso']) {
1014 $atleastonefavorite++;
1015 }
1016 if (empty($row['favorite']) && $atleastonefavorite) {
1017 $atleastonefavorite = 0;
1018 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1019 }
1020
1021 $labeltoshow = '';
1022 if ($row['label']) {
1023 $labeltoshow .= dol_trunc($row['label'], $maxlength, 'middle');
1024 } else {
1025 $labeltoshow .= '&nbsp;';
1026 }
1027 if ($row['code_iso']) {
1028 $labeltoshow .= ' <span class="opacitymedium">(' . $row['code_iso'] . ')</span>';
1029 if (empty($hideflags)) {
1030 $tmpflag = picto_from_langcode($row['code_iso'], 'class="saturatemedium paddingrightonly"', 1);
1031 $labeltoshow = $tmpflag . ' ' . $labeltoshow;
1032 }
1033 }
1034
1035 if ($selected && $selected != '-1' && ($selected == $row['rowid'] || $selected == $row['code_iso'] || $selected == $row['code_iso3'] || $selected == $row['label'])) {
1036 $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']) . '">';
1037 } else {
1038 $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']) . '">';
1039 }
1040 $out .= $labeltoshow;
1041 $out .= '</option>' . "\n";
1042 }
1043 }
1044 $out .= '</select>';
1045 } else {
1046 dol_print_error($this->db);
1047 }
1048
1049 // Make select dynamic
1050 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1051 $out .= ajax_combobox('select' . $htmlname, array(), 0, 0, 'resolve');
1052
1053 return $out;
1054 }
1055
1056 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1057
1071 public function select_incoterms($selected = '', $location_incoterms = '', $page = '', $htmlname = 'incoterm_id', $htmloption = '', $forcecombo = 1, $events = array(), $disableautocomplete = 0)
1072 {
1073 // phpcs:enable
1074 global $conf, $langs;
1075
1076 $langs->load("dict");
1077
1078 $out = '';
1079 $moreattrib = '';
1080 $incotermArray = array();
1081
1082 $sql = "SELECT rowid, code";
1083 $sql .= " FROM " . $this->db->prefix() . "c_incoterms";
1084 $sql .= " WHERE active > 0";
1085 $sql .= " ORDER BY code ASC";
1086
1087 dol_syslog(get_class($this) . "::select_incoterm", LOG_DEBUG);
1088 $resql = $this->db->query($sql);
1089 if ($resql) {
1090 if ($conf->use_javascript_ajax && !$forcecombo) {
1091 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1092 $out .= ajax_combobox($htmlname, $events);
1093 }
1094
1095 if (!empty($page)) {
1096 $out .= '<form method="post" action="' . $page . '">';
1097 $out .= '<input type="hidden" name="action" value="set_incoterms">';
1098 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
1099 }
1100
1101 $out .= '<select id="' . $htmlname . '" class="flat selectincoterm width75" name="' . $htmlname . '" ' . $htmloption . '>';
1102 $out .= '<option value="0">&nbsp;</option>';
1103 $num = $this->db->num_rows($resql);
1104 $i = 0;
1105 if ($num) {
1106 while ($i < $num) {
1107 $obj = $this->db->fetch_object($resql);
1108 $incotermArray[$i]['rowid'] = $obj->rowid;
1109 $incotermArray[$i]['code'] = $obj->code;
1110 $i++;
1111 }
1112
1113 foreach ($incotermArray as $row) {
1114 if ($selected && ($selected == $row['rowid'] || $selected == $row['code'])) {
1115 $out .= '<option value="' . $row['rowid'] . '" selected>';
1116 } else {
1117 $out .= '<option value="' . $row['rowid'] . '">';
1118 }
1119
1120 if ($row['code']) {
1121 $out .= $row['code'];
1122 }
1123
1124 $out .= '</option>';
1125 }
1126 }
1127 $out .= '</select>';
1128
1129 if ($conf->use_javascript_ajax && empty($disableautocomplete)) {
1130 $out .= ajax_multiautocompleter('location_incoterms', array(), DOL_URL_ROOT . '/core/ajax/locationincoterms.php') . "\n";
1131 $moreattrib .= ' autocomplete="off"';
1132 }
1133 $out .= '<input id="location_incoterms" class="maxwidthonsmartphone type="text" name="location_incoterms" value="' . $location_incoterms . '">' . "\n";
1134
1135 if (!empty($page)) {
1136 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp nomargintop nomarginbottom" value="' . $langs->trans("Modify") . '"></form>';
1137 }
1138 } else {
1139 dol_print_error($this->db);
1140 }
1141
1142 return $out;
1143 }
1144
1145 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1146
1159 public function select_type_of_lines($selected = '', $htmlname = 'type', $showempty = 0, $hidetext = 0, $forceall = 0, $morecss = "")
1160 {
1161 // phpcs:enable
1162 global $langs;
1163
1164 // If product & services are enabled or both disabled.
1165 if ($forceall == 1 || (empty($forceall) && isModEnabled("product") && isModEnabled("service"))
1166 || (empty($forceall) && !isModEnabled('product') && !isModEnabled('service'))) {
1167 if (empty($hidetext)) {
1168 print $langs->trans("Type") . ': ';
1169 }
1170 print '<select class="flat'.($morecss ? ' '.$morecss : '').'" id="select_' . $htmlname . '" name="' . $htmlname . '">';
1171 if ($showempty) {
1172 print '<option value="-1"';
1173 if ($selected == -1) {
1174 print ' selected';
1175 }
1176 print '>';
1177 if (is_numeric($showempty)) {
1178 print '&nbsp;';
1179 } else {
1180 print $showempty;
1181 }
1182 print '</option>';
1183 }
1184
1185 print '<option value="0"';
1186 if (0 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'product')) {
1187 print ' selected';
1188 }
1189 print '>' . $langs->trans("Product");
1190
1191 print '<option value="1"';
1192 if (1 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'service')) {
1193 print ' selected';
1194 }
1195 print '>' . $langs->trans("Service");
1196
1197 print '</select>';
1198 print ajax_combobox('select_' . $htmlname);
1199 //if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1200 }
1201 if ((empty($forceall) && !isModEnabled('product') && isModEnabled("service")) || $forceall == 3) {
1202 print $langs->trans("Service");
1203 print '<input type="hidden" name="' . $htmlname . '" value="1">';
1204 }
1205 if ((empty($forceall) && isModEnabled("product") && !isModEnabled('service')) || $forceall == 2) {
1206 print $langs->trans("Product");
1207 print '<input type="hidden" name="' . $htmlname . '" value="0">';
1208 }
1209 if ($forceall < 0) { // This should happened only for contracts when both predefined product and service are disabled.
1210 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
1211 }
1212 }
1213
1214 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1215
1221 public function load_cache_types_fees()
1222 {
1223 // phpcs:enable
1224 global $langs;
1225
1226 $num = count($this->cache_types_fees);
1227 if ($num > 0) {
1228 return 0; // Cache already loaded
1229 }
1230
1231 dol_syslog(__METHOD__, LOG_DEBUG);
1232
1233 $langs->load("trips");
1234
1235 $sql = "SELECT c.code, c.label";
1236 $sql .= " FROM " . $this->db->prefix() . "c_type_fees as c";
1237 $sql .= " WHERE active > 0";
1238
1239 $resql = $this->db->query($sql);
1240 if ($resql) {
1241 $num = $this->db->num_rows($resql);
1242 $i = 0;
1243
1244 while ($i < $num) {
1245 $obj = $this->db->fetch_object($resql);
1246
1247 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
1248 $label = ($obj->code != $langs->trans($obj->code) ? $langs->trans($obj->code) : $langs->trans($obj->label));
1249 $this->cache_types_fees[$obj->code] = $label;
1250 $i++;
1251 }
1252
1253 asort($this->cache_types_fees);
1254
1255 return $num;
1256 } else {
1257 dol_print_error($this->db);
1258 return -1;
1259 }
1260 }
1261
1262 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1263
1272 public function select_type_fees($selected = '', $htmlname = 'type', $showempty = 0)
1273 {
1274 // phpcs:enable
1275 global $user, $langs;
1276
1277 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
1278
1279 $this->load_cache_types_fees();
1280
1281 print '<select id="select_' . $htmlname . '" class="flat" name="' . $htmlname . '">';
1282 if ($showempty) {
1283 print '<option value="-1"';
1284 if ($selected == -1) {
1285 print ' selected';
1286 }
1287 print '>&nbsp;</option>';
1288 }
1289
1290 foreach ($this->cache_types_fees as $key => $value) {
1291 print '<option value="' . $key . '"';
1292 if ($key == $selected) {
1293 print ' selected';
1294 }
1295 print '>';
1296 print $value;
1297 print '</option>';
1298 }
1299
1300 print '</select>';
1301 if ($user->admin) {
1302 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1303 }
1304 }
1305
1306
1307 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1308
1331 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)
1332 {
1333 // phpcs:enable
1334 global $conf, $langs;
1335
1336 $out = '';
1337
1338 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT') && !$forcecombo) {
1339 if (is_null($ajaxoptions)) {
1340 $ajaxoptions = array();
1341 }
1342
1343 require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1344
1345 // No immediate load of all database
1346 $placeholder = '';
1347 if ($selected && empty($selected_input_value)) {
1348 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1349 $societetmp = new Societe($this->db);
1350 $societetmp->fetch($selected);
1351 $selected_input_value = $societetmp->name;
1352 unset($societetmp);
1353 }
1354
1355 // mode 1
1356 $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)) : '');
1357
1358 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
1359 if (empty($hidelabel)) {
1360 print $langs->trans("RefOrLabel") . ' : ';
1361 } elseif ($hidelabel > 1) {
1362 $placeholder = $langs->trans("RefOrLabel");
1363 if ($hidelabel == 2) {
1364 $out .= img_picto($langs->trans("Search"), 'search');
1365 }
1366 }
1367 $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' : '') . ' />';
1368 if ($hidelabel == 3) {
1369 $out .= img_picto($langs->trans("Search"), 'search');
1370 }
1371
1372 $out .= ajax_event($htmlname, $events);
1373
1374 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/societe/ajax/company.php', $urloption, getDolGlobalInt('COMPANY_USE_SEARCH_TO_SELECT'), 0, $ajaxoptions);
1375 } else {
1376 // Immediate load of all database
1377 $out .= $this->select_thirdparty_list($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, '', 0, $limit, $morecss, $moreparam, $multiple, $excludeids, $showcode);
1378 }
1379
1380 return $out;
1381 }
1382
1383
1384 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1385
1411 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 = '')
1412 {
1413 // phpcs:enable
1414
1415 global $conf, $langs;
1416
1417 $out = '';
1418
1419 $sav = getDolGlobalString('CONTACT_USE_SEARCH_TO_SELECT');
1420 if ($nokeyifsocid && $socid > 0) {
1421 $conf->global->CONTACT_USE_SEARCH_TO_SELECT = 0;
1422 }
1423
1424 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('CONTACT_USE_SEARCH_TO_SELECT') && !$forcecombo) {
1425 if (is_null($events)) {
1426 $events = array();
1427 }
1428
1429 require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1430
1431 // No immediate load of all database
1432 $placeholder = '';
1433 if ($selected && empty($selected_input_value)) {
1434 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1435 $contacttmp = new Contact($this->db);
1436 $contacttmp->fetch($selected);
1437 $selected_input_value = $contacttmp->getFullName($langs);
1438 unset($contacttmp);
1439 }
1440 if (!is_numeric($showempty)) {
1441 $placeholder = $showempty;
1442 }
1443
1444 // mode 1
1445 $urloption = 'htmlname=' . urlencode((string) (str_replace('.', '_', $htmlname))) . '&outjson=1&filter=' . urlencode((string) ($filter)) . (empty($exclude) ? '' : '&exclude=' . urlencode($exclude)) . ($showsoc ? '&showsoc=' . urlencode((string) ($showsoc)) : '');
1446
1447 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
1448
1449 $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' : '') . ' />';
1450
1451 $out .= ajax_event($htmlname, $events);
1452
1453 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/contact/ajax/contact.php', $urloption, getDolGlobalInt('CONTACT_USE_SEARCH_TO_SELECT'), 0, $events);
1454 } else {
1455 // Immediate load of all database
1456 $multiple = false;
1457 $disableifempty = 0;
1458 $options_only = 0;
1459 $limitto = '';
1460
1461 $out .= $this->selectcontacts($socid, $selected, $htmlname, $showempty, $exclude, $limitto, $showfunction, $morecss, $options_only, $showsoc, $forcecombo, $events, $moreparam, $htmlid, $multiple, $disableifempty);
1462 }
1463
1464 $conf->global->CONTACT_USE_SEARCH_TO_SELECT = $sav;
1465
1466 return $out;
1467 }
1468
1469
1470 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1471
1496 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)
1497 {
1498 // phpcs:enable
1499 global $user, $langs;
1500 global $hookmanager;
1501
1502 $out = '';
1503 $num = 0;
1504 $outarray = array();
1505
1506 if ($selected === '') {
1507 $selected = array();
1508 } elseif (!is_array($selected)) {
1509 $selected = array($selected);
1510 }
1511
1512 // Clean $filter that may contains sql conditions so sql code
1513 if (function_exists('testSqlAndScriptInject')) {
1514 if (testSqlAndScriptInject($filter, 3) > 0) {
1515 $filter = '';
1516 return 'SQLInjectionTryDetected';
1517 }
1518 }
1519
1520 if ($filter != '') { // If a filter was provided
1521 if (preg_match('/[\‍(\‍)]/', $filter)) {
1522 // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax.
1523 $errormsg = '';
1524 $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1);
1525
1526 // Redo clean $filter that may contains sql conditions so sql code
1527 if (function_exists('testSqlAndScriptInject')) {
1528 if (testSqlAndScriptInject($filter, 3) > 0) {
1529 $filter = '';
1530 return 'SQLInjectionTryDetected';
1531 }
1532 }
1533 } else {
1534 // If not, we do nothing. We already know that there is no parenthesis
1535 // TODO Disallow this case in a future.
1536 dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Syntax.", LOG_WARNING);
1537 }
1538 }
1539
1540 // We search companies
1541 $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.tva_intra, s.client, s.fournisseur, s.code_client, s.code_fournisseur";
1542 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1543 $sql .= ", s.address, s.zip, s.town";
1544 $sql .= ", dictp.code as country_code";
1545 }
1546 $sql .= " FROM " . $this->db->prefix() . "societe as s";
1547 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1548 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_country as dictp ON dictp.rowid = s.fk_pays";
1549 }
1550 if (!$user->hasRight('societe', 'client', 'voir')) {
1551 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
1552 }
1553 $sql .= " WHERE s.entity IN (" . getEntity('societe') . ")";
1554 if (!empty($user->socid)) {
1555 $sql .= " AND s.rowid = " . ((int) $user->socid);
1556 }
1557 if ($filter) {
1558 // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria()
1559 // if not, by testSqlAndScriptInject() only.
1560 $sql .= " AND (" . $filter . ")";
1561 }
1562 if (!$user->hasRight('societe', 'client', 'voir')) {
1563 $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
1564 }
1565 if (getDolGlobalString('COMPANY_HIDE_INACTIVE_IN_COMBOBOX')) {
1566 $sql .= " AND s.status <> 0";
1567 }
1568 if (!empty($excludeids)) {
1569 $sql .= " AND s.rowid NOT IN (" . $this->db->sanitize(implode(',', $excludeids)) . ")";
1570 }
1571 // Add where from hooks
1572 $parameters = array();
1573 $reshook = $hookmanager->executeHooks('selectThirdpartyListWhere', $parameters); // Note that $action and $object may have been modified by hook
1574 $sql .= $hookmanager->resPrint;
1575 // Add criteria
1576 if ($filterkey && $filterkey != '') {
1577 $sql .= " AND (";
1578 $prefix = !getDolGlobalString('COMPANY_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if COMPANY_DONOTSEARCH_ANYWHERE is on
1579 // For natural search
1580 $search_crit = explode(' ', $filterkey);
1581 $i = 0;
1582 if (count($search_crit) > 1) {
1583 $sql .= "(";
1584 }
1585 foreach ($search_crit as $crit) {
1586 if ($i > 0) {
1587 $sql .= " AND ";
1588 }
1589 $sql .= "(s.nom LIKE '" . $this->db->escape($prefix . $crit) . "%')";
1590 $i++;
1591 }
1592 if (count($search_crit) > 1) {
1593 $sql .= ")";
1594 }
1595 if (isModEnabled('barcode')) {
1596 $sql .= " OR s.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1597 }
1598 $sql .= " OR s.code_client LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.code_fournisseur LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1599 $sql .= " OR s.name_alias LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.tva_intra LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1600 $sql .= ")";
1601 }
1602 $sql .= $this->db->order("nom", "ASC");
1603 $sql .= $this->db->plimit($limit, 0);
1604
1605 // Build output string
1606 dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
1607 $resql = $this->db->query($sql);
1608 if ($resql) {
1609 // Construct $out and $outarray
1610 $out .= '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($moreparam ? ' ' . $moreparam : '') . ' name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . '>' . "\n";
1611
1612 $textifempty = (($showempty && !is_numeric($showempty)) ? $langs->trans($showempty) : '');
1613 if (getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
1614 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
1615 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
1616 if ($showempty && !is_numeric($showempty)) {
1617 $textifempty = $langs->trans($showempty);
1618 } else {
1619 $textifempty .= $langs->trans("All");
1620 }
1621 }
1622 if ($showempty) {
1623 $out .= '<option value="-1" data-html="' . dol_escape_htmltag('<span class="opacitymedium">' . ($textifempty ? $textifempty : '&nbsp;') . '</span>') . '">' . $textifempty . '</option>' . "\n";
1624 }
1625
1626 $companytemp = new Societe($this->db);
1627
1628 $num = $this->db->num_rows($resql);
1629 $i = 0;
1630 if ($num) {
1631 while ($i < $num) {
1632 $obj = $this->db->fetch_object($resql);
1633 $label = '';
1634 if ($showcode || getDolGlobalString('SOCIETE_ADD_REF_IN_LIST')) {
1635 if (($obj->client) && (!empty($obj->code_client))) {
1636 $label = $obj->code_client . ' - ';
1637 }
1638 if (($obj->fournisseur) && (!empty($obj->code_fournisseur))) {
1639 $label .= $obj->code_fournisseur . ' - ';
1640 }
1641 $label .= ' ' . $obj->name;
1642 } else {
1643 $label = $obj->name;
1644 }
1645
1646 if (!empty($obj->name_alias)) {
1647 $label .= ' (' . $obj->name_alias . ')';
1648 }
1649
1650 if (getDolGlobalString('SOCIETE_SHOW_VAT_IN_LIST') && !empty($obj->tva_intra)) {
1651 $label .= ' - '.$obj->tva_intra;
1652 }
1653
1654 $labelhtml = $label;
1655
1656 if ($showtype) {
1657 $companytemp->id = $obj->rowid;
1658 $companytemp->client = $obj->client;
1659 $companytemp->fournisseur = $obj->fournisseur;
1660 $tmptype = $companytemp->getTypeUrl(1, '', 0, 'span');
1661 if ($tmptype) {
1662 $labelhtml .= ' ' . $tmptype;
1663 }
1664
1665 if ($obj->client || $obj->fournisseur) {
1666 $label .= ' (';
1667 }
1668 if ($obj->client == 1 || $obj->client == 3) {
1669 $label .= $langs->trans("Customer");
1670 }
1671 if ($obj->client == 2 || $obj->client == 3) {
1672 $label .= ($obj->client == 3 ? ', ' : '') . $langs->trans("Prospect");
1673 }
1674 if ($obj->fournisseur) {
1675 $label .= ($obj->client ? ', ' : '') . $langs->trans("Supplier");
1676 }
1677 if ($obj->client || $obj->fournisseur) {
1678 $label .= ')';
1679 }
1680 }
1681
1682 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1683 $s = ($obj->address ? ' - ' . $obj->address : '') . ($obj->zip ? ' - ' . $obj->zip : '') . ($obj->town ? ' ' . $obj->town : '');
1684 if (!empty($obj->country_code)) {
1685 $s .= ', ' . $langs->trans('Country' . $obj->country_code);
1686 }
1687 $label .= $s;
1688 $labelhtml .= $s;
1689 }
1690
1691 if (empty($outputmode)) {
1692 if (in_array($obj->rowid, $selected)) {
1693 $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>';
1694 } else {
1695 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1696 }
1697 } else {
1698 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label, 'labelhtml' => $labelhtml));
1699 }
1700
1701 $i++;
1702 if (($i % 10) == 0) {
1703 $out .= "\n";
1704 }
1705 }
1706 }
1707 $out .= '</select>' . "\n";
1708 if (!$forcecombo) {
1709 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1710 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("COMPANY_USE_SEARCH_TO_SELECT"));
1711 }
1712 } else {
1713 dol_print_error($this->db);
1714 }
1715
1716 $this->result = array('nbofthirdparties' => $num);
1717
1718 if ($outputmode) {
1719 return $outarray;
1720 }
1721 return $out;
1722 }
1723
1724
1750 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 = '')
1751 {
1752 global $conf, $langs, $hookmanager, $action;
1753
1754 $langs->load('companies');
1755
1756 if (empty($htmlid)) {
1757 $htmlid = $htmlname;
1758 }
1759 $num = 0;
1760 $out = '';
1761 $outarray = array();
1762
1763 if ($selected === '') {
1764 $selected = array();
1765 } elseif (!is_array($selected)) {
1766 $selected = array((int) $selected);
1767 }
1768
1769 // Clean $filter that may contains sql conditions so sql code
1770 if (function_exists('testSqlAndScriptInject')) {
1771 if (testSqlAndScriptInject($filter, 3) > 0) {
1772 $filter = '';
1773 return 'SQLInjectionTryDetected';
1774 }
1775 }
1776
1777 if ($filter != '') { // If a filter was provided
1778 if (preg_match('/[\‍(\‍)]/', $filter)) {
1779 // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax.
1780 $errormsg = '';
1781 $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1);
1782
1783 // Redo clean $filter that may contains sql conditions so sql code
1784 if (function_exists('testSqlAndScriptInject')) {
1785 if (testSqlAndScriptInject($filter, 3) > 0) {
1786 $filter = '';
1787 return 'SQLInjectionTryDetected';
1788 }
1789 }
1790 } else {
1791 // If not, we do nothing. We already know that there is no parenthesis
1792 // TODO Disallow this case in a future by returning an error here.
1793 dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Filter Syntax.", LOG_WARNING);
1794 }
1795 }
1796
1797 if (!is_object($hookmanager)) {
1798 include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
1799 $hookmanager = new HookManager($this->db);
1800 }
1801
1802 // We search third parties
1803 $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";
1804 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1805 $sql .= ", s.nom as company, s.town AS company_town";
1806 }
1807 $sql .= " FROM " . $this->db->prefix() . "socpeople as sp";
1808 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1809 $sql .= " LEFT OUTER JOIN " . $this->db->prefix() . "societe as s ON s.rowid=sp.fk_soc";
1810 }
1811 $sql .= " WHERE sp.entity IN (" . getEntity('contact') . ")";
1812 if ($socid > 0 || $socid == -1) {
1813 $sql .= " AND sp.fk_soc = " . ((int) $socid);
1814 }
1815 if (getDolGlobalString('CONTACT_HIDE_INACTIVE_IN_COMBOBOX')) {
1816 $sql .= " AND sp.statut <> 0";
1817 }
1818 if ($filter) {
1819 // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria()
1820 // if not, by testSqlAndScriptInject() only.
1821 $sql .= " AND (" . $filter . ")";
1822 }
1823 // Add where from hooks
1824 $parameters = array();
1825 $reshook = $hookmanager->executeHooks('selectContactListWhere', $parameters); // Note that $action and $object may have been modified by hook
1826 $sql .= $hookmanager->resPrint;
1827 $sql .= " ORDER BY sp.lastname ASC";
1828
1829 dol_syslog(get_class($this) . "::selectcontacts", LOG_DEBUG);
1830 $resql = $this->db->query($sql);
1831 if ($resql) {
1832 $num = $this->db->num_rows($resql);
1833
1834 if ($htmlname != 'none' && !$options_only) {
1835 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlid . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . (($num || empty($disableifempty)) ? '' : ' disabled') . ($multiple ? 'multiple' : '') . ' ' . (!empty($moreparam) ? $moreparam : '') . '>';
1836 }
1837
1838 if ($showempty && !is_numeric($showempty)) {
1839 $textforempty = $showempty;
1840 $out .= '<option class="optiongrey" value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>' . $textforempty . '</option>';
1841 } else {
1842 if (($showempty == 1 || ($showempty == 3 && $num > 1)) && !$multiple) {
1843 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>&nbsp;</option>';
1844 }
1845 if ($showempty == 2) {
1846 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>-- ' . $langs->trans("Internal") . ' --</option>';
1847 }
1848 }
1849
1850 $i = 0;
1851 if ($num) {
1852 include_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1853 $contactstatic = new Contact($this->db);
1854
1855 while ($i < $num) {
1856 $obj = $this->db->fetch_object($resql);
1857
1858 // Set email (or phones) and town extended infos
1859 $extendedInfos = '';
1860 if (getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1861 $extendedInfos = array();
1862 $email = trim($obj->email);
1863 if (!empty($email)) {
1864 $extendedInfos[] = $email;
1865 } else {
1866 $phone = trim($obj->phone);
1867 $phone_perso = trim($obj->phone_perso);
1868 $phone_mobile = trim($obj->phone_mobile);
1869 if (!empty($phone)) {
1870 $extendedInfos[] = $phone;
1871 }
1872 if (!empty($phone_perso)) {
1873 $extendedInfos[] = $phone_perso;
1874 }
1875 if (!empty($phone_mobile)) {
1876 $extendedInfos[] = $phone_mobile;
1877 }
1878 }
1879 $contact_town = trim($obj->contact_town);
1880 $company_town = trim($obj->company_town);
1881 if (!empty($contact_town)) {
1882 $extendedInfos[] = $contact_town;
1883 } elseif (!empty($company_town)) {
1884 $extendedInfos[] = $company_town;
1885 }
1886 $extendedInfos = implode(' - ', $extendedInfos);
1887 if (!empty($extendedInfos)) {
1888 $extendedInfos = ' - ' . $extendedInfos;
1889 }
1890 }
1891
1892 $contactstatic->id = $obj->rowid;
1893 $contactstatic->lastname = $obj->lastname;
1894 $contactstatic->firstname = $obj->firstname;
1895 if ($obj->statut == 1) {
1896 $tmplabel = '';
1897 if ($htmlname != 'none') {
1898 $disabled = 0;
1899 if (is_array($exclude) && count($exclude) && in_array($obj->rowid, $exclude)) {
1900 $disabled = 1;
1901 }
1902 if (is_array($limitto) && count($limitto) && !in_array($obj->rowid, $limitto)) {
1903 $disabled = 1;
1904 }
1905 if (!empty($selected) && in_array($obj->rowid, $selected)) {
1906 $out .= '<option value="' . $obj->rowid . '"';
1907 if ($disabled) {
1908 $out .= ' disabled';
1909 }
1910 $out .= ' selected>';
1911
1912 $tmplabel = $contactstatic->getFullName($langs) . $extendedInfos;
1913 if ($showfunction && $obj->poste) {
1914 $tmplabel .= ' (' . $obj->poste . ')';
1915 }
1916 if (($showsoc > 0) && $obj->company) {
1917 $tmplabel .= ' - (' . $obj->company . ')';
1918 }
1919
1920 $out .= $tmplabel;
1921 $out .= '</option>';
1922 } else {
1923 $out .= '<option value="' . $obj->rowid . '"';
1924 if ($disabled) {
1925 $out .= ' disabled';
1926 }
1927 $out .= '>';
1928
1929 $tmplabel = $contactstatic->getFullName($langs) . $extendedInfos;
1930 if ($showfunction && $obj->poste) {
1931 $tmplabel .= ' (' . $obj->poste . ')';
1932 }
1933 if (($showsoc > 0) && $obj->company) {
1934 $tmplabel .= ' - (' . $obj->company . ')';
1935 }
1936
1937 $out .= $tmplabel;
1938 $out .= '</option>';
1939 }
1940 } else {
1941 if (in_array($obj->rowid, $selected)) {
1942 $tmplabel = $contactstatic->getFullName($langs) . $extendedInfos;
1943 if ($showfunction && $obj->poste) {
1944 $tmplabel .= ' (' . $obj->poste . ')';
1945 }
1946 if (($showsoc > 0) && $obj->company) {
1947 $tmplabel .= ' - (' . $obj->company . ')';
1948 }
1949
1950 $out .= $tmplabel;
1951 }
1952 }
1953
1954 if ($tmplabel != '') {
1955 array_push($outarray, array('key' => $obj->rowid, 'value' => $tmplabel, 'label' => $tmplabel, 'labelhtml' => $tmplabel));
1956 }
1957 }
1958 $i++;
1959 }
1960 } else {
1961 $labeltoshow = ($socid != -1) ? ($langs->trans($socid ? "NoContactDefinedForThirdParty" : "NoContactDefined")) : $langs->trans('SelectAThirdPartyFirst');
1962 $out .= '<option class="disabled" value="-1"' . (($showempty == 2 || $multiple) ? '' : ' selected') . ' disabled="disabled">';
1963 $out .= $labeltoshow;
1964 $out .= '</option>';
1965 }
1966
1967 $parameters = array(
1968 'socid' => $socid,
1969 'htmlname' => $htmlname,
1970 'resql' => $resql,
1971 'out' => &$out,
1972 'showfunction' => $showfunction,
1973 'showsoc' => $showsoc,
1974 );
1975
1976 $reshook = $hookmanager->executeHooks('afterSelectContactOptions', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1977
1978 if ($htmlname != 'none' && !$options_only) {
1979 $out .= '</select>';
1980 }
1981
1982 if ($conf->use_javascript_ajax && !$forcecombo && !$options_only) {
1983 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1984 $out .= ajax_combobox($htmlid, $events, getDolGlobalInt("CONTACT_USE_SEARCH_TO_SELECT"));
1985 }
1986
1987 $this->num = $num;
1988
1989 if ($options_only === 2) {
1990 // Return array of options
1991 return $outarray;
1992 } else {
1993 return $out;
1994 }
1995 } else {
1996 dol_print_error($this->db);
1997 return -1;
1998 }
1999 }
2000
2001
2002 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2003
2014 public function select_remises($selected, $htmlname, $filter, $socid, $maxvalue = 0)
2015 {
2016 // phpcs:enable
2017 global $langs, $conf;
2018
2019 // On recherche les remises
2020 $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
2021 $sql .= " re.description, re.fk_facture_source";
2022 $sql .= " FROM " . $this->db->prefix() . "societe_remise_except as re";
2023 $sql .= " WHERE re.fk_soc = " . (int) $socid;
2024 $sql .= " AND re.entity = " . $conf->entity;
2025 if ($filter) {
2026 $sql .= " AND " . $filter;
2027 }
2028 $sql .= " ORDER BY re.description ASC";
2029
2030 dol_syslog(get_class($this) . "::select_remises", LOG_DEBUG);
2031 $resql = $this->db->query($sql);
2032 if ($resql) {
2033 print '<select id="select_' . $htmlname . '" class="flat maxwidthonsmartphone" name="' . $htmlname . '">';
2034 $num = $this->db->num_rows($resql);
2035
2036 $qualifiedlines = $num;
2037
2038 $i = 0;
2039 if ($num) {
2040 print '<option value="0">&nbsp;</option>';
2041 while ($i < $num) {
2042 $obj = $this->db->fetch_object($resql);
2043 $desc = dol_trunc($obj->description, 40);
2044 if (preg_match('/\‍(CREDIT_NOTE\‍)/', $desc)) {
2045 $desc = preg_replace('/\‍(CREDIT_NOTE\‍)/', $langs->trans("CreditNote"), $desc);
2046 }
2047 if (preg_match('/\‍(DEPOSIT\‍)/', $desc)) {
2048 $desc = preg_replace('/\‍(DEPOSIT\‍)/', $langs->trans("Deposit"), $desc);
2049 }
2050 if (preg_match('/\‍(EXCESS RECEIVED\‍)/', $desc)) {
2051 $desc = preg_replace('/\‍(EXCESS RECEIVED\‍)/', $langs->trans("ExcessReceived"), $desc);
2052 }
2053 if (preg_match('/\‍(EXCESS PAID\‍)/', $desc)) {
2054 $desc = preg_replace('/\‍(EXCESS PAID\‍)/', $langs->trans("ExcessPaid"), $desc);
2055 }
2056
2057 $selectstring = '';
2058 if ($selected > 0 && $selected == $obj->rowid) {
2059 $selectstring = ' selected';
2060 }
2061
2062 $disabled = '';
2063 if ($maxvalue > 0 && $obj->amount_ttc > $maxvalue) {
2064 $qualifiedlines--;
2065 $disabled = ' disabled';
2066 }
2067
2068 if (getDolGlobalString('MAIN_SHOW_FACNUMBER_IN_DISCOUNT_LIST') && !empty($obj->fk_facture_source)) {
2069 $tmpfac = new Facture($this->db);
2070 if ($tmpfac->fetch($obj->fk_facture_source) > 0) {
2071 $desc = $desc . ' - ' . $tmpfac->ref;
2072 }
2073 }
2074
2075 print '<option value="' . $obj->rowid . '"' . $selectstring . $disabled . '>' . $desc . ' (' . price($obj->amount_ht) . ' ' . $langs->trans("HT") . ' - ' . price($obj->amount_ttc) . ' ' . $langs->trans("TTC") . ')</option>';
2076 $i++;
2077 }
2078 }
2079 print '</select>';
2080 print ajax_combobox('select_' . $htmlname);
2081
2082 return $qualifiedlines;
2083 } else {
2084 dol_print_error($this->db);
2085 return -1;
2086 }
2087 }
2088
2089
2090 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2091
2107 public function select_users($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0')
2108 {
2109 // phpcs:enable
2110 print $this->select_dolusers($selected, $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity);
2111 }
2112
2113 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2114
2139 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)
2140 {
2141 // phpcs:enable
2142 global $conf, $user, $langs, $hookmanager;
2143 global $action;
2144
2145 // If no preselected user defined, we take current user
2146 if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) {
2147 $selected = $user->id;
2148 }
2149
2150 if ($selected === '') {
2151 $selected = array();
2152 } elseif (!is_array($selected)) {
2153 $selected = array($selected);
2154 }
2155
2156 $excludeUsers = null;
2157 $includeUsers = null;
2158
2159 // Exclude some users
2160 if (is_array($exclude)) {
2161 $excludeUsers = implode(",", $exclude);
2162 }
2163 // Include some uses
2164 if (is_array($include)) {
2165 $includeUsers = implode(",", $include);
2166 } elseif ($include == 'hierarchy') {
2167 // Build list includeUsers to have only hierarchy
2168 $includeUsers = implode(",", $user->getAllChildIds(0));
2169 } elseif ($include == 'hierarchyme') {
2170 // Build list includeUsers to have only hierarchy and current user
2171 $includeUsers = implode(",", $user->getAllChildIds(1));
2172 }
2173
2174 $num = 0;
2175
2176 $out = '';
2177 $outarray = array();
2178 $outarray2 = array();
2179
2180 // Do we want to show the label of entity into the combo list ?
2181 $showlabelofentity = isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1 && !empty($user->admin) && empty($user->entity);
2182 $userissuperadminentityone = isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && empty($user->entity);
2183
2184 // Forge request to select users
2185 $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";
2186 if ($showlabelofentity) {
2187 $sql .= ", e.label";
2188 }
2189 $sql .= " FROM " . $this->db->prefix() . "user as u";
2190 if ($showlabelofentity) {
2191 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid = u.entity";
2192 }
2193 // Condition here should be the same than into societe->getSalesRepresentatives().
2194 if ($userissuperadminentityone && $force_entity != 'default') {
2195 if (!empty($force_entity)) {
2196 $sql .= " WHERE u.entity IN (0, " . $this->db->sanitize($force_entity) . ")";
2197 } else {
2198 $sql .= " WHERE u.entity IS NOT NULL";
2199 }
2200 } else {
2201 if (isModEnabled('multicompany') && getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE')) {
2202 $sql .= " WHERE u.rowid IN (SELECT ug.fk_user FROM ".$this->db->prefix()."usergroup_user as ug WHERE ug.entity IN (".getEntity('usergroup')."))";
2203 } else {
2204 $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
2205 }
2206 }
2207
2208 if (!empty($user->socid)) {
2209 $sql .= " AND u.fk_soc = " . ((int) $user->socid);
2210 }
2211 if (is_array($exclude) && $excludeUsers) {
2212 $sql .= " AND u.rowid NOT IN (" . $this->db->sanitize($excludeUsers) . ")";
2213 }
2214 if ($includeUsers) {
2215 $sql .= " AND u.rowid IN (" . $this->db->sanitize($includeUsers) . ")";
2216 }
2217 if (getDolGlobalString('USER_HIDE_INACTIVE_IN_COMBOBOX') || $notdisabled) {
2218 $sql .= " AND u.statut <> 0";
2219 }
2220 if (getDolGlobalString('USER_HIDE_NONEMPLOYEE_IN_COMBOBOX') || $notdisabled) {
2221 $sql .= " AND u.employee <> 0";
2222 }
2223 if (getDolGlobalString('USER_HIDE_EXTERNAL_IN_COMBOBOX') || $notdisabled) {
2224 $sql .= " AND u.fk_soc IS NULL";
2225 }
2226 if (!empty($morefilter)) {
2227 $sql .= " " . $morefilter;
2228 }
2229
2230 //Add hook to filter on user (for example on usergroup define in custom modules)
2231 $reshook = $hookmanager->executeHooks('addSQLWhereFilterOnSelectUsers', array(), $this, $action);
2232 if (!empty($reshook)) {
2233 $sql .= $hookmanager->resPrint;
2234 }
2235
2236 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) { // MAIN_FIRSTNAME_NAME_POSITION is 0 means firstname+lastname
2237 $sql .= " ORDER BY u.statut DESC, u.firstname ASC, u.lastname ASC";
2238 } else {
2239 $sql .= " ORDER BY u.statut DESC, u.lastname ASC, u.firstname ASC";
2240 }
2241
2242 dol_syslog(get_class($this) . "::select_dolusers", LOG_DEBUG);
2243
2244 $resql = $this->db->query($sql);
2245 if ($resql) {
2246 $num = $this->db->num_rows($resql);
2247 $i = 0;
2248 if ($num) {
2249 // do not use maxwidthonsmartphone by default. Set it by caller so auto size to 100% will work when not defined
2250 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : ' minwidth200') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
2251 if ($show_empty && !$multiple) {
2252 $textforempty = ' ';
2253 if (!empty($conf->use_javascript_ajax)) {
2254 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
2255 }
2256 if (!is_numeric($show_empty)) {
2257 $textforempty = $show_empty;
2258 }
2259 $out .= '<option class="optiongrey" value="' . ($show_empty < 0 ? $show_empty : -1) . '"' . ((empty($selected) || in_array(-1, $selected)) ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
2260
2261 $outarray[($show_empty < 0 ? $show_empty : -1)] = $textforempty;
2262 $outarray2[($show_empty < 0 ? $show_empty : -1)] = array(
2263 'id' => ($show_empty < 0 ? $show_empty : -1),
2264 'label' => $textforempty,
2265 'labelhtml' => $textforempty,
2266 'color' => '',
2267 'picto' => ''
2268 );
2269 }
2270 if ($show_every) {
2271 $out .= '<option value="-2"' . ((in_array(-2, $selected)) ? ' selected' : '') . '>-- ' . $langs->trans("Everybody") . ' --</option>' . "\n";
2272
2273 $outarray[-2] = '-- ' . $langs->trans("Everybody") . ' --';
2274 $outarray2[-2] = array(
2275 'id' => -2,
2276 'label' => '-- ' . $langs->trans("Everybody") . ' --',
2277 'labelhtml' => '-- ' . $langs->trans("Everybody") . ' --',
2278 'color' => '',
2279 'picto' => ''
2280 );
2281 }
2282
2283 $userstatic = new User($this->db);
2284
2285 while ($i < $num) {
2286 $obj = $this->db->fetch_object($resql);
2287
2288 $userstatic->id = $obj->rowid;
2289 $userstatic->lastname = $obj->lastname;
2290 $userstatic->firstname = $obj->firstname;
2291 $userstatic->photo = $obj->photo;
2292 $userstatic->status = $obj->status;
2293 $userstatic->entity = $obj->entity;
2294 $userstatic->admin = $obj->admin;
2295 $userstatic->gender = $obj->gender;
2296
2297 $disableline = '';
2298 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
2299 $disableline = ($enableonlytext ? $enableonlytext : '1');
2300 }
2301
2302 $labeltoshow = '';
2303 $labeltoshowhtml = '';
2304
2305 // $fullNameMode is 0=Lastname+Firstname (MAIN_FIRSTNAME_NAME_POSITION=1), 1=Firstname+Lastname (MAIN_FIRSTNAME_NAME_POSITION=0)
2306 $fullNameMode = 0;
2307 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) {
2308 $fullNameMode = 1; //Firstname+lastname
2309 }
2310 $labeltoshow .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2311 $labeltoshowhtml .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2312 if (empty($obj->firstname) && empty($obj->lastname)) {
2313 $labeltoshow .= $obj->login;
2314 $labeltoshowhtml .= $obj->login;
2315 }
2316
2317 // Complete name with a more info string like: ' (info1 - info2 - ...)'
2318 $moreinfo = '';
2319 $moreinfohtml = '';
2320 if (getDolGlobalString('MAIN_SHOW_LOGIN')) {
2321 $moreinfo .= ($moreinfo ? ' - ' : ' (');
2322 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(');
2323 $moreinfo .= $obj->login;
2324 $moreinfohtml .= $obj->login;
2325 }
2326 if ($showstatus >= 0) {
2327 if ($obj->status == 1 && $showstatus == 1) {
2328 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Enabled');
2329 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Enabled');
2330 }
2331 if ($obj->status == 0 && $showstatus == 1) {
2332 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Disabled');
2333 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Disabled');
2334 }
2335 }
2336 if ($showlabelofentity) {
2337 if (empty($obj->entity)) {
2338 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans("AllEntities");
2339 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans("AllEntities");
2340 } else {
2341 if ($obj->entity != $conf->entity) {
2342 $moreinfo .= ($moreinfo ? ' - ' : ' (') . ($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2343 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(').($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2344 }
2345 }
2346 }
2347 $moreinfo .= (!empty($moreinfo) ? ')' : '');
2348 $moreinfohtml .= (!empty($moreinfohtml) ? ')</span>' : '');
2349 if (!empty($disableline) && $disableline != '1') {
2350 // Add text from $enableonlytext parameter
2351 $moreinfo .= ' - ' . $disableline;
2352 $moreinfohtml .= ' - ' . $disableline;
2353 }
2354 $labeltoshow .= $moreinfo;
2355 $labeltoshowhtml .= $moreinfohtml;
2356
2357 $out .= '<option value="' . $obj->rowid . '"';
2358 if (!empty($disableline)) {
2359 $out .= ' disabled';
2360 }
2361 if ((!empty($selected[0]) && is_object($selected[0])) ? $selected[0]->id == $obj->rowid : in_array($obj->rowid, $selected)) {
2362 $out .= ' selected';
2363 }
2364 $out .= ' data-html="';
2365
2366 $outhtml = $userstatic->getNomUrl(-3, '', 0, 1, 24, 1, 'login', '', 1) . ' ';
2367 if ($showstatus >= 0 && $obj->status == 0) {
2368 $outhtml .= '<strike class="opacitymediumxxx">';
2369 }
2370 $outhtml .= $labeltoshowhtml;
2371 if ($showstatus >= 0 && $obj->status == 0) {
2372 $outhtml .= '</strike>';
2373 }
2374 $labeltoshowhtml = $outhtml;
2375
2376 $out .= dol_escape_htmltag($outhtml);
2377 $out .= '">';
2378 $out .= $labeltoshow;
2379 $out .= '</option>';
2380
2381 $outarray[$userstatic->id] = $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength) . $moreinfo;
2382 $outarray2[$userstatic->id] = array(
2383 'id' => $userstatic->id,
2384 'label' => $labeltoshow,
2385 'labelhtml' => $labeltoshowhtml,
2386 'color' => '',
2387 'picto' => ''
2388 );
2389
2390 $i++;
2391 }
2392 } else {
2393 $out .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '" disabled>';
2394 $out .= '<option value="">' . $langs->trans("None") . '</option>';
2395 }
2396 $out .= '</select>';
2397
2398 if ($num && !$forcecombo) {
2399 // Enhance with select2
2400 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2401 $out .= ajax_combobox($htmlname);
2402 }
2403 } else {
2404 dol_print_error($this->db);
2405 }
2406
2407 $this->num = $num;
2408
2409 if ($outputmode == 2) {
2410 return $outarray2;
2411 } elseif ($outputmode) {
2412 return $outarray;
2413 }
2414
2415 return $out;
2416 }
2417
2418
2419 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2442 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())
2443 {
2444 // phpcs:enable
2445 global $langs;
2446
2447 $userstatic = new User($this->db);
2448 $out = '';
2449
2450 if (!empty($_SESSION['assignedtouser'])) {
2451 $assignedtouser = json_decode($_SESSION['assignedtouser'], true);
2452 if (!is_array($assignedtouser)) {
2453 $assignedtouser = array();
2454 }
2455 } else {
2456 $assignedtouser = array();
2457 }
2458 $nbassignetouser = count($assignedtouser);
2459
2460 //if ($nbassignetouser && $action != 'view') $out .= '<br>';
2461 if ($nbassignetouser) {
2462 $out .= '<ul class="attendees">';
2463 }
2464 $i = 0;
2465 $ownerid = 0;
2466 foreach ($assignedtouser as $key => $value) {
2467 if ($value['id'] == $ownerid) {
2468 continue;
2469 }
2470
2471 $out .= '<li>';
2472 $userstatic->fetch($value['id']);
2473 $out .= $userstatic->getNomUrl(-1);
2474 if ($i == 0) {
2475 $ownerid = $value['id'];
2476 $out .= ' (' . $langs->trans("Owner") . ')';
2477 }
2478 if ($nbassignetouser > 1 && $action != 'view') {
2479 $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 . '">';
2480 }
2481 // Show my availability
2482 if ($showproperties) {
2483 if ($ownerid == $value['id'] && is_array($listofuserid) && count($listofuserid) && in_array($ownerid, array_keys($listofuserid))) {
2484 $out .= '<div class="myavailability inline-block">';
2485 $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>';
2486 $out .= '</div>';
2487 }
2488 }
2489 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2490 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2491
2492 $out .= '</li>';
2493 $i++;
2494 }
2495 if ($nbassignetouser) {
2496 $out .= '</ul>';
2497 }
2498
2499 // Method with no ajax
2500 if ($action != 'view') {
2501 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassigned" value="">';
2502 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2503 $out .= 'jQuery(".removedassigned").click(function() { jQuery(".removedassignedhidden").val(jQuery(this).val()); });';
2504 $out .= 'jQuery(".assignedtouser").change(function() { console.log(jQuery(".assignedtouser option:selected").val());';
2505 $out .= ' if (jQuery(".assignedtouser option:selected").val() > 0) { jQuery("#' . $action . 'assignedtouser").attr("disabled", false); }';
2506 $out .= ' else { jQuery("#' . $action . 'assignedtouser").attr("disabled", true); }';
2507 $out .= '});';
2508 $out .= '})</script>';
2509 $out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2510 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtouser" name="' . $action . 'assignedtouser" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2511 $out .= '<br>';
2512 }
2513
2514 return $out;
2515 }
2516
2517 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2537 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())
2538 {
2539 // phpcs:enable
2540 global $langs;
2541
2542 require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php';
2543 require_once DOL_DOCUMENT_ROOT.'/resource/class/dolresource.class.php';
2544 $formresources = new FormResource($this->db);
2545 $resourcestatic = new Dolresource($this->db);
2546
2547 $out = '';
2548 if (!empty($_SESSION['assignedtoresource'])) {
2549 $assignedtoresource = json_decode($_SESSION['assignedtoresource'], true);
2550 if (!is_array($assignedtoresource)) {
2551 $assignedtoresource = array();
2552 }
2553 } else {
2554 $assignedtoresource = array();
2555 }
2556 $nbassignetoresource = count($assignedtoresource);
2557
2558 //if ($nbassignetoresource && $action != 'view') $out .= '<br>';
2559 if ($nbassignetoresource) {
2560 $out .= '<ul class="attendees">';
2561 }
2562 $i = 0;
2563
2564 foreach ($assignedtoresource as $key => $value) {
2565 $out .= '<li>';
2566 $resourcestatic->fetch($value['id']);
2567 $out .= $resourcestatic->getNomUrl(-1);
2568 if ($nbassignetoresource > 1 && $action != 'view') {
2569 $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 . '">';
2570 }
2571 // Show my availability
2572 if ($showproperties) {
2573 if (is_array($listofresourceid) && count($listofresourceid)) {
2574 $out .= '<div class="myavailability inline-block">';
2575 $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>';
2576 $out .= '</div>';
2577 }
2578 }
2579 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2580 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2581
2582 $out .= '</li>';
2583 $i++;
2584 }
2585 if ($nbassignetoresource) {
2586 $out .= '</ul>';
2587 }
2588
2589 // Method with no ajax
2590 if ($action != 'view') {
2591 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassignedresource" value="">';
2592 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2593 $out .= 'jQuery(".removedassignedresource").click(function() { jQuery(".removedassignedresourcehidden").val(jQuery(this).val()); });';
2594 $out .= 'jQuery(".assignedtoresource").change(function() { console.log(jQuery(".assignedtoresource option:selected").val());';
2595 $out .= ' if (jQuery(".assignedtoresource option:selected").val() > 0) { jQuery("#' . $action . 'assignedtoresource").attr("disabled", false); }';
2596 $out .= ' else { jQuery("#' . $action . 'assignedtoresource").attr("disabled", true); }';
2597 $out .= '});';
2598 $out .= '})</script>';
2599
2600 $events = array();
2601 $out .= img_picto('', 'resource', 'class="pictofixedwidth"');
2602 $out .= $formresources->select_resource_list(0, $htmlname, [], 1, 1, 0, $events, array(), 2, 0);
2603 //$out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2604 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtoresource" name="' . $action . 'assignedtoresource" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2605 $out .= '<br>';
2606 }
2607
2608 return $out;
2609 }
2610
2611 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2612
2643 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, $warehouseId = 0)
2644 {
2645 // phpcs:enable
2646 global $langs, $conf;
2647
2648 $out = '';
2649
2650 // check parameters
2651 $price_level = (!empty($price_level) ? $price_level : 0);
2652 if (is_null($ajaxoptions)) {
2653 $ajaxoptions = array();
2654 }
2655
2656 if (strval($filtertype) === '' && (isModEnabled("product") || isModEnabled("service"))) {
2657 if (isModEnabled("product") && !isModEnabled('service')) {
2658 $filtertype = '0';
2659 } elseif (!isModEnabled('product') && isModEnabled("service")) {
2660 $filtertype = '1';
2661 }
2662 }
2663
2664 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
2665 $placeholder = '';
2666
2667 if ($selected && empty($selected_input_value)) {
2668 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2669 $producttmpselect = new Product($this->db);
2670 $producttmpselect->fetch($selected);
2671 $selected_input_value = $producttmpselect->ref;
2672 unset($producttmpselect);
2673 }
2674 // handle case where product or service module is disabled + no filter specified
2675 if ($filtertype == '') {
2676 if (!isModEnabled('product')) { // when product module is disabled, show services only
2677 $filtertype = 1;
2678 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
2679 $filtertype = 0;
2680 }
2681 }
2682 // mode=1 means customers products
2683 $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;
2684 if ((int) $warehouseId > 0) {
2685 $urloption .= '&warehouseid=' . (int) $warehouseId;
2686 }
2687 $out .= ajax_autocompleter((string) $selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, getDolGlobalInt('PRODUIT_USE_SEARCH_TO_SELECT'), getDolGlobalInt('PRODUCT_SEARCH_AUTO_SELECT_IF_ONLY_ONE', 1), $ajaxoptions);
2688
2689 if (isModEnabled('variants') && is_array($selected_combinations)) {
2690 // Code to automatically insert with javascript the select of attributes under the select of product
2691 // when a parent of variant has been selected.
2692 $out .= '
2693 <!-- script to auto show attributes select tags if a variant was selected -->
2694 <script nonce="' . getNonce() . '">
2695 // auto show attributes fields
2696 selected = ' . json_encode($selected_combinations) . ';
2697 combvalues = {};
2698
2699 jQuery(document).ready(function () {
2700
2701 jQuery("input[name=\'prod_entry_mode\']").change(function () {
2702 if (jQuery(this).val() == \'free\') {
2703 jQuery(\'div#attributes_box\').empty();
2704 }
2705 });
2706
2707 jQuery("input#' . $htmlname . '").change(function () {
2708
2709 if (!jQuery(this).val()) {
2710 jQuery(\'div#attributes_box\').empty();
2711 return;
2712 }
2713
2714 console.log("A change has started. We get variants fields to inject html select");
2715
2716 jQuery.getJSON("' . DOL_URL_ROOT . '/variants/ajax/getCombinations.php", {
2717 id: jQuery(this).val()
2718 }, function (data) {
2719 jQuery(\'div#attributes_box\').empty();
2720
2721 jQuery.each(data, function (key, val) {
2722
2723 combvalues[val.id] = val.values;
2724
2725 var span = jQuery(document.createElement(\'div\')).css({
2726 \'display\': \'table-row\'
2727 });
2728
2729 span.append(
2730 jQuery(document.createElement(\'div\')).text(val.label).css({
2731 \'font-weight\': \'bold\',
2732 \'display\': \'table-cell\'
2733 })
2734 );
2735
2736 var html = jQuery(document.createElement(\'select\')).attr(\'name\', \'combinations[\' + val.id + \']\').css({
2737 \'margin-left\': \'15px\',
2738 \'white-space\': \'pre\'
2739 }).append(
2740 jQuery(document.createElement(\'option\')).val(\'\')
2741 );
2742
2743 jQuery.each(combvalues[val.id], function (key, val) {
2744 var tag = jQuery(document.createElement(\'option\')).val(val.id).html(val.value);
2745
2746 if (selected[val.fk_product_attribute] == val.id) {
2747 tag.attr(\'selected\', \'selected\');
2748 }
2749
2750 html.append(tag);
2751 });
2752
2753 span.append(html);
2754 jQuery(\'div#attributes_box\').append(span);
2755 });
2756 })
2757 });
2758
2759 ' . ($selected ? 'jQuery("input#' . $htmlname . '").change();' : '') . '
2760 });
2761 </script>
2762 ';
2763 }
2764
2765 if (empty($hidelabel)) {
2766 $out .= $langs->trans("RefOrLabel") . ' : ';
2767 } elseif ($hidelabel > 1) {
2768 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
2769 if ($hidelabel == 2) {
2770 $out .= img_picto($langs->trans("Search"), 'search');
2771 }
2772 }
2773 $out .= '<input type="text" class="minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
2774 if ($hidelabel == 3) {
2775 $out .= img_picto($langs->trans("Search"), 'search');
2776 }
2777 } else {
2778 $out .= $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus, $status_purchase, $warehouseId);
2779 }
2780
2781 if (empty($nooutput)) {
2782 print $out;
2783 } else {
2784 return $out;
2785 }
2786 }
2787
2788 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2789
2805 public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 0, $showempty = '1', $morecss = '', $nooutput = '', $forcecombo = 0, $TProducts = [])
2806 {
2807 // phpcs:enable
2808 global $db;
2809
2810 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2811
2812 $error = 0;
2813 $out = '';
2814
2815 if (!$forcecombo) {
2816 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2817 $events = array();
2818 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
2819 }
2820
2821 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
2822
2823 $sql = 'SELECT b.rowid, b.ref, b.label, b.fk_product';
2824 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'bom_bom as b';
2825 $sql .= ' WHERE b.entity IN (' . getEntity('bom') . ')';
2826 if (!empty($status)) {
2827 $sql .= ' AND status = ' . (int) $status;
2828 }
2829 if (!empty($type)) {
2830 $sql .= ' AND bomtype = ' . (int) $type;
2831 }
2832 if (!empty($TProducts)) {
2833 $sql .= ' AND fk_product IN (' . $this->db->sanitize(implode(',', $TProducts)) . ')';
2834 }
2835 if (!empty($limit)) {
2836 $sql .= ' LIMIT ' . (int) $limit;
2837 }
2838 $resql = $db->query($sql);
2839 if ($resql) {
2840 if ($showempty) {
2841 $out .= '<option value="-1"';
2842 if (empty($selected)) {
2843 $out .= ' selected';
2844 }
2845 $out .= '>&nbsp;</option>';
2846 }
2847 while ($obj = $db->fetch_object($resql)) {
2848 $product = new Product($db);
2849 $res = $product->fetch($obj->fk_product);
2850 $out .= '<option value="' . $obj->rowid . '"';
2851 if ($obj->rowid == $selected) {
2852 $out .= 'selected';
2853 }
2854 $out .= '>' . $obj->ref . ' - ' . $product->label . ' - ' . $obj->label . '</option>';
2855 }
2856 } else {
2857 $error++;
2858 dol_print_error($db);
2859 }
2860 $out .= '</select>';
2861 if (empty($nooutput)) {
2862 print $out;
2863 } else {
2864 return $out;
2865 }
2866 }
2867
2868 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2869
2896 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, $warehouseId = 0)
2897 {
2898 // phpcs:enable
2899 global $langs;
2900 global $hookmanager;
2901
2902 $out = '';
2903 $outarray = array();
2904
2905 // Units
2906 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2907 $langs->load('other');
2908 }
2909
2910 $warehouseStatusArray = array();
2911 if (!empty($warehouseStatus)) {
2912 require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
2913 if (preg_match('/warehouseclosed/', $warehouseStatus)) {
2914 $warehouseStatusArray[] = Entrepot::STATUS_CLOSED;
2915 }
2916 if (preg_match('/warehouseopen/', $warehouseStatus)) {
2917 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL;
2918 }
2919 if (preg_match('/warehouseinternal/', $warehouseStatus)) {
2920 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL;
2921 }
2922 }
2923
2924 $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";
2925 if (count($warehouseStatusArray)) {
2926 $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
2927 } else {
2928 $selectFieldsGrouped = ", " . $this->db->ifsql("p.stock IS NULL", 0, "p.stock") . " AS stock";
2929 }
2930
2931 $sql = "SELECT ";
2932
2933 // Add select from hooks
2934 $parameters = array();
2935 $reshook = $hookmanager->executeHooks('selectProductsListSelect', $parameters); // Note that $action and $object may have been modified by hook
2936 if (empty($reshook)) {
2937 $sql .= $selectFields.$selectFieldsGrouped.$hookmanager->resPrint;
2938 } else {
2939 $sql .= $hookmanager->resPrint;
2940 }
2941
2942 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
2943 //Product category
2944 $sql .= ", (SELECT " . $this->db->prefix() . "categorie_product.fk_categorie
2945 FROM " . $this->db->prefix() . "categorie_product
2946 WHERE " . $this->db->prefix() . "categorie_product.fk_product=p.rowid
2947 LIMIT 1
2948 ) AS categorie_product_id ";
2949 }
2950
2951 //Price by customer
2952 if ((getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !empty($socid)) {
2953 $sql .= ', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
2954 $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';
2955 $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custdefault_vat_code, custref";
2956 }
2957 // Units
2958 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2959 $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";
2960 $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';
2961 }
2962
2963 // Multilang : we add translation
2964 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2965 $sql .= ", pl.label as label_translated";
2966 $sql .= ", pl.description as description_translated";
2967 $selectFields .= ", label_translated";
2968 $selectFields .= ", description_translated";
2969 }
2970 // Price by quantity
2971 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2972 $sql .= ", (SELECT pp.rowid FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid";
2973 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2974 $sql .= " AND price_level = " . ((int) $price_level);
2975 }
2976 $sql .= " ORDER BY date_price";
2977 $sql .= " DESC LIMIT 1) as price_rowid";
2978 $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
2979 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2980 $sql .= " AND price_level = " . ((int) $price_level);
2981 }
2982 $sql .= " ORDER BY date_price";
2983 $sql .= " DESC LIMIT 1) as price_by_qty";
2984 $selectFields .= ", price_rowid, price_by_qty";
2985 }
2986
2987 $sql .= " FROM ".$this->db->prefix()."product as p";
2988
2989 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_FORCE_INDEX')) {
2990 $sql .= " USE INDEX (" . $this->db->sanitize(getDolGlobalString('MAIN_PRODUCT_FORCE_INDEX')) . ")";
2991 }
2992
2993 // Add from (left join) from hooks
2994 $parameters = array();
2995 $reshook = $hookmanager->executeHooks('selectProductsListFrom', $parameters); // Note that $action and $object may have been modified by hook
2996 $sql .= $hookmanager->resPrint;
2997
2998 if (count($warehouseStatusArray)) {
2999 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_stock as ps on ps.fk_product = p.rowid";
3000 $sql .= " LEFT JOIN " . $this->db->prefix() . "entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (" . getEntity('stock') . ")";
3001 $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.
3002 }
3003
3004 // include search in supplier ref
3005 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
3006 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
3007 }
3008
3009 //Price by customer
3010 if ((getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !empty($socid)) {
3011 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_customer_price as pcp ON pcp.fk_soc=" . ((int) $socid) . " AND pcp.fk_product=p.rowid";
3012 }
3013 // Units
3014 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3015 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3016 }
3017 // Multilang : we add translation
3018 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3019 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_lang as pl ON pl.fk_product = p.rowid ";
3020 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE') && !empty($socid)) {
3021 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
3022 $soc = new Societe($this->db);
3023 $result = $soc->fetch($socid);
3024 if ($result > 0 && !empty($soc->default_lang)) {
3025 $sql .= " AND pl.lang = '" . $this->db->escape($soc->default_lang) . "'";
3026 } else {
3027 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
3028 }
3029 } else {
3030 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
3031 }
3032 }
3033
3034 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
3035 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_attribute_combination pac ON pac.fk_product_child = p.rowid";
3036 }
3037
3038 $sql .= ' WHERE p.entity IN (' . getEntity('product') . ')';
3039
3040 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
3041 $sql .= " AND pac.rowid IS NULL";
3042 }
3043
3044 if ($finished == 0) {
3045 $sql .= " AND p.finished = " . ((int) $finished);
3046 } elseif ($finished == 1) {
3047 $sql .= " AND p.finished = ".((int) $finished);
3048 }
3049 if ($status >= 0) {
3050 $sql .= " AND p.tosell = ".((int) $status);
3051 }
3052 if ($status_purchase >= 0) {
3053 $sql .= " AND p.tobuy = " . ((int) $status_purchase);
3054 }
3055 // Filter by product type
3056 if (strval($filtertype) != '') {
3057 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3058 } elseif (!isModEnabled('product')) { // when product module is disabled, show services only
3059 $sql .= " AND p.fk_product_type = 1";
3060 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
3061 $sql .= " AND p.fk_product_type = 0";
3062 }
3063
3064 if ((int) $warehouseId > 0) {
3065 $sql .= " AND EXISTS (SELECT psw.fk_product FROM " . $this->db->prefix() . "product_stock as psw WHERE psw.reel>0 AND psw.fk_entrepot=".(int) $warehouseId." AND psw.fk_product = p.rowid)";
3066 }
3067
3068 // Add where from hooks
3069 $parameters = array();
3070 $reshook = $hookmanager->executeHooks('selectProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3071 $sql .= $hookmanager->resPrint;
3072 // Add criteria on ref/label
3073 if ($filterkey != '') {
3074 $sql .= ' AND (';
3075 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3076 // For natural search
3077 $search_crit = explode(' ', $filterkey);
3078 $i = 0;
3079 if (count($search_crit) > 1) {
3080 $sql .= "(";
3081 }
3082 foreach ($search_crit as $crit) {
3083 if ($i > 0) {
3084 $sql .= " AND ";
3085 }
3086 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3087 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3088 $sql .= " OR pl.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3089 }
3090 if ((getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !empty($socid)) {
3091 $sql .= " OR pcp.ref_customer LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3092 }
3093 if (getDolGlobalString('PRODUCT_AJAX_SEARCH_ON_DESCRIPTION')) {
3094 $sql .= " OR p.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3095 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3096 $sql .= " OR pl.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3097 }
3098 }
3099 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
3100 $sql .= " OR pfp.ref_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3101 }
3102 $sql .= ")";
3103 $i++;
3104 }
3105 if (count($search_crit) > 1) {
3106 $sql .= ")";
3107 }
3108 if (isModEnabled('barcode')) {
3109 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3110 }
3111 $sql .= ')';
3112 }
3113 if (count($warehouseStatusArray)) {
3114 $sql .= " GROUP BY " . $selectFields;
3115 }
3116
3117 //Sort by category
3118 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
3119 $sql .= " ORDER BY categorie_product_id ";
3120 //ASC OR DESC order
3121 (getDolGlobalInt('PRODUCT_SORT_BY_CATEGORY') == 1) ? $sql .= "ASC" : $sql .= "DESC";
3122 } else {
3123 $sql .= $this->db->order("p.ref");
3124 }
3125
3126 $sql .= $this->db->plimit($limit, 0);
3127
3128 // Build output string
3129 dol_syslog(get_class($this) . "::select_produits_list search products", LOG_DEBUG);
3130 $result = $this->db->query($sql);
3131 if ($result) {
3132 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3133 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3134 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3135
3136 $num = $this->db->num_rows($result);
3137
3138 $events = array();
3139
3140 if (!$forcecombo) {
3141 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
3142 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
3143 }
3144
3145 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
3146
3147 $textifempty = '';
3148 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
3149 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
3150 if (getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3151 if ($showempty && !is_numeric($showempty)) {
3152 $textifempty = $langs->trans($showempty);
3153 } else {
3154 $textifempty .= $langs->trans("All");
3155 }
3156 } else {
3157 if ($showempty && !is_numeric($showempty)) {
3158 $textifempty = $langs->trans($showempty);
3159 }
3160 }
3161 if ($showempty) {
3162 $out .= '<option value="-1" selected>' . ($textifempty ? $textifempty : '&nbsp;') . '</option>';
3163 }
3164
3165 $i = 0;
3166 while ($num && $i < $num) {
3167 $opt = '';
3168 $optJson = array();
3169 $objp = $this->db->fetch_object($result);
3170
3171 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
3172 $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type";
3173 $sql .= " FROM " . $this->db->prefix() . "product_price_by_qty";
3174 $sql .= " WHERE fk_product_price = " . ((int) $objp->price_rowid);
3175 $sql .= " ORDER BY quantity ASC";
3176
3177 dol_syslog(get_class($this) . "::select_produits_list search prices by qty", LOG_DEBUG);
3178 $result2 = $this->db->query($sql);
3179 if ($result2) {
3180 $nb_prices = $this->db->num_rows($result2);
3181 $j = 0;
3182 while ($nb_prices && $j < $nb_prices) {
3183 $objp2 = $this->db->fetch_object($result2);
3184
3185 $objp->price_by_qty_rowid = $objp2->rowid;
3186 $objp->price_by_qty_price_base_type = $objp2->price_base_type;
3187 $objp->price_by_qty_quantity = $objp2->quantity;
3188 $objp->price_by_qty_unitprice = $objp2->unitprice;
3189 $objp->price_by_qty_remise_percent = $objp2->remise_percent;
3190 // For backward compatibility
3191 $objp->quantity = $objp2->quantity;
3192 $objp->price = $objp2->price;
3193 $objp->unitprice = $objp2->unitprice;
3194 $objp->remise_percent = $objp2->remise_percent;
3195
3196 //$objp->tva_tx is not overwritten by $objp2 value
3197 //$objp->default_vat_code is not overwritten by $objp2 value
3198
3199 $this->constructProductListOption($objp, $opt, $optJson, 0, $selected, $hidepriceinlabel, $filterkey);
3200
3201 $j++;
3202
3203 // Add new entry
3204 // "key" value of json key array is used by jQuery automatically as selected value
3205 // "label" value of json key array is used by jQuery automatically as text for combo box
3206 $out .= $opt;
3207 array_push($outarray, $optJson);
3208 }
3209 }
3210 } else {
3211 if (isModEnabled('dynamicprices') && !empty($objp->fk_price_expression)) {
3212 $price_product = new Product($this->db);
3213 $price_product->fetch($objp->rowid, '', '', 1);
3214
3215 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3216 $priceparser = new PriceParser($this->db);
3217 $price_result = $priceparser->parseProduct($price_product);
3218 if ($price_result >= 0) {
3219 $objp->price = $price_result;
3220 $objp->unitprice = $price_result;
3221 //Calculate the VAT
3222 $objp->price_ttc = (float) price2num($objp->price) * (1 + ($objp->tva_tx / 100));
3223 $objp->price_ttc = price2num($objp->price_ttc, 'MU');
3224 }
3225 }
3226 if (getDolGlobalInt('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES') && !empty($objp->custprice)) {
3227 $price_level = '';
3228 }
3229 $this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected, $hidepriceinlabel, $filterkey);
3230 // Add new entry
3231 // "key" value of json key array is used by jQuery automatically as selected value
3232 // "label" value of json key array is used by jQuery automatically as text for combo box
3233 $out .= $opt;
3234 array_push($outarray, $optJson);
3235 }
3236
3237 $i++;
3238 }
3239
3240 $out .= '</select>';
3241
3242 $this->db->free($result);
3243
3244 if (empty($outputmode)) {
3245 return $out;
3246 }
3247
3248 return $outarray;
3249 } else {
3250 dol_print_error($this->db);
3251 }
3252
3253 return '';
3254 }
3255
3271 protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0)
3272 {
3273 global $langs, $conf, $user;
3274 global $hookmanager;
3275
3276 $outkey = '';
3277 $outval = '';
3278 $outref = '';
3279 $outlabel = '';
3280 $outlabel_translated = '';
3281 $outdesc = '';
3282 $outdesc_translated = '';
3283 $outbarcode = '';
3284 $outorigin = '';
3285 $outtype = '';
3286 $outprice_ht = '';
3287 $outprice_ttc = '';
3288 $outpricebasetype = '';
3289 $outtva_tx = '';
3290 $outdefault_vat_code = '';
3291 $outqty = 1;
3292 $outdiscount = 0;
3293
3294 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3295
3296 $label = $objp->label;
3297 if (!empty($objp->label_translated)) {
3298 $label = $objp->label_translated;
3299 }
3300 if (!empty($filterkey) && $filterkey != '') {
3301 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3302 }
3303
3304 $outkey = $objp->rowid;
3305 $outref = $objp->ref;
3306 $outrefcust = empty($objp->custref) ? '' : $objp->custref;
3307 $outlabel = $objp->label;
3308 $outdesc = $objp->description;
3309 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3310 $outlabel_translated = $objp->label_translated;
3311 $outdesc_translated = $objp->description_translated;
3312 }
3313 $outbarcode = $objp->barcode;
3314 $outorigin = $objp->fk_country;
3315 $outpbq = empty($objp->price_by_qty_rowid) ? '' : $objp->price_by_qty_rowid;
3316
3317 $outtype = $objp->fk_product_type;
3318 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3319 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3320
3321 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3322 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
3323 }
3324
3325 // Units
3326 $outvalUnits = '';
3327 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3328 if (!empty($objp->unit_short)) {
3329 $outvalUnits .= ' - ' . $objp->unit_short;
3330 }
3331 }
3332 if (getDolGlobalString('PRODUCT_SHOW_DIMENSIONS_IN_COMBO')) {
3333 if (!empty($objp->weight) && $objp->weight_units !== null) {
3334 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3335 $outvalUnits .= ' - ' . $unitToShow;
3336 }
3337 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3338 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3339 $outvalUnits .= ' - ' . $unitToShow;
3340 }
3341 if (!empty($objp->surface) && $objp->surface_units !== null) {
3342 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3343 $outvalUnits .= ' - ' . $unitToShow;
3344 }
3345 if (!empty($objp->volume) && $objp->volume_units !== null) {
3346 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3347 $outvalUnits .= ' - ' . $unitToShow;
3348 }
3349 }
3350 if ($outdurationvalue && $outdurationunit) {
3351 $da = array(
3352 'h' => $langs->trans('Hour'),
3353 'd' => $langs->trans('Day'),
3354 'w' => $langs->trans('Week'),
3355 'm' => $langs->trans('Month'),
3356 'y' => $langs->trans('Year')
3357 );
3358 if (isset($da[$outdurationunit])) {
3359 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3360 }
3361 }
3362
3363 // Set stocktag (stock too low or not or unknown)
3364 $stocktag = 0;
3365 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3366 if ($user->hasRight('stock', 'lire')) {
3367 if ($objp->stock > 0) {
3368 $stocktag = 1;
3369 } elseif ($objp->stock <= 0) {
3370 $stocktag = -1;
3371 }
3372 }
3373 }
3374
3375 // Set $labeltoshow
3376 $labeltoshow = '';
3377 $labeltoshow .= $objp->ref;
3378 if (!empty($objp->custref)) {
3379 $labeltoshow .= ' (' . $objp->custref . ')';
3380 }
3381 if ($outbarcode) {
3382 $labeltoshow .= ' (' . $outbarcode . ')';
3383 }
3384 $labeltoshow .= ' - ' . dol_trunc($label, $maxlengtharticle);
3385 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3386 $labeltoshow .= ' (' . getCountry($outorigin, '1') . ')';
3387 }
3388
3389 // Set $labltoshowhtml
3390 $labeltoshowhtml = '';
3391 $labeltoshowhtml .= $objp->ref;
3392 if (!empty($objp->custref)) {
3393 $labeltoshowhtml .= ' (' . $objp->custref . ')';
3394 }
3395 if (!empty($filterkey) && $filterkey != '') {
3396 $labeltoshowhtml = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $labeltoshowhtml, 1);
3397 }
3398 if ($outbarcode) {
3399 $labeltoshowhtml .= ' (' . $outbarcode . ')';
3400 }
3401 $labeltoshowhtml .= ' - ' . dol_trunc($label, $maxlengtharticle);
3402 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3403 $labeltoshowhtml .= ' (' . getCountry($outorigin, '1') . ')';
3404 }
3405
3406 // Stock
3407 $labeltoshowstock = '';
3408 $labeltoshowhtmlstock = '';
3409 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3410 if ($user->hasRight('stock', 'lire')) {
3411 $labeltoshowstock .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3412
3413 if ($objp->stock > 0) {
3414 $labeltoshowhtmlstock .= ' - <span class="product_line_stock_ok">';
3415 } elseif ($objp->stock <= 0) {
3416 $labeltoshowhtmlstock .= ' - <span class="product_line_stock_too_low">';
3417 }
3418 $labeltoshowhtmlstock .= $langs->transnoentities("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3419 $labeltoshowhtmlstock .= '</span>';
3420
3421 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3422 $langs->load("stocks");
3423
3424 $tmpproduct = new Product($this->db);
3425 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3426 $tmpproduct->load_virtual_stock();
3427 $virtualstock = $tmpproduct->stock_theorique;
3428
3429 $labeltoshowstock .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3430
3431 $labeltoshowhtmlstock .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3432 if ($virtualstock > 0) {
3433 $labeltoshowhtmlstock .= '<span class="product_line_stock_ok">';
3434 } elseif ($virtualstock <= 0) {
3435 $labeltoshowhtmlstock .= '<span class="product_line_stock_too_low">';
3436 }
3437 $labeltoshowhtmlstock .= $virtualstock;
3438 $labeltoshowhtmlstock .= '</span>';
3439
3440 unset($tmpproduct);
3441 }
3442 }
3443 }
3444
3445 // Price
3446 $found = 0;
3447 $labeltoshowprice = '';
3448 $labeltoshowhtmlprice = '';
3449 // If we need a particular price level (from 1 to n)
3450 if (empty($hidepriceinlabel) && $price_level >= 1 && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES'))) {
3451 $sql = "SELECT price, price_ttc, price_base_type, tva_tx, default_vat_code";
3452 $sql .= " FROM " . $this->db->prefix() . "product_price";
3453 $sql .= " WHERE fk_product = " . ((int) $objp->rowid);
3454 $sql .= " AND entity IN (" . getEntity('productprice') . ")";
3455 $sql .= " AND price_level = " . ((int) $price_level);
3456 $sql .= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid.
3457 $sql .= " LIMIT 1";
3458
3459 dol_syslog(get_class($this) . '::constructProductListOption search price for product ' . $objp->rowid . ' AND level ' . $price_level, LOG_DEBUG);
3460 $result2 = $this->db->query($sql);
3461 if ($result2) {
3462 $objp2 = $this->db->fetch_object($result2);
3463 if ($objp2) {
3464 $found = 1;
3465 if ($objp2->price_base_type == 'HT') {
3466 $labeltoshowprice .= ' - ' . price($objp2->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3467 $labeltoshowhtmlprice .= ' - ' . price($objp2->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3468 } else {
3469 $labeltoshowprice .= ' - ' . price($objp2->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3470 $labeltoshowhtmlprice .= ' - ' . price($objp2->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3471 }
3472 $outprice_ht = price($objp2->price);
3473 $outprice_ttc = price($objp2->price_ttc);
3474 $outpricebasetype = $objp2->price_base_type;
3475 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
3476 $outtva_tx = $objp2->tva_tx; // We use the vat rate on line of multiprice
3477 $outdefault_vat_code = $objp2->default_vat_code; // We use the vat code on line of multiprice
3478 } else {
3479 $outtva_tx = $objp->tva_tx; // We use the vat rate of product, not the one on line of multiprice
3480 $outdefault_vat_code = $objp->default_vat_code; // We use the vat code or product, not the one on line of multiprice
3481 }
3482 }
3483 } else {
3484 dol_print_error($this->db);
3485 }
3486 }
3487
3488 // Price by quantity
3489 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1 && (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3490 $found = 1;
3491 $outqty = $objp->quantity;
3492 $outdiscount = $objp->remise_percent;
3493 if ($objp->quantity == 1) {
3494 $labeltoshowprice .= ' - ' . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/";
3495 $labeltoshowhtmlprice .= ' - ' . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/";
3496 $labeltoshowprice .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3497 $labeltoshowhtmlprice .= $langs->transnoentities("Unit");
3498 } else {
3499 $labeltoshowprice .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3500 $labeltoshowhtmlprice .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3501 $labeltoshowprice .= $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3502 $labeltoshowhtmlprice .= $langs->transnoentities("Units");
3503 }
3504
3505 $outprice_ht = price($objp->unitprice);
3506 $outprice_ttc = price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
3507 $outpricebasetype = $objp->price_base_type;
3508 $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
3509 $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
3510 }
3511 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1) {
3512 $labeltoshowprice .= " (" . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3513 $labeltoshowhtmlprice .= " (" . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3514 }
3515 if (empty($hidepriceinlabel) && !empty($objp->remise_percent) && $objp->remise_percent >= 1) {
3516 $labeltoshowprice .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3517 $labeltoshowhtmlprice .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3518 }
3519
3520 // Price by customer
3521 if (empty($hidepriceinlabel) && (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES'))) {
3522 if (!empty($objp->idprodcustprice)) {
3523 $found = 1;
3524
3525 if ($objp->custprice_base_type == 'HT') {
3526 $labeltoshowprice .= ' - ' . price($objp->custprice, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3527 $labeltoshowhtmlprice .= ' - ' . price($objp->custprice, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3528 } else {
3529 $labeltoshowprice .= ' - ' . price($objp->custprice_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3530 $labeltoshowhtmlprice .= ' - ' . price($objp->custprice_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3531 }
3532
3533 $outprice_ht = price($objp->custprice);
3534 $outprice_ttc = price($objp->custprice_ttc);
3535 $outpricebasetype = $objp->custprice_base_type;
3536 $outtva_tx = $objp->custtva_tx;
3537 $outdefault_vat_code = $objp->custdefault_vat_code;
3538 }
3539 }
3540
3541 // If level no defined or multiprice not found, we used the default price
3542 if (empty($hidepriceinlabel) && !$found) {
3543 if ($objp->price_base_type == 'HT') {
3544 $labeltoshowprice .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3545 $labeltoshowhtmlprice .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3546 } else {
3547 $labeltoshowprice .= ' - ' . price($objp->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3548 $labeltoshowhtmlprice .= ' - ' . price($objp->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3549 }
3550 $outprice_ht = price($objp->price);
3551 $outprice_ttc = price($objp->price_ttc);
3552 $outpricebasetype = $objp->price_base_type;
3553 $outtva_tx = $objp->tva_tx;
3554 $outdefault_vat_code = $objp->default_vat_code;
3555 }
3556
3557
3558 // Build options
3559 $opt = '<option value="' . $objp->rowid . '"';
3560 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
3561 if (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0) {
3562 $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 . '"';
3563 }
3564 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
3565 $opt .= ' data-labeltrans="' . $outlabel_translated . '"';
3566 $opt .= ' data-desctrans="' . dol_escape_htmltag($outdesc_translated) . '"';
3567 }
3568
3569 if ($stocktag == 1) {
3570 $opt .= ' class="product_line_stock_ok" data-html="'.$labeltoshowhtml.$outvalUnits.$labeltoshowhtmlprice.dolPrintHTMLForAttribute($labeltoshowhtmlstock).'"';
3571 //$opt .= ' class="product_line_stock_ok"';
3572 }
3573 if ($stocktag == -1) {
3574 $opt .= ' class="product_line_stock_too_low" data-html="'.$labeltoshowhtml.$outvalUnits.$labeltoshowhtmlprice.dolPrintHTMLForAttribute($labeltoshowhtmlstock).'"';
3575 //$opt .= ' class="product_line_stock_too_low"';
3576 }
3577
3578 $opt .= '>';
3579
3580 // Ref, barcode, country
3581 $opt .= $labeltoshow;
3582 $outval .= $labeltoshowhtml;
3583
3584 // Units
3585 $opt .= $outvalUnits;
3586 $outval .= $outvalUnits;
3587
3588 // Price
3589 $opt .= $labeltoshowprice;
3590 $outval .= $labeltoshowhtmlprice;
3591
3592 // Stock
3593 $opt .= $labeltoshowstock;
3594 $outval .= $labeltoshowhtmlstock;
3595
3596
3597 $parameters = array('objp' => $objp);
3598 $reshook = $hookmanager->executeHooks('constructProductListOption', $parameters); // Note that $action and $object may have been modified by hook
3599 if (empty($reshook)) {
3600 $opt .= $hookmanager->resPrint;
3601 } else {
3602 $opt = $hookmanager->resPrint;
3603 }
3604
3605 $opt .= "</option>\n";
3606 $optJson = array(
3607 'key' => $outkey,
3608 'value' => $outref,
3609 'label' => $outval,
3610 'label2' => $outlabel,
3611 'desc' => $outdesc,
3612 'type' => $outtype,
3613 'price_ht' => price2num($outprice_ht),
3614 'price_ttc' => price2num($outprice_ttc),
3615 'price_ht_locale' => price(price2num($outprice_ht)),
3616 'price_ttc_locale' => price(price2num($outprice_ttc)),
3617 'pricebasetype' => $outpricebasetype,
3618 'tva_tx' => $outtva_tx,
3619 'default_vat_code' => $outdefault_vat_code,
3620 'qty' => $outqty,
3621 'discount' => $outdiscount,
3622 'duration_value' => $outdurationvalue,
3623 'duration_unit' => $outdurationunit,
3624 'pbq' => $outpbq,
3625 'labeltrans' => $outlabel_translated,
3626 'desctrans' => $outdesc_translated,
3627 'ref_customer' => $outrefcust
3628 );
3629 }
3630
3631 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3632
3648 public function select_produits_fournisseurs($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $ajaxoptions = array(), $hidelabel = 0, $alsoproductwithnosupplierprice = 0, $morecss = '', $placeholder = '')
3649 {
3650 // phpcs:enable
3651 global $langs, $conf;
3652 global $price_level, $status, $finished;
3653
3654 if (!isset($status)) {
3655 $status = 1;
3656 }
3657
3658 $selected_input_value = '';
3659 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3660 if ($selected > 0) {
3661 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3662 $producttmpselect = new Product($this->db);
3663 $producttmpselect->fetch($selected);
3664 $selected_input_value = $producttmpselect->ref;
3665 unset($producttmpselect);
3666 }
3667
3668 // mode=2 means suppliers products
3669 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=2&status=' . $status . '&finished=' . $finished . '&alsoproductwithnosupplierprice=' . $alsoproductwithnosupplierprice;
3670 print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, getDolGlobalInt('PRODUIT_USE_SEARCH_TO_SELECT'), 0, $ajaxoptions);
3671
3672 print($hidelabel ? '' : $langs->trans("RefOrLabel") . ' : ') . '<input type="text" class="'.$morecss.'" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . $placeholder . '"' : '') . '>';
3673 } else {
3674 print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', $status, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder);
3675 }
3676 }
3677
3678 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3679
3698 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 = '')
3699 {
3700 // phpcs:enable
3701 global $langs, $conf, $user;
3702 global $hookmanager;
3703
3704 $out = '';
3705 $outarray = array();
3706
3707 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3708
3709 $langs->load('stocks');
3710 // Units
3711 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3712 $langs->load('other');
3713 }
3714
3715 $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,";
3716 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice, pfp.barcode";
3717 $sql .= ", pfp.multicurrency_code, pfp.multicurrency_unitprice";
3718 $sql .= ", pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.default_vat_code, pfp.fk_soc, s.nom as name";
3719 $sql .= ", pfp.supplier_reputation";
3720 // if we use supplier description of the products
3721 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3722 $sql .= ", pfp.desc_fourn as description";
3723 } else {
3724 $sql .= ", p.description";
3725 }
3726 // Units
3727 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3728 $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";
3729 }
3730 $sql .= " FROM " . $this->db->prefix() . "product as p";
3731 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (" . getEntity('product') . ") )";
3732 if ($socid > 0) {
3733 $sql .= " AND pfp.fk_soc = " . ((int) $socid);
3734 }
3735 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3736 // Units
3737 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3738 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3739 }
3740 $sql .= " WHERE p.entity IN (" . getEntity('product') . ")";
3741 if ($statut != -1) {
3742 $sql .= " AND p.tobuy = " . ((int) $statut);
3743 }
3744 if (strval($filtertype) != '') {
3745 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3746 }
3747 if (!empty($filtre)) {
3748 $sql .= " " . $filtre;
3749 }
3750 // Add where from hooks
3751 $parameters = array();
3752 $reshook = $hookmanager->executeHooks('selectSuppliersProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3753 $sql .= $hookmanager->resPrint;
3754 // Add criteria on ref/label
3755 if ($filterkey != '') {
3756 $sql .= ' AND (';
3757 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3758 // For natural search
3759 $search_crit = explode(' ', $filterkey);
3760 $i = 0;
3761 if (count($search_crit) > 1) {
3762 $sql .= "(";
3763 }
3764 foreach ($search_crit as $crit) {
3765 if ($i > 0) {
3766 $sql .= " AND ";
3767 }
3768 $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) . "%'";
3769 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3770 $sql .= " OR pfp.desc_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3771 }
3772 $sql .= ")";
3773 $i++;
3774 }
3775 if (count($search_crit) > 1) {
3776 $sql .= ")";
3777 }
3778 if (isModEnabled('barcode')) {
3779 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3780 $sql .= " OR pfp.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3781 }
3782 $sql .= ')';
3783 }
3784 $sql .= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC";
3785 $sql .= $this->db->plimit($limit, 0);
3786
3787 // Build output string
3788
3789 dol_syslog(get_class($this) . "::select_produits_fournisseurs_list", LOG_DEBUG);
3790 $result = $this->db->query($sql);
3791 if ($result) {
3792 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3793 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3794
3795 $num = $this->db->num_rows($result);
3796
3797 //$out.='<select class="flat" id="select'.$htmlname.'" name="'.$htmlname.'">'; // remove select to have id same with combo and ajax
3798 $out .= '<select class="flat ' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '">';
3799 if (!$selected) {
3800 $out .= '<option value="-1" selected>' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3801 } else {
3802 $out .= '<option value="-1">' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3803 }
3804
3805 $i = 0;
3806 while ($i < $num) {
3807 $objp = $this->db->fetch_object($result);
3808
3809 if (is_null($objp->idprodfournprice)) {
3810 // There is no supplier price found, we will use the vat rate for sale
3811 $objp->tva_tx = $objp->tva_tx_sale;
3812 $objp->default_vat_code = $objp->default_vat_code_sale;
3813 }
3814
3815 $outkey = $objp->idprodfournprice; // id in table of price
3816 if (!$outkey && $alsoproductwithnosupplierprice) {
3817 $outkey = 'idprod_' . $objp->rowid; // id of product
3818 }
3819
3820 $outref = $objp->ref;
3821 $outbarcode = $objp->barcode;
3822 $outqty = 1;
3823 $outdiscount = 0;
3824 $outtype = $objp->fk_product_type;
3825 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3826 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3827
3828 // Units
3829 $outvalUnits = '';
3830 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3831 if (!empty($objp->unit_short)) {
3832 $outvalUnits .= ' - ' . $objp->unit_short;
3833 }
3834 if (!empty($objp->weight) && $objp->weight_units !== null) {
3835 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3836 $outvalUnits .= ' - ' . $unitToShow;
3837 }
3838 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3839 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3840 $outvalUnits .= ' - ' . $unitToShow;
3841 }
3842 if (!empty($objp->surface) && $objp->surface_units !== null) {
3843 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3844 $outvalUnits .= ' - ' . $unitToShow;
3845 }
3846 if (!empty($objp->volume) && $objp->volume_units !== null) {
3847 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3848 $outvalUnits .= ' - ' . $unitToShow;
3849 }
3850 if ($outdurationvalue && $outdurationunit) {
3851 $da = array(
3852 'h' => $langs->trans('Hour'),
3853 'd' => $langs->trans('Day'),
3854 'w' => $langs->trans('Week'),
3855 'm' => $langs->trans('Month'),
3856 'y' => $langs->trans('Year')
3857 );
3858 if (isset($da[$outdurationunit])) {
3859 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3860 }
3861 }
3862 }
3863
3864 $objRef = $objp->ref;
3865 if ($filterkey && $filterkey != '') {
3866 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3867 }
3868 $objRefFourn = $objp->ref_fourn;
3869 if ($filterkey && $filterkey != '') {
3870 $objRefFourn = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRefFourn, 1);
3871 }
3872 $label = $objp->label;
3873 if ($filterkey && $filterkey != '') {
3874 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3875 }
3876
3877 switch ($objp->fk_product_type) {
3879 $picto = 'product';
3880 break;
3882 $picto = 'service';
3883 break;
3884 default:
3885 $picto = '';
3886 break;
3887 }
3888
3889 if (empty($picto)) {
3890 $optlabel = '';
3891 } else {
3892 $optlabel = img_object('', $picto, 'class="paddingright classfortooltip"', 0, 0, 1);
3893 }
3894
3895 $optlabel .= $objp->ref;
3896 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3897 $optlabel .= ' <span class="opacitymedium">(' . $objp->ref_fourn . ')</span>';
3898 }
3899 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3900 $optlabel .= ' (' . $outbarcode . ')';
3901 }
3902 $optlabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3903
3904 $outvallabel = $objRef;
3905 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3906 $outvallabel .= ' (' . $objRefFourn . ')';
3907 }
3908 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3909 $outvallabel .= ' (' . $outbarcode . ')';
3910 }
3911 $outvallabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3912
3913 // Units
3914 $optlabel .= $outvalUnits;
3915 $outvallabel .= $outvalUnits;
3916
3917 if (!empty($objp->idprodfournprice)) {
3918 $outqty = $objp->quantity;
3919 $outdiscount = $objp->remise_percent;
3920 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3921 $prod_supplier = new ProductFournisseur($this->db);
3922 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3923 $prod_supplier->id = $objp->fk_product;
3924 $prod_supplier->fourn_qty = $objp->quantity;
3925 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3926 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3927
3928 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3929 $priceparser = new PriceParser($this->db);
3930 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3931 if ($price_result >= 0) {
3932 $objp->fprice = $price_result;
3933 if ($objp->quantity >= 1) {
3934 $objp->unitprice = $objp->fprice / $objp->quantity; // Replace dynamically unitprice
3935 }
3936 }
3937 }
3938 if ($objp->quantity == 1) {
3939 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3940 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/";
3941 $optlabel .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3942 $outvallabel .= $langs->transnoentities("Unit");
3943 } else {
3944 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3945 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3946 $optlabel .= ' ' . $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3947 $outvallabel .= ' ' . $langs->transnoentities("Units");
3948 }
3949
3950 if ($objp->quantity > 1) {
3951 $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
3952 $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
3953 }
3954 if ($objp->remise_percent >= 1) {
3955 $optlabel .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3956 $outvallabel .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3957 }
3958 if ($objp->duration) {
3959 $optlabel .= " - " . $objp->duration;
3960 $outvallabel .= " - " . $objp->duration;
3961 }
3962 if (!$socid) {
3963 $optlabel .= " - " . dol_trunc($objp->name, 8);
3964 $outvallabel .= " - " . dol_trunc($objp->name, 8);
3965 }
3966 if ($objp->supplier_reputation) {
3967 //TODO dictionary
3968 $reputations = array('' => $langs->trans('Standard'), 'FAVORITE' => $langs->trans('Favorite'), 'NOTTHGOOD' => $langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER' => $langs->trans('DoNotOrderThisProductToThisSupplier'));
3969
3970 $optlabel .= " - " . $reputations[$objp->supplier_reputation];
3971 $outvallabel .= " - " . $reputations[$objp->supplier_reputation];
3972 }
3973 } else {
3974 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3975 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3976 }
3977
3978 if (isModEnabled('stock') && $showstockinlist && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3979 $novirtualstock = ($showstockinlist == 2);
3980
3981 if ($user->hasRight('stock', 'lire')) {
3982 $outvallabel .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3983
3984 if ($objp->stock > 0) {
3985 $optlabel .= ' - <span class="product_line_stock_ok">';
3986 } elseif ($objp->stock <= 0) {
3987 $optlabel .= ' - <span class="product_line_stock_too_low">';
3988 }
3989 $optlabel .= $langs->transnoentities("Stock") . ':' . price(price2num($objp->stock, 'MS'));
3990 $optlabel .= '</span>';
3991 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3992 $langs->load("stocks");
3993
3994 $tmpproduct = new Product($this->db);
3995 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3996 $tmpproduct->load_virtual_stock();
3997 $virtualstock = $tmpproduct->stock_theorique;
3998
3999 $outvallabel .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
4000
4001 $optlabel .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
4002 if ($virtualstock > 0) {
4003 $optlabel .= '<span class="product_line_stock_ok">';
4004 } elseif ($virtualstock <= 0) {
4005 $optlabel .= '<span class="product_line_stock_too_low">';
4006 }
4007 $optlabel .= $virtualstock;
4008 $optlabel .= '</span>';
4009
4010 unset($tmpproduct);
4011 }
4012 }
4013 }
4014
4015 $optstart = '<option value="' . $outkey . '"';
4016 if ($selected && $selected == $objp->idprodfournprice) {
4017 $optstart .= ' selected';
4018 }
4019 if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) {
4020 $optstart .= ' disabled';
4021 }
4022
4023 if (!empty($objp->idprodfournprice) && $objp->idprodfournprice > 0) {
4024 $optstart .= ' data-product-id="' . dol_escape_htmltag($objp->rowid) . '"';
4025 $optstart .= ' data-price-id="' . dol_escape_htmltag($objp->idprodfournprice) . '"';
4026 $optstart .= ' data-qty="' . dol_escape_htmltag($objp->quantity) . '"';
4027 $optstart .= ' data-up="' . dol_escape_htmltag(price2num($objp->unitprice)) . '"';
4028 $optstart .= ' data-up-locale="' . dol_escape_htmltag(price($objp->unitprice)) . '"';
4029 $optstart .= ' data-discount="' . dol_escape_htmltag($outdiscount) . '"';
4030 $optstart .= ' data-tvatx="' . dol_escape_htmltag(price2num($objp->tva_tx)) . '"';
4031 $optstart .= ' data-tvatx-formated="' . dol_escape_htmltag(price($objp->tva_tx, 0, $langs, 1, -1, 2)) . '"';
4032 $optstart .= ' data-default-vat-code="' . dol_escape_htmltag($objp->default_vat_code) . '"';
4033 $optstart .= ' data-supplier-ref="' . dol_escape_htmltag($objp->ref_fourn) . '"';
4034 if (isModEnabled('multicurrency')) {
4035 $optstart .= ' data-multicurrency-code="' . dol_escape_htmltag($objp->multicurrency_code) . '"';
4036 $optstart .= ' data-multicurrency-up="' . dol_escape_htmltag($objp->multicurrency_unitprice) . '"';
4037 }
4038 }
4039 $optstart .= ' data-description="' . dol_escape_htmltag($objp->description, 0, 1) . '"';
4040
4041 $outarrayentry = array(
4042 'key' => $outkey,
4043 'value' => $outref,
4044 'label' => $outvallabel,
4045 'qty' => $outqty,
4046 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
4047 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
4048 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
4049 'tva_tx_formated' => price($objp->tva_tx, 0, $langs, 1, -1, 2),
4050 'tva_tx' => price2num($objp->tva_tx),
4051 'default_vat_code' => $objp->default_vat_code,
4052 'supplier_ref' => $objp->ref_fourn,
4053 'discount' => $outdiscount,
4054 'type' => $outtype,
4055 'duration_value' => $outdurationvalue,
4056 'duration_unit' => $outdurationunit,
4057 'disabled' => empty($objp->idprodfournprice),
4058 'description' => $objp->description
4059 );
4060 if (isModEnabled('multicurrency')) {
4061 $outarrayentry['multicurrency_code'] = $objp->multicurrency_code;
4062 $outarrayentry['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
4063 }
4064
4065 $parameters = array(
4066 'objp' => &$objp,
4067 'optstart' => &$optstart,
4068 'optlabel' => &$optlabel,
4069 'outvallabel' => &$outvallabel,
4070 'outarrayentry' => &$outarrayentry,
4071 'fk_soc' => $socid
4072 );
4073 $reshook = $hookmanager->executeHooks('selectProduitsFournisseurListOption', $parameters, $this);
4074
4075
4076 // Add new entry
4077 // "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
4078 // "label" value of json key array is used by jQuery automatically as text for combo box
4079 $out .= $optstart . ' data-html="' . dol_escape_htmltag($optlabel) . '">' . $optlabel . "</option>\n";
4080 $outarraypush = array(
4081 'key' => $outkey,
4082 'value' => $outref,
4083 'label' => $outvallabel,
4084 'qty' => $outqty,
4085 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
4086 'price_qty_ht_locale' => price($objp->fprice),
4087 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
4088 'price_unit_ht_locale' => price($objp->unitprice),
4089 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
4090 'tva_tx_formated' => price($objp->tva_tx),
4091 'tva_tx' => price2num($objp->tva_tx),
4092 'default_vat_code' => $objp->default_vat_code,
4093 'supplier_ref' => $objp->ref_fourn,
4094 'discount' => $outdiscount,
4095 'type' => $outtype,
4096 'duration_value' => $outdurationvalue,
4097 'duration_unit' => $outdurationunit,
4098 'disabled' => empty($objp->idprodfournprice),
4099 'description' => $objp->description
4100 );
4101 if (isModEnabled('multicurrency')) {
4102 $outarraypush['multicurrency_code'] = $objp->multicurrency_code;
4103 $outarraypush['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
4104 }
4105 array_push($outarray, $outarraypush);
4106
4107 // Example of var_dump $outarray
4108 // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
4109 // ["label"]=>string(76) "ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
4110 // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false)
4111 //}
4112 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
4113 //$outval=array('label'=>'ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)');
4114 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
4115
4116 $i++;
4117 }
4118 $out .= '</select>';
4119
4120 $this->db->free($result);
4121
4122 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
4123 $out .= ajax_combobox($htmlname);
4124 } else {
4125 dol_print_error($this->db);
4126 }
4127
4128 if (empty($outputmode)) {
4129 return $out;
4130 }
4131 return $outarray;
4132 }
4133
4134 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4135
4144 public function select_product_fourn_price($productid, $htmlname = 'productfournpriceid', $selected_supplier = 0)
4145 {
4146 // phpcs:enable
4147 global $langs, $conf;
4148
4149 $langs->load('stocks');
4150
4151 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, pfp.fk_soc,";
4152 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,";
4153 $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name";
4154 $sql .= " FROM " . $this->db->prefix() . "product as p";
4155 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
4156 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
4157 $sql .= " WHERE pfp.entity IN (" . getEntity('productsupplierprice') . ")";
4158 $sql .= " AND p.tobuy = 1";
4159 $sql .= " AND s.fournisseur = 1";
4160 $sql .= " AND p.rowid = " . ((int) $productid);
4161 if (!getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED')) {
4162 $sql .= " ORDER BY s.nom, pfp.ref_fourn DESC";
4163 } else {
4164 $sql .= " ORDER BY pfp.unitprice ASC";
4165 }
4166
4167 dol_syslog(get_class($this) . "::select_product_fourn_price", LOG_DEBUG);
4168 $result = $this->db->query($sql);
4169
4170 if ($result) {
4171 $num = $this->db->num_rows($result);
4172
4173 $form = '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4174
4175 if (!$num) {
4176 $form .= '<option value="0">-- ' . $langs->trans("NoSupplierPriceDefinedForThisProduct") . ' --</option>';
4177 } else {
4178 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
4179 $form .= '<option value="0">&nbsp;</option>';
4180
4181 $i = 0;
4182 while ($i < $num) {
4183 $objp = $this->db->fetch_object($result);
4184
4185 $opt = '<option value="' . $objp->idprodfournprice . '"';
4186 //if there is only one supplier, preselect it
4187 if ($num == 1 || ($selected_supplier > 0 && $objp->fk_soc == $selected_supplier) || ($i == 0 && getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED'))) {
4188 $opt .= ' selected';
4189 }
4190 $opt .= '>' . $objp->name . ' - ' . $objp->ref_fourn . ' - ';
4191
4192 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
4193 $prod_supplier = new ProductFournisseur($this->db);
4194 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
4195 $prod_supplier->id = $productid;
4196 $prod_supplier->fourn_qty = $objp->quantity;
4197 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
4198 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
4199
4200 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
4201 $priceparser = new PriceParser($this->db);
4202 $price_result = $priceparser->parseProductSupplier($prod_supplier);
4203 if ($price_result >= 0) {
4204 $objp->fprice = $price_result;
4205 if ($objp->quantity >= 1) {
4206 $objp->unitprice = $objp->fprice / $objp->quantity;
4207 }
4208 }
4209 }
4210 if ($objp->quantity == 1) {
4211 $opt .= price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
4212 }
4213
4214 $opt .= $objp->quantity . ' ';
4215
4216 if ($objp->quantity == 1) {
4217 $opt .= $langs->trans("Unit");
4218 } else {
4219 $opt .= $langs->trans("Units");
4220 }
4221 if ($objp->quantity > 1) {
4222 $opt .= " - ";
4223 $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");
4224 }
4225 if ($objp->duration) {
4226 $opt .= " - " . $objp->duration;
4227 }
4228 $opt .= "</option>\n";
4229
4230 $form .= $opt;
4231 $i++;
4232 }
4233 }
4234
4235 $form .= '</select>';
4236 $this->db->free($result);
4237 return $form;
4238 } else {
4239 dol_print_error($this->db);
4240 return '';
4241 }
4242 }
4243
4244
4245 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4252 {
4253 // phpcs:enable
4254 global $langs;
4255
4256 $num = count($this->cache_conditions_paiements);
4257 if ($num > 0) {
4258 return 0; // Cache already loaded
4259 }
4260
4261 dol_syslog(__METHOD__, LOG_DEBUG);
4262
4263 $sql = "SELECT rowid, code, libelle as label, deposit_percent";
4264 $sql .= " FROM " . $this->db->prefix() . 'c_payment_term';
4265 $sql .= " WHERE entity IN (" . getEntity('c_payment_term') . ")";
4266 $sql .= " AND active > 0";
4267 $sql .= " ORDER BY sortorder";
4268
4269 $resql = $this->db->query($sql);
4270 if ($resql) {
4271 $num = $this->db->num_rows($resql);
4272 $i = 0;
4273 while ($i < $num) {
4274 $obj = $this->db->fetch_object($resql);
4275
4276 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4277 $label = ($langs->trans("PaymentConditionShort" . $obj->code) != "PaymentConditionShort" . $obj->code ? $langs->trans("PaymentConditionShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4278 $this->cache_conditions_paiements[$obj->rowid]['code'] = $obj->code;
4279 $this->cache_conditions_paiements[$obj->rowid]['label'] = $label;
4280 $this->cache_conditions_paiements[$obj->rowid]['deposit_percent'] = $obj->deposit_percent;
4281 $i++;
4282 }
4283
4284 //$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1); // We use the field sortorder of table
4285
4286 return $num;
4287 } else {
4288 dol_print_error($this->db);
4289 return -1;
4290 }
4291 }
4292
4293 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4294
4300 public function load_cache_availability()
4301 {
4302 // phpcs:enable
4303 global $langs;
4304
4305 $num = count($this->cache_availability); // TODO Use $conf->cache['availability'] instead of $this->cache_availability
4306 if ($num > 0) {
4307 return 0; // Cache already loaded
4308 }
4309
4310 dol_syslog(__METHOD__, LOG_DEBUG);
4311
4312 $langs->load('propal');
4313
4314 $sql = "SELECT rowid, code, label, position";
4315 $sql .= " FROM " . $this->db->prefix() . 'c_availability';
4316 $sql .= " WHERE active > 0";
4317
4318 $resql = $this->db->query($sql);
4319 if ($resql) {
4320 $num = $this->db->num_rows($resql);
4321 $i = 0;
4322 while ($i < $num) {
4323 $obj = $this->db->fetch_object($resql);
4324
4325 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4326 $label = ($langs->trans("AvailabilityType" . $obj->code) != "AvailabilityType" . $obj->code ? $langs->trans("AvailabilityType" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4327 $this->cache_availability[$obj->rowid]['code'] = $obj->code;
4328 $this->cache_availability[$obj->rowid]['label'] = $label;
4329 $this->cache_availability[$obj->rowid]['position'] = $obj->position;
4330 $i++;
4331 }
4332
4333 $this->cache_availability = dol_sort_array($this->cache_availability, 'position', 'asc', 0, 0, 1);
4334
4335 return $num;
4336 } else {
4337 dol_print_error($this->db);
4338 return -1;
4339 }
4340 }
4341
4352 public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0, $morecss = '')
4353 {
4354 global $langs, $user;
4355
4356 $this->load_cache_availability();
4357
4358 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4359
4360 print '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4361 if ($addempty) {
4362 print '<option value="0">&nbsp;</option>';
4363 }
4364 foreach ($this->cache_availability as $id => $arrayavailability) {
4365 if ($selected == $id) {
4366 print '<option value="' . $id . '" selected>';
4367 } else {
4368 print '<option value="' . $id . '">';
4369 }
4370 print dol_escape_htmltag($arrayavailability['label']);
4371 print '</option>';
4372 }
4373 print '</select>';
4374 if ($user->admin) {
4375 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4376 }
4377 print ajax_combobox($htmlname);
4378 }
4379
4385 public function loadCacheInputReason()
4386 {
4387 global $langs;
4388
4389 $num = count($this->cache_demand_reason); // TODO Use $conf->cache['input_reason'] instead of $this->cache_demand_reason
4390 if ($num > 0) {
4391 return 0; // Cache already loaded
4392 }
4393
4394 $sql = "SELECT rowid, code, label";
4395 $sql .= " FROM " . $this->db->prefix() . 'c_input_reason';
4396 $sql .= " WHERE active > 0";
4397
4398 $resql = $this->db->query($sql);
4399 if ($resql) {
4400 $num = $this->db->num_rows($resql);
4401 $i = 0;
4402 $tmparray = array();
4403 while ($i < $num) {
4404 $obj = $this->db->fetch_object($resql);
4405
4406 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4407 $label = ($obj->label != '-' ? $obj->label : '');
4408 if ($langs->trans("DemandReasonType" . $obj->code) != "DemandReasonType" . $obj->code) {
4409 $label = $langs->trans("DemandReasonType" . $obj->code); // So translation key DemandReasonTypeSRC_XXX will work
4410 }
4411 if ($langs->trans($obj->code) != $obj->code) {
4412 $label = $langs->trans($obj->code); // So translation key SRC_XXX will work
4413 }
4414
4415 $tmparray[$obj->rowid]['id'] = $obj->rowid;
4416 $tmparray[$obj->rowid]['code'] = $obj->code;
4417 $tmparray[$obj->rowid]['label'] = $label;
4418 $i++;
4419 }
4420
4421 $this->cache_demand_reason = dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1);
4422
4423 unset($tmparray);
4424 return $num;
4425 } else {
4426 dol_print_error($this->db);
4427 return -1;
4428 }
4429 }
4430
4443 public function selectInputReason($selected = '', $htmlname = 'demandreasonid', $exclude = '', $addempty = 0, $morecss = '', $notooltip = 0)
4444 {
4445 global $langs, $user;
4446
4447 $this->loadCacheInputReason();
4448
4449 print '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4450 if ($addempty) {
4451 print '<option value="0"' . (empty($selected) ? ' selected' : '') . '>&nbsp;</option>';
4452 }
4453 foreach ($this->cache_demand_reason as $id => $arraydemandreason) {
4454 if ($arraydemandreason['code'] == $exclude) {
4455 continue;
4456 }
4457
4458 if ($selected && ($selected == $arraydemandreason['id'] || $selected == $arraydemandreason['code'])) {
4459 print '<option value="' . $arraydemandreason['id'] . '" selected>';
4460 } else {
4461 print '<option value="' . $arraydemandreason['id'] . '">';
4462 }
4463 $label = $arraydemandreason['label']; // Translation of label was already done into the ->loadCacheInputReason
4464 print $langs->trans($label);
4465 print '</option>';
4466 }
4467 print '</select>';
4468 if ($user->admin && empty($notooltip)) {
4469 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4470 }
4471 print ajax_combobox('select_' . $htmlname);
4472 }
4473
4474 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4475
4482 {
4483 // phpcs:enable
4484 global $langs;
4485
4486 $num = count($this->cache_types_paiements); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_types_paiements
4487 if ($num > 0) {
4488 return $num; // Cache already loaded
4489 }
4490
4491 dol_syslog(__METHOD__, LOG_DEBUG);
4492
4493 $this->cache_types_paiements = array();
4494
4495 $sql = "SELECT id, code, libelle as label, type, active";
4496 $sql .= " FROM " . $this->db->prefix() . "c_paiement";
4497 $sql .= " WHERE entity IN (" . getEntity('c_paiement') . ")";
4498
4499 $resql = $this->db->query($sql);
4500 if ($resql) {
4501 $num = $this->db->num_rows($resql);
4502 $i = 0;
4503 while ($i < $num) {
4504 $obj = $this->db->fetch_object($resql);
4505
4506 // Si traduction existe, on l'utilise, sinon on prend le libelle par default
4507 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4508 $this->cache_types_paiements[$obj->id]['id'] = $obj->id;
4509 $this->cache_types_paiements[$obj->id]['code'] = $obj->code;
4510 $this->cache_types_paiements[$obj->id]['label'] = $label;
4511 $this->cache_types_paiements[$obj->id]['type'] = $obj->type;
4512 $this->cache_types_paiements[$obj->id]['active'] = $obj->active;
4513 $i++;
4514 }
4515
4516 $this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1);
4517
4518 return $num;
4519 } else {
4520 dol_print_error($this->db);
4521 return -1;
4522 }
4523 }
4524
4525
4526 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4527
4546 public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1, $noprint = 0)
4547 {
4548 // phpcs:enable
4549 $out = $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, $noinfoadmin, $morecss, $deposit_percent);
4550 if (empty($noprint)) {
4551 print $out;
4552 } else {
4553 return $out;
4554 }
4555 }
4556
4557
4574 public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4575 {
4576 global $langs, $user, $conf;
4577
4578 $out = '';
4579 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4580
4582
4583 // Set default value if not already set by caller
4584 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID')) {
4585 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TERM_ID", LOG_NOTICE);
4586 $selected = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID');
4587 }
4588
4589 $out .= '<select id="' . $htmlname . '" class="flat selectpaymentterms' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4590 if ($addempty) {
4591 $out .= '<option value="0">&nbsp;</option>';
4592 }
4593
4594 $selectedDepositPercent = null;
4595
4596 foreach ($this->cache_conditions_paiements as $id => $arrayconditions) {
4597 if ($filtertype <= 0 && !empty($arrayconditions['deposit_percent'])) {
4598 continue;
4599 }
4600
4601 if ($selected == $id) {
4602 $selectedDepositPercent = $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'];
4603 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '" selected>';
4604 } else {
4605 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '">';
4606 }
4607 $label = $arrayconditions['label'];
4608
4609 if (!empty($arrayconditions['deposit_percent'])) {
4610 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'], $label);
4611 }
4612
4613 $out .= $label;
4614 $out .= '</option>';
4615 }
4616 $out .= '</select>';
4617 if ($user->admin && empty($noinfoadmin)) {
4618 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4619 }
4620 $out .= ajax_combobox($htmlname);
4621
4622 if ($deposit_percent >= 0) {
4623 $out .= ' <span id="' . $htmlname . '_deposit_percent_container"' . (empty($selectedDepositPercent) ? ' style="display: none"' : '') . '>';
4624 $out .= $langs->trans('DepositPercent') . ' : ';
4625 $out .= '<input id="' . $htmlname . '_deposit_percent" name="' . $htmlname . '_deposit_percent" class="maxwidth50" value="' . $deposit_percent . '" />';
4626 $out .= '</span>';
4627 $out .= '
4628 <script nonce="' . getNonce() . '">
4629 $(document).ready(function () {
4630 $("#' . $htmlname . '").change(function () {
4631 let $selected = $(this).find("option:selected");
4632 let depositPercent = $selected.attr("data-deposit_percent");
4633
4634 if (depositPercent.length > 0) {
4635 $("#' . $htmlname . '_deposit_percent_container").show().find("#' . $htmlname . '_deposit_percent").val(depositPercent);
4636 } else {
4637 $("#' . $htmlname . '_deposit_percent_container").hide();
4638 }
4639
4640 return true;
4641 });
4642 });
4643 </script>';
4644 }
4645
4646 return $out;
4647 }
4648
4649
4650 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4651
4668 public function select_types_paiements($selected = '', $htmlname = 'paiementtype', $filtertype = '', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '', $nooutput = 0)
4669 {
4670 // phpcs:enable
4671 global $langs, $user, $conf;
4672
4673 $out = '';
4674
4675 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
4676
4677 $filterarray = array();
4678 if ($filtertype == 'CRDT') {
4679 $filterarray = array(0, 2, 3);
4680 } elseif ($filtertype == 'DBIT') {
4681 $filterarray = array(1, 2, 3);
4682 } elseif ($filtertype != '' && $filtertype != '-1') {
4683 $filterarray = explode(',', $filtertype);
4684 }
4685
4687
4688 // Set default value if not already set by caller
4689 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID')) {
4690 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TYPE_ID", LOG_NOTICE);
4691 $selected = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID');
4692 }
4693
4694 $out .= '<select id="select' . $htmlname . '" class="flat selectpaymenttypes' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4695 if ($empty) {
4696 $out .= '<option value="">&nbsp;</option>';
4697 }
4698 foreach ($this->cache_types_paiements as $id => $arraytypes) {
4699 // If not good status
4700 if ($active >= 0 && $arraytypes['active'] != $active) {
4701 continue;
4702 }
4703
4704 // We skip of the user requested to filter on specific payment methods
4705 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
4706 continue;
4707 }
4708
4709 // We discard empty lines if showempty is on because an empty line has already been output.
4710 if ($empty && empty($arraytypes['code'])) {
4711 continue;
4712 }
4713
4714 if ($format == 0) {
4715 $out .= '<option value="' . $id . '"';
4716 } elseif ($format == 1) {
4717 $out .= '<option value="' . $arraytypes['code'] . '"';
4718 } elseif ($format == 2) {
4719 $out .= '<option value="' . $arraytypes['code'] . '"';
4720 } elseif ($format == 3) {
4721 $out .= '<option value="' . $id . '"';
4722 }
4723 // Print attribute selected or not
4724 if ($format == 1 || $format == 2) {
4725 if ($selected == $arraytypes['code']) {
4726 $out .= ' selected';
4727 }
4728 } else {
4729 if ($selected == $id) {
4730 $out .= ' selected';
4731 }
4732 }
4733 $out .= '>';
4734 $value = '';
4735 if ($format == 0) {
4736 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4737 } elseif ($format == 1) {
4738 $value = $arraytypes['code'];
4739 } elseif ($format == 2) {
4740 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4741 } elseif ($format == 3) {
4742 $value = $arraytypes['code'];
4743 }
4744 $out .= $value ? $value : '&nbsp;';
4745 $out .= '</option>';
4746 }
4747 $out .= '</select>';
4748 if ($user->admin && !$noadmininfo) {
4749 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4750 }
4751 $out .= ajax_combobox('select' . $htmlname);
4752
4753 if (empty($nooutput)) {
4754 print $out;
4755 } else {
4756 return $out;
4757 }
4758 }
4759
4760
4769 public function selectPriceBaseType($selected = '', $htmlname = 'price_base_type', $addjscombo = 0)
4770 {
4771 global $langs;
4772
4773 $return = '<select class="flat maxwidth100" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4774 $options = array(
4775 'HT' => $langs->trans("HT"),
4776 'TTC' => $langs->trans("TTC")
4777 );
4778 foreach ($options as $id => $value) {
4779 if ($selected == $id) {
4780 $return .= '<option value="' . $id . '" selected>' . $value;
4781 } else {
4782 $return .= '<option value="' . $id . '">' . $value;
4783 }
4784 $return .= '</option>';
4785 }
4786 $return .= '</select>';
4787 if ($addjscombo) {
4788 $return .= ajax_combobox('select_' . $htmlname);
4789 }
4790
4791 return $return;
4792 }
4793
4794 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4795
4802 {
4803 // phpcs:enable
4804 global $langs;
4805
4806 $num = count($this->cache_transport_mode); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_transport_mode
4807 if ($num > 0) {
4808 return $num; // Cache already loaded
4809 }
4810
4811 dol_syslog(__METHOD__, LOG_DEBUG);
4812
4813 $this->cache_transport_mode = array();
4814
4815 $sql = "SELECT rowid, code, label, active";
4816 $sql .= " FROM " . $this->db->prefix() . "c_transport_mode";
4817 $sql .= " WHERE entity IN (" . getEntity('c_transport_mode') . ")";
4818
4819 $resql = $this->db->query($sql);
4820 if ($resql) {
4821 $num = $this->db->num_rows($resql);
4822 $i = 0;
4823 while ($i < $num) {
4824 $obj = $this->db->fetch_object($resql);
4825
4826 // If traduction exist, we use it else we take the default label
4827 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4828 $this->cache_transport_mode[$obj->rowid]['rowid'] = $obj->rowid;
4829 $this->cache_transport_mode[$obj->rowid]['code'] = $obj->code;
4830 $this->cache_transport_mode[$obj->rowid]['label'] = $label;
4831 $this->cache_transport_mode[$obj->rowid]['active'] = $obj->active;
4832 $i++;
4833 }
4834
4835 $this->cache_transport_mode = dol_sort_array($this->cache_transport_mode, 'label', 'asc', 0, 0, 1);
4836
4837 return $num;
4838 } else {
4839 dol_print_error($this->db);
4840 return -1;
4841 }
4842 }
4843
4857 public function selectTransportMode($selected = '', $htmlname = 'transportmode', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '')
4858 {
4859 global $langs, $user;
4860
4861 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $format, LOG_DEBUG);
4862
4864
4865 print '<select id="select' . $htmlname . '" class="flat selectmodetransport' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4866 if ($empty) {
4867 print '<option value="">&nbsp;</option>';
4868 }
4869 foreach ($this->cache_transport_mode as $id => $arraytypes) {
4870 // If not good status
4871 if ($active >= 0 && $arraytypes['active'] != $active) {
4872 continue;
4873 }
4874
4875 // We discard empty line if showempty is on because an empty line has already been output.
4876 if ($empty && empty($arraytypes['code'])) {
4877 continue;
4878 }
4879
4880 if ($format == 0) {
4881 print '<option value="' . $id . '"';
4882 } elseif ($format == 1) {
4883 print '<option value="' . $arraytypes['code'] . '"';
4884 } elseif ($format == 2) {
4885 print '<option value="' . $arraytypes['code'] . '"';
4886 } elseif ($format == 3) {
4887 print '<option value="' . $id . '"';
4888 }
4889 // If text is selected, we compare with code, else with id
4890 if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) {
4891 print ' selected';
4892 } elseif ($selected == $id) {
4893 print ' selected';
4894 }
4895 print '>';
4896 $value = '';
4897 if ($format == 0) {
4898 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4899 } elseif ($format == 1) {
4900 $value = $arraytypes['code'];
4901 } elseif ($format == 2) {
4902 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4903 } elseif ($format == 3) {
4904 $value = $arraytypes['code'];
4905 }
4906 print $value ? $value : '&nbsp;';
4907 print '</option>';
4908 }
4909 print '</select>';
4910 if ($user->admin && !$noadmininfo) {
4911 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4912 }
4913 }
4914
4927 public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '', $noinfoadmin = 0, $morecss = '')
4928 {
4929 global $langs, $user;
4930
4931 $langs->load("admin");
4932 $langs->load("deliveries");
4933
4934 $sql = "SELECT rowid, code, libelle as label";
4935 $sql .= " FROM " . $this->db->prefix() . "c_shipment_mode";
4936 $sql .= " WHERE active > 0";
4937 if ($filtre) {
4938 $sql .= " AND " . $filtre;
4939 }
4940 $sql .= " ORDER BY libelle ASC";
4941
4942 dol_syslog(get_class($this) . "::selectShippingMode", LOG_DEBUG);
4943 $result = $this->db->query($sql);
4944 if ($result) {
4945 $num = $this->db->num_rows($result);
4946 $i = 0;
4947 if ($num) {
4948 print '<select id="select' . $htmlname . '" class="flat selectshippingmethod' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4949 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4950 print '<option value="-1">&nbsp;</option>';
4951 }
4952 while ($i < $num) {
4953 $obj = $this->db->fetch_object($result);
4954 if ($selected == $obj->rowid) {
4955 print '<option value="' . $obj->rowid . '" selected>';
4956 } else {
4957 print '<option value="' . $obj->rowid . '">';
4958 }
4959 print ($langs->trans("SendingMethod" . strtoupper($obj->code)) != "SendingMethod" . strtoupper($obj->code)) ? $langs->trans("SendingMethod" . strtoupper($obj->code)) : $obj->label;
4960 print '</option>';
4961 $i++;
4962 }
4963 print "</select>";
4964 if ($user->admin && empty($noinfoadmin)) {
4965 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4966 }
4967
4968 print ajax_combobox('select' . $htmlname);
4969 } else {
4970 print $langs->trans("NoShippingMethodDefined");
4971 }
4972 } else {
4973 dol_print_error($this->db);
4974 }
4975 }
4976
4986 public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0)
4987 {
4988 global $langs;
4989
4990 $langs->load("deliveries");
4991
4992 if ($htmlname != "none") {
4993 print '<form method="POST" action="' . $page . '">';
4994 print '<input type="hidden" name="action" value="setshippingmethod">';
4995 print '<input type="hidden" name="token" value="' . newToken() . '">';
4996 $this->selectShippingMethod($selected, $htmlname, '', $addempty);
4997 print '<input type="submit" class="button valignmiddle" value="' . $langs->trans("Modify") . '">';
4998 print '</form>';
4999 } else {
5000 if ($selected) {
5001 $code = $langs->getLabelFromKey($this->db, $selected, 'c_shipment_mode', 'rowid', 'code');
5002 print $langs->trans("SendingMethod" . strtoupper($code));
5003 } else {
5004 print "&nbsp;";
5005 }
5006 }
5007 }
5008
5017 public function selectSituationInvoices($selected = '', $socid = 0)
5018 {
5019 global $langs;
5020
5021 $langs->load('bills');
5022
5023 $opt = '<option value="" selected></option>';
5024 $sql = "SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc";
5025 $sql .= ' FROM ' . $this->db->prefix() . 'facture';
5026 $sql .= ' WHERE entity IN (' . getEntity('invoice') . ')';
5027 $sql .= ' AND situation_counter >= 1';
5028 $sql .= ' AND fk_soc = ' . (int) $socid;
5029 $sql .= ' AND type <> 2';
5030 $sql .= ' ORDER by situation_cycle_ref, situation_counter desc';
5031 $resql = $this->db->query($sql);
5032
5033 if ($resql && $this->db->num_rows($resql) > 0) {
5034 // Last seen cycle
5035 $ref = 0;
5036 while ($obj = $this->db->fetch_object($resql)) {
5037 //Same cycle ?
5038 if ($obj->situation_cycle_ref != $ref) {
5039 // Just seen this cycle
5040 $ref = $obj->situation_cycle_ref;
5041 //not final ?
5042 if ($obj->situation_final != 1) {
5043 //Not prov?
5044 if (substr($obj->ref, 1, 4) != 'PROV') {
5045 if ($selected == $obj->rowid) {
5046 $opt .= '<option value="' . $obj->rowid . '" selected>' . $obj->ref . '</option>';
5047 } else {
5048 $opt .= '<option value="' . $obj->rowid . '">' . $obj->ref . '</option>';
5049 }
5050 }
5051 }
5052 }
5053 }
5054 } else {
5055 dol_syslog("Error sql=" . $sql . ", error=" . $this->error, LOG_ERR);
5056 }
5057 if ($opt == '<option value ="" selected></option>') {
5058 $opt = '<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>';
5059 }
5060 return $opt;
5061 }
5062
5072 public function selectUnits($selected = '', $htmlname = 'units', $showempty = 0, $unit_type = '')
5073 {
5074 global $langs;
5075
5076 $langs->load('products');
5077
5078 $return = '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
5079
5080 $sql = "SELECT rowid, label, code FROM " . $this->db->prefix() . "c_units";
5081 $sql .= ' WHERE active > 0';
5082 if (!empty($unit_type)) {
5083 $sql .= " AND unit_type = '" . $this->db->escape($unit_type) . "'";
5084 }
5085 $sql .= " ORDER BY sortorder";
5086
5087 $resql = $this->db->query($sql);
5088 if ($resql && $this->db->num_rows($resql) > 0) {
5089 if ($showempty) {
5090 $return .= '<option value="none"></option>';
5091 }
5092
5093 while ($res = $this->db->fetch_object($resql)) {
5094 $unitLabel = $res->label;
5095 if (!empty($langs->tab_translate['unit' . $res->code])) { // check if Translation is available before
5096 $unitLabel = $langs->trans('unit' . $res->code) != $res->label ? $langs->trans('unit' . $res->code) : $res->label;
5097 }
5098
5099 if ($selected == $res->rowid) {
5100 $return .= '<option value="' . $res->rowid . '" selected>' . $unitLabel . '</option>';
5101 } else {
5102 $return .= '<option value="' . $res->rowid . '">' . $unitLabel . '</option>';
5103 }
5104 }
5105 $return .= '</select>';
5106 }
5107 return $return;
5108 }
5109
5110 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5111
5126 public function select_comptes($selected = '', $htmlname = 'accountid', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '', $showcurrency = 0, $morecss = '', $nooutput = 0)
5127 {
5128 // phpcs:enable
5129 global $langs;
5130
5131 $out = '';
5132
5133 $langs->load("admin");
5134 $num = 0;
5135
5136 $sql = "SELECT rowid, label, bank, clos as status, currency_code";
5137 $sql .= " FROM " . $this->db->prefix() . "bank_account";
5138 $sql .= " WHERE entity IN (" . getEntity('bank_account') . ")";
5139 if ($status != 2) {
5140 $sql .= " AND clos = " . (int) $status;
5141 }
5142 if ($filtre) { // TODO Support USF
5143 $sql .= " AND " . $filtre;
5144 }
5145 $sql .= " ORDER BY label";
5146
5147 dol_syslog(get_class($this) . "::select_comptes", LOG_DEBUG);
5148 $result = $this->db->query($sql);
5149 if ($result) {
5150 $num = $this->db->num_rows($result);
5151 $i = 0;
5152 if ($num) {
5153 $out .= '<select id="select' . $htmlname . '" class="flat selectbankaccount' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5154
5155 if (!empty($useempty) && !is_numeric($useempty)) {
5156 $out .= '<option value="-1">'.$langs->trans($useempty).'</option>';
5157 } elseif ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5158 $out .= '<option value="-1">&nbsp;</option>';
5159 }
5160
5161 while ($i < $num) {
5162 $obj = $this->db->fetch_object($result);
5163 if ($selected == $obj->rowid || ($useempty == 2 && $num == 1 && empty($selected))) {
5164 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '" selected>';
5165 } else {
5166 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '">';
5167 }
5168 $out .= trim($obj->label);
5169 if ($showcurrency) {
5170 $out .= ' (' . $obj->currency_code . ')';
5171 }
5172 if ($status == 2 && $obj->status == 1) {
5173 $out .= ' (' . $langs->trans("Closed") . ')';
5174 }
5175 $out .= '</option>';
5176 $i++;
5177 }
5178 $out .= "</select>";
5179 $out .= ajax_combobox('select' . $htmlname);
5180 } else {
5181 if ($status == 0) {
5182 $out .= '<span class="opacitymedium">' . $langs->trans("NoActiveBankAccountDefined") . '</span>';
5183 } else {
5184 $out .= '<span class="opacitymedium">' . $langs->trans("NoBankAccountFound") . '</span>';
5185 }
5186 }
5187 } else {
5188 dol_print_error($this->db);
5189 }
5190
5191 // Output or return
5192 if (empty($nooutput)) {
5193 print $out;
5194 } else {
5195 return $out;
5196 }
5197
5198 return $num;
5199 }
5200
5212 public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '')
5213 {
5214 global $langs;
5215
5216 $langs->load("admin");
5217 $num = 0;
5218
5219 $sql = "SELECT rowid, name, fk_country, status, entity";
5220 $sql .= " FROM " . $this->db->prefix() . "establishment";
5221 $sql .= " WHERE 1=1";
5222 if ($status != 2) {
5223 $sql .= " AND status = " . (int) $status;
5224 }
5225 if ($filtre) { // TODO Support USF
5226 $sql .= " AND " . $filtre;
5227 }
5228 $sql .= " ORDER BY name";
5229
5230 dol_syslog(get_class($this) . "::select_establishment", LOG_DEBUG);
5231 $result = $this->db->query($sql);
5232 if ($result) {
5233 $num = $this->db->num_rows($result);
5234 $i = 0;
5235 if ($num) {
5236 print '<select id="select' . $htmlname . '" class="flat selectestablishment" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5237 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5238 print '<option value="-1">&nbsp;</option>';
5239 }
5240
5241 while ($i < $num) {
5242 $obj = $this->db->fetch_object($result);
5243 if ($selected == $obj->rowid) {
5244 print '<option value="' . $obj->rowid . '" selected>';
5245 } else {
5246 print '<option value="' . $obj->rowid . '">';
5247 }
5248 print trim($obj->name);
5249 if ($status == 2 && $obj->status == 1) {
5250 print ' (' . $langs->trans("Closed") . ')';
5251 }
5252 print '</option>';
5253 $i++;
5254 }
5255 print "</select>";
5256 } else {
5257 if ($status == 0) {
5258 print '<span class="opacitymedium">' . $langs->trans("NoActiveEstablishmentDefined") . '</span>';
5259 } else {
5260 print '<span class="opacitymedium">' . $langs->trans("NoEstablishmentFound") . '</span>';
5261 }
5262 }
5263
5264 return $num;
5265 } else {
5266 dol_print_error($this->db);
5267 return -1;
5268 }
5269 }
5270
5280 public function formSelectAccount($page, $selected = '', $htmlname = 'fk_account', $addempty = 0)
5281 {
5282 global $langs;
5283 if ($htmlname != "none") {
5284 print '<form method="POST" action="' . $page . '">';
5285 print '<input type="hidden" name="action" value="setbankaccount">';
5286 print '<input type="hidden" name="token" value="' . newToken() . '">';
5287 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
5288 $nbaccountfound = $this->select_comptes($selected, $htmlname, 0, '', $addempty);
5289 if ($nbaccountfound > 0) {
5290 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5291 }
5292 print '</form>';
5293 } else {
5294 $langs->load('banks');
5295
5296 if ($selected) {
5297 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
5298 $bankstatic = new Account($this->db);
5299 $result = $bankstatic->fetch($selected);
5300 if ($result) {
5301 print $bankstatic->getNomUrl(1);
5302 }
5303 } else {
5304 print "&nbsp;";
5305 }
5306 }
5307 }
5308
5309 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5310
5330 public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $fromid = 0, $outputmode = 0, $include = 0, $morecss = '', $useempty = 1)
5331 {
5332 // phpcs:enable
5333 global $conf, $langs;
5334 $langs->load("categories");
5335
5336 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
5337
5338 // For backward compatibility
5339 if (is_numeric($type)) {
5340 dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING);
5341 }
5342
5343 if ($type === Categorie::TYPE_BANK_LINE) {
5344 // TODO Move this into common category feature
5345 $cate_arbo = array();
5346 $sql = "SELECT c.label, c.rowid";
5347 $sql .= " FROM " . $this->db->prefix() . "category_bank as c";
5348 $sql .= " WHERE entity = " . $conf->entity;
5349 $sql .= " ORDER BY c.label";
5350 $result = $this->db->query($sql);
5351 if ($result) {
5352 $num = $this->db->num_rows($result);
5353 $i = 0;
5354 while ($i < $num) {
5355 $objp = $this->db->fetch_object($result);
5356 if ($objp) {
5357 $cate_arbo[$objp->rowid] = array('id' => $objp->rowid, 'fulllabel' => $objp->label, 'color' => '', 'picto' => 'category');
5358 }
5359 $i++;
5360 }
5361 $this->db->free($result);
5362 } else {
5363 dol_print_error($this->db);
5364 }
5365 } else {
5366 $cat = new Categorie($this->db);
5367 $cate_arbo = $cat->get_full_arbo($type, $fromid, $include);
5368 }
5369
5370 $outarray = array();
5371 $outarrayrichhtml = array();
5372
5373
5374 $output = '<select class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
5375 if (is_array($cate_arbo)) {
5376 $num = count($cate_arbo);
5377
5378 if (!$num) {
5379 $output .= '<option value="-1" disabled>' . $langs->trans("NoCategoriesDefined") . '</option>';
5380 } else {
5381 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5382 $output .= '<option value="-1">&nbsp;</option>';
5383 }
5384 foreach ($cate_arbo as $key => $value) {
5385 if ($cate_arbo[$key]['id'] == $selected || ($selected === 'auto' && count($cate_arbo) == 1)) {
5386 $add = 'selected ';
5387 } else {
5388 $add = '';
5389 }
5390
5391 $labeltoshow = img_picto('', 'category', 'class="pictofixedwidth" style="color: #' . $cate_arbo[$key]['color'] . '"');
5392 $labeltoshow .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5393
5394 $outarray[$cate_arbo[$key]['id']] = $cate_arbo[$key]['fulllabel'];
5395
5396 $outarrayrichhtml[$cate_arbo[$key]['id']] = $labeltoshow;
5397
5398 $output .= '<option ' . $add . 'value="' . $cate_arbo[$key]['id'] . '"';
5399 $output .= ' data-html="' . dol_escape_htmltag($labeltoshow) . '"';
5400 $output .= '>';
5401 $output .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5402 $output .= '</option>';
5403
5404 $cate_arbo[$key]['data-html'] = $labeltoshow;
5405 }
5406 }
5407 }
5408 $output .= '</select>';
5409 $output .= "\n";
5410
5411 if ($outputmode == 2) {
5412 // TODO: handle error when $cate_arbo is not an array
5413 return $cate_arbo;
5414 } elseif ($outputmode == 1) {
5415 return $outarray;
5416 } elseif ($outputmode == 3) {
5417 return $outarrayrichhtml;
5418 }
5419 return $output;
5420 }
5421
5422 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5423
5442 public function form_confirm($page, $title, $question, $action, $formquestion = array(), $selectedchoice = "", $useajax = 0, $height = 170, $width = 500)
5443 {
5444 // phpcs:enable
5445 dol_syslog(__METHOD__ . ': using form_confirm is deprecated. Use formconfim instead.', LOG_WARNING);
5446 print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width);
5447 }
5448
5476 public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No')
5477 {
5478 global $langs, $conf;
5479
5480 $more = '<!-- formconfirm - before call, page=' . dol_escape_htmltag($page) . ' -->';
5481 $formconfirm = '';
5482 $inputok = array();
5483 $inputko = array();
5484
5485 // Clean parameters
5486 $newselectedchoice = empty($selectedchoice) ? "no" : $selectedchoice;
5487 if ($conf->browser->layout == 'phone') {
5488 $width = '95%';
5489 }
5490
5491 // Set height automatically if not defined
5492 if (empty($height)) {
5493 $height = 220;
5494 if (is_array($formquestion) && count($formquestion) > 2) {
5495 $height += ((count($formquestion) - 2) * 24);
5496 }
5497 }
5498
5499 if (is_array($formquestion) && !empty($formquestion)) {
5500 // First add hidden fields and value
5501 foreach ($formquestion as $key => $input) {
5502 if (is_array($input) && !empty($input)) {
5503 if ($input['type'] == 'hidden') {
5504 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5505 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5506
5507 $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";
5508 }
5509 }
5510 }
5511
5512 // Now add questions
5513 $moreonecolumn = '';
5514 $more .= '<div class="tagtable paddingtopbottomonly centpercent noborderspacing">' . "\n";
5515 foreach ($formquestion as $key => $input) {
5516 if (is_array($input) && !empty($input)) {
5517 $size = (!empty($input['size']) ? ' size="' . $input['size'] . '"' : ''); // deprecated. Use morecss instead.
5518 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5519 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5520
5521 if ($input['type'] == 'text') {
5522 $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";
5523 } elseif ($input['type'] == 'password') {
5524 $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";
5525 } elseif ($input['type'] == 'textarea') {
5526 /*$more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">'.$input['label'].'</div><div class="tagtd">';
5527 $more .= '<textarea name="'.$input['name'].'" class="'.$morecss.'"'.$moreattr.'>';
5528 $more .= $input['value'];
5529 $more .= '</textarea>';
5530 $more .= '</div></div>'."\n";*/
5531 $moreonecolumn .= '<div class="margintoponly">';
5532 $moreonecolumn .= $input['label'] . '<br>';
5533 $moreonecolumn .= '<textarea name="' . dol_escape_htmltag($input['name']) . '" id="' . dol_escape_htmltag($input['name']) . '" class="' . $morecss . '"' . $moreattr . '>';
5534 $moreonecolumn .= $input['value'];
5535 $moreonecolumn .= '</textarea>';
5536 $moreonecolumn .= '</div>';
5537 } elseif (in_array($input['type'], ['select', 'multiselect'])) {
5538 if (empty($morecss)) {
5539 $morecss = 'minwidth100';
5540 }
5541
5542 $show_empty = isset($input['select_show_empty']) ? $input['select_show_empty'] : 1;
5543 $key_in_label = isset($input['select_key_in_label']) ? $input['select_key_in_label'] : 0;
5544 $value_as_key = isset($input['select_value_as_key']) ? $input['select_value_as_key'] : 0;
5545 $translate = isset($input['select_translate']) ? $input['select_translate'] : 0;
5546 $maxlen = isset($input['select_maxlen']) ? $input['select_maxlen'] : 0;
5547 $disabled = isset($input['select_disabled']) ? $input['select_disabled'] : 0;
5548 $sort = isset($input['select_sort']) ? $input['select_sort'] : '';
5549
5550 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">';
5551 if (!empty($input['label'])) {
5552 $more .= $input['label'] . '</div><div class="tagtd left">';
5553 }
5554 if ($input['type'] == 'select') {
5555 $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);
5556 } else {
5557 $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);
5558 }
5559 $more .= '</div></div>' . "\n";
5560 } elseif ($input['type'] == 'checkbox') {
5561 $more .= '<div class="tagtr">';
5562 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '"><label for="' . dol_escape_htmltag($input['name']) . '">' . $input['label'] . '</label></div><div class="tagtd">';
5563 $more .= '<input type="checkbox" class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $moreattr;
5564 if (!is_bool($input['value']) && $input['value'] != 'false' && $input['value'] != '0' && $input['value'] != '') {
5565 $more .= ' checked';
5566 }
5567 if (is_bool($input['value']) && $input['value']) {
5568 $more .= ' checked';
5569 }
5570 if (isset($input['disabled'])) {
5571 $more .= ' disabled';
5572 }
5573 $more .= ' /></div>';
5574 $more .= '</div>' . "\n";
5575 } elseif ($input['type'] == 'radio') {
5576 $i = 0;
5577 foreach ($input['values'] as $selkey => $selval) {
5578 $more .= '<div class="tagtr">';
5579 if (isset($input['label'])) {
5580 if ($i == 0) {
5581 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? ' tdtop' : (' tdtop ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5582 } else {
5583 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' "' . $input['tdclass'])) . '">&nbsp;</div>';
5584 }
5585 }
5586 $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;
5587 if (!empty($input['disabled'])) {
5588 $more .= ' disabled';
5589 }
5590 if (isset($input['default']) && $input['default'] === $selkey) {
5591 $more .= ' checked="checked"';
5592 }
5593 $more .= ' /> ';
5594 $more .= '<label for="' . dol_escape_htmltag($input['name'] . $selkey) . '" class="valignmiddle">' . $selval . '</label>';
5595 $more .= '</div></div>' . "\n";
5596 $i++;
5597 }
5598 } elseif ($input['type'] == 'date' || $input['type'] == 'datetime') {
5599 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5600 $more .= '<div class="tagtd">';
5601 $addnowlink = (empty($input['datenow']) ? 0 : 1);
5602 $h = $m = 0;
5603 if ($input['type'] == 'datetime') {
5604 $h = isset($input['hours']) ? $input['hours'] : 1;
5605 $m = isset($input['minutes']) ? $input['minutes'] : 1;
5606 }
5607 $more .= $this->selectDate(isset($input['value']) ? $input['value'] : -1, $input['name'], $h, $m, 0, '', 1, $addnowlink);
5608 $more .= '</div></div>'."\n";
5609 $formquestion[] = array('name' => $input['name'].'day');
5610 $formquestion[] = array('name' => $input['name'].'month');
5611 $formquestion[] = array('name' => $input['name'].'year');
5612 $formquestion[] = array('name' => $input['name'].'hour');
5613 $formquestion[] = array('name' => $input['name'].'min');
5614 } elseif ($input['type'] == 'other') { // can be 1 column or 2 depending if label is set or not
5615 $more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">';
5616 if (!empty($input['label'])) {
5617 $more .= $input['label'] . '</div><div class="tagtd">';
5618 }
5619 $more .= $input['value'];
5620 $more .= '</div></div>' . "\n";
5621 } elseif ($input['type'] == 'onecolumn') {
5622 $moreonecolumn .= '<div class="margintoponly">';
5623 $moreonecolumn .= $input['value'];
5624 $moreonecolumn .= '</div>' . "\n";
5625 } elseif ($input['type'] == 'hidden') {
5626 // Do nothing more, already added by a previous loop
5627 } elseif ($input['type'] == 'separator') {
5628 $more .= '<br>';
5629 } else {
5630 $more .= 'Error type ' . $input['type'] . ' for the confirm box is not a supported type';
5631 }
5632 }
5633 }
5634 $more .= '</div>' . "\n";
5635 $more .= $moreonecolumn;
5636 }
5637
5638 // JQUERY method dialog is broken with smartphone, we use standard HTML.
5639 // 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
5640 // See page product/card.php for example
5641 if (!empty($conf->dol_use_jmobile)) {
5642 $useajax = 0;
5643 }
5644 if (empty($conf->use_javascript_ajax)) {
5645 $useajax = 0;
5646 }
5647
5648 if ($useajax) {
5649 $autoOpen = true;
5650 $dialogconfirm = 'dialog-confirm';
5651 $button = '';
5652 if (!is_numeric($useajax)) {
5653 $button = $useajax;
5654 $useajax = 1;
5655 $autoOpen = false;
5656 $dialogconfirm .= '-' . $button;
5657 }
5658 $pageyes = $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=yes';
5659 $pageno = ($useajax == 2 ? $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=no' : '');
5660
5661 // Add input fields into list of fields to read during submit (inputok and inputko)
5662 if (is_array($formquestion)) {
5663 foreach ($formquestion as $key => $input) {
5664 //print "xx ".$key." rr ".is_array($input)."<br>\n";
5665 // Add name of fields to propagate with the GET when submitting the form with button OK.
5666 if (is_array($input) && isset($input['name'])) {
5667 if (strpos($input['name'], ',') > 0) {
5668 $inputok = array_merge($inputok, explode(',', $input['name']));
5669 } else {
5670 array_push($inputok, $input['name']);
5671 }
5672 }
5673 // Add name of fields to propagate with the GET when submitting the form with button KO.
5674 // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset
5675 if (is_array($input) && isset($input['inputko']) && $input['inputko'] == 1 && isset($input['name'])) {
5676 array_push($inputko, $input['name']);
5677 }
5678 }
5679 }
5680
5681 // Show JQuery confirm box.
5682 $formconfirm .= '<div id="' . $dialogconfirm . '" title="' . dol_escape_htmltag($title) . '" style="display: none;">';
5683 if (is_array($formquestion) && array_key_exists('text', $formquestion) && !empty($formquestion['text'])) {
5684 $formconfirm .= '<div class="confirmtext">' . $formquestion['text'] . '</div>' . "\n";
5685 }
5686 if (!empty($more)) {
5687 $formconfirm .= '<div class="confirmquestions">' . $more . '</div>' . "\n";
5688 }
5689 $formconfirm .= ($question ? '<div class="confirmmessage">' . img_help(0, '') . ' ' . $question . '</div>' : '');
5690 $formconfirm .= '</div>' . "\n";
5691
5692 $formconfirm .= "\n<!-- begin code of popup for formconfirm page=" . $page . " -->\n";
5693 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5694 $formconfirm .= "/* Code for the jQuery('#dialogforpopup').dialog() */\n";
5695 $formconfirm .= 'jQuery(document).ready(function() {
5696 $(function() {
5697 $( "#' . $dialogconfirm . '" ).dialog(
5698 {
5699 autoOpen: ' . ($autoOpen ? "true" : "false") . ',';
5700 if ($newselectedchoice == 'no') {
5701 $formconfirm .= '
5702 open: function() {
5703 $(this).parent().find("button.ui-button:eq(2)").focus();
5704 },';
5705 }
5706
5707 $jsforcursor = '';
5708 if ($useajax == 1) {
5709 $jsforcursor = '// The call to urljump can be slow, so we set the wait cursor' . "\n";
5710 $jsforcursor .= 'jQuery("html,body,#id-container").addClass("cursorwait");' . "\n";
5711 }
5712
5713 $postconfirmas = 'GET';
5714
5715 $formconfirm .= '
5716 resizable: false,
5717 height: "' . $height . '",
5718 width: "' . $width . '",
5719 modal: true,
5720 closeOnEscape: false,
5721 buttons: {
5722 "' . dol_escape_js($langs->transnoentities($labelbuttonyes)) . '": function() {
5723 var options = "token=' . urlencode(newToken()) . '";
5724 var inputok = ' . json_encode($inputok) . '; /* List of fields into form */
5725 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5726 var pageyes = "' . dol_escape_js(!empty($pageyes) ? $pageyes : '') . '";
5727
5728 if (inputok.length > 0) {
5729 $.each(inputok, function(i, inputname) {
5730 var more = "";
5731 var inputvalue;
5732 if ($("input[name=\'" + inputname + "\']").attr("type") == "radio") {
5733 inputvalue = $("input[name=\'" + inputname + "\']:checked").val();
5734 } else {
5735 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5736 inputvalue = $("#" + inputname + more).val();
5737 }
5738 if (typeof inputvalue == "undefined") { inputvalue=""; }
5739 console.log("formconfirm check inputname="+inputname+" inputvalue="+inputvalue);
5740 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5741 });
5742 }
5743 var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "&") + options;
5744 if (pageyes.length > 0) {';
5745 if ($postconfirmas == 'GET') {
5746 $formconfirm .= 'location.href = urljump;';
5747 } else {
5748 $formconfirm .= $jsforcursor;
5749 $formconfirm .= 'var post = $.post(
5750 pageyes,
5751 options,
5752 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5753 );';
5754 }
5755 $formconfirm .= '
5756 console.log("after post ok");
5757 }
5758 $(this).dialog("close");
5759 },
5760 "' . dol_escape_js($langs->transnoentities($labelbuttonno)) . '": function() {
5761 var options = "token=' . urlencode(newToken()) . '";
5762 var inputko = ' . json_encode($inputko) . '; /* List of fields into form */
5763 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5764 var pageno="' . dol_escape_js(!empty($pageno) ? $pageno : '') . '";
5765 if (inputko.length > 0) {
5766 $.each(inputko, function(i, inputname) {
5767 var more = "";
5768 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5769 var inputvalue = $("#" + inputname + more).val();
5770 if (typeof inputvalue == "undefined") { inputvalue=""; }
5771 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5772 });
5773 }
5774 var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "&") + options;
5775 //alert(urljump);
5776 if (pageno.length > 0) {';
5777 if ($postconfirmas == 'GET') {
5778 $formconfirm .= 'location.href = urljump;';
5779 } else {
5780 $formconfirm .= $jsforcursor;
5781 $formconfirm .= 'var post = $.post(
5782 pageno,
5783 options,
5784 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5785 );';
5786 }
5787 $formconfirm .= '
5788 console.log("after post ko");
5789 }
5790 $(this).dialog("close");
5791 }
5792 }
5793 }
5794 );
5795
5796 var button = "' . $button . '";
5797 if (button.length > 0) {
5798 $( "#" + button ).click(function() {
5799 $("#' . $dialogconfirm . '").dialog("open");
5800 });
5801 }
5802 });
5803 });
5804 </script>';
5805 $formconfirm .= "<!-- end ajax formconfirm -->\n";
5806 } else {
5807 $formconfirm .= "\n<!-- begin formconfirm page=" . dol_escape_htmltag($page) . " -->\n";
5808
5809 if (empty($disableformtag)) {
5810 $formconfirm .= '<form method="POST" action="' . $page . '" class="notoptoleftroright">' . "\n";
5811 }
5812
5813 $formconfirm .= '<input type="hidden" name="action" value="' . $action . '">' . "\n";
5814 $formconfirm .= '<input type="hidden" name="token" value="' . newToken() . '">' . "\n";
5815
5816 $formconfirm .= '<table class="valid centpercent">' . "\n";
5817
5818 // Line title
5819 $formconfirm .= '<tr class="validtitre"><td class="validtitre" colspan="2">';
5820 $formconfirm .= img_picto('', 'pictoconfirm') . ' ' . $title;
5821 $formconfirm .= '</td></tr>' . "\n";
5822
5823 // Line text
5824 if (is_array($formquestion) && array_key_exists('text', $formquestion) && !empty($formquestion['text'])) {
5825 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . $formquestion['text'] . '</td></tr>' . "\n";
5826 }
5827
5828 // Line form fields
5829 if ($more) {
5830 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . "\n";
5831 $formconfirm .= $more;
5832 $formconfirm .= '</td></tr>' . "\n";
5833 }
5834
5835 // Line with question
5836 $formconfirm .= '<tr class="valid">';
5837 $formconfirm .= '<td class="valid">' . $question . '</td>';
5838 $formconfirm .= '<td class="valid center">';
5839 $formconfirm .= $this->selectyesno("confirm", $newselectedchoice, 0, false, 0, 0, 'marginleftonly marginrightonly', $labelbuttonyes, $labelbuttonno);
5840 $formconfirm .= '<input class="button valignmiddle confirmvalidatebutton small" type="submit" value="' . $langs->trans("Validate") . '">';
5841 $formconfirm .= '</td>';
5842 $formconfirm .= '</tr>' . "\n";
5843
5844 $formconfirm .= '</table>' . "\n";
5845
5846 if (empty($disableformtag)) {
5847 $formconfirm .= "</form>\n";
5848 }
5849 $formconfirm .= '<br>';
5850
5851 if (!empty($conf->use_javascript_ajax)) {
5852 $formconfirm .= '<!-- code to disable button to avoid double clic -->';
5853 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5854 $formconfirm .= '
5855 $(document).ready(function () {
5856 $(".confirmvalidatebutton").on("click", function() {
5857 console.log("We click on button confirmvalidatebutton");
5858 $(this).attr("disabled", "disabled");
5859 setTimeout(\'$(".confirmvalidatebutton").removeAttr("disabled")\', 3000);
5860 //console.log($(this).closest("form"));
5861 $(this).closest("form").submit();
5862 });
5863 });
5864 ';
5865 $formconfirm .= '</script>' . "\n";
5866 }
5867
5868 $formconfirm .= "<!-- end formconfirm -->\n";
5869 }
5870
5871 return $formconfirm;
5872 }
5873
5874
5875 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5876
5892 public function form_project($page, $socid, $selected = '', $htmlname = 'projectid', $discard_closed = 0, $maxlength = 20, $forcefocus = 0, $nooutput = 0, $textifnoproject = '', $morecss = '')
5893 {
5894 // phpcs:enable
5895 global $langs;
5896
5897 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
5898 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
5899
5900 $out = '';
5901
5902 $formproject = new FormProjets($this->db);
5903
5904 $langs->load("project");
5905 if ($htmlname != "none") {
5906 $out .= '<form method="post" action="' . $page . '">';
5907 $out .= '<input type="hidden" name="action" value="classin">';
5908 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5909 $out .= $formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1, 0, $morecss);
5910 $out .= '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5911 $out .= '</form>';
5912 } else {
5913 $out .= '<span class="project_head_block">';
5914 if ($selected) {
5915 $projet = new Project($this->db);
5916 $projet->fetch($selected);
5917 $out .= $projet->getNomUrl(0, '', 1);
5918 } else {
5919 $out .= '<span class="opacitymedium">' . $textifnoproject . '</span>';
5920 }
5921 $out .= '</span>';
5922 }
5923
5924 if (empty($nooutput)) {
5925 print $out;
5926 return '';
5927 }
5928 return $out;
5929 }
5930
5931 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5932
5948 public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0, $type = '', $filtertype = -1, $deposit_percent = -1, $nooutput = 0)
5949 {
5950 // phpcs:enable
5951 global $langs;
5952
5953 $out = '';
5954
5955 if ($htmlname != "none") {
5956 $out .= '<form method="POST" action="' . $page . '">';
5957 $out .= '<input type="hidden" name="action" value="setconditions">';
5958 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5959 if ($type) {
5960 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5961 }
5962 $out .= $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, 0, '', $deposit_percent);
5963 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5964 $out .= '</form>';
5965 } else {
5966 if ($selected) {
5968 if (isset($this->cache_conditions_paiements[$selected])) {
5969 $label = $this->cache_conditions_paiements[$selected]['label'];
5970
5971 if (!empty($this->cache_conditions_paiements[$selected]['deposit_percent'])) {
5972 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $this->cache_conditions_paiements[$selected]['deposit_percent'], $label);
5973 }
5974
5975 $out .= $label;
5976 } else {
5977 $langs->load('errors');
5978 $out .= $langs->trans('ErrorNotInDictionaryPaymentConditions');
5979 }
5980 } else {
5981 $out .= '&nbsp;';
5982 }
5983 }
5984
5985 if (empty($nooutput)) {
5986 print $out;
5987 return '';
5988 }
5989 return $out;
5990 }
5991
5992 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5993
6003 public function form_availability($page, $selected = '', $htmlname = 'availability', $addempty = 0)
6004 {
6005 // phpcs:enable
6006 global $langs;
6007 if ($htmlname != "none") {
6008 print '<form method="post" action="' . $page . '">';
6009 print '<input type="hidden" name="action" value="setavailability">';
6010 print '<input type="hidden" name="token" value="' . newToken() . '">';
6011 $this->selectAvailabilityDelay($selected, $htmlname, '', $addempty);
6012 print '<input type="submit" name="modify" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
6013 print '<input type="submit" name="cancel" class="button smallpaddingimp" value="' . $langs->trans("Cancel") . '">';
6014 print '</form>';
6015 } else {
6016 if ($selected) {
6017 $this->load_cache_availability();
6018 print $this->cache_availability[$selected]['label'];
6019 } else {
6020 print "&nbsp;";
6021 }
6022 }
6023 }
6024
6035 public function formInputReason($page, $selected = '', $htmlname = 'demandreason', $addempty = 0)
6036 {
6037 global $langs;
6038 if ($htmlname != "none") {
6039 print '<form method="post" action="' . $page . '">';
6040 print '<input type="hidden" name="action" value="setdemandreason">';
6041 print '<input type="hidden" name="token" value="' . newToken() . '">';
6042 $this->selectInputReason($selected, $htmlname, '-1', $addempty);
6043 print '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
6044 print '</form>';
6045 } else {
6046 if ($selected) {
6047 $this->loadCacheInputReason();
6048 foreach ($this->cache_demand_reason as $key => $val) {
6049 if ($val['id'] == $selected) {
6050 print $val['label'];
6051 break;
6052 }
6053 }
6054 } else {
6055 print "&nbsp;";
6056 }
6057 }
6058 }
6059
6060 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6061
6075 public function form_date($page, $selected, $htmlname, $displayhour = 0, $displaymin = 0, $nooutput = 0, $type = '')
6076 {
6077 // phpcs:enable
6078 global $langs;
6079
6080 $ret = '';
6081
6082 if ($htmlname != "none") {
6083 $ret .= '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
6084 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
6085 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
6086 if ($type) {
6087 $ret .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
6088 }
6089 $ret .= '<table class="nobordernopadding">';
6090 $ret .= '<tr><td>';
6091 $ret .= $this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form' . $htmlname, 1, 0);
6092 $ret .= '</td>';
6093 $ret .= '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6094 $ret .= '</tr></table></form>';
6095 } else {
6096 if ($displayhour) {
6097 $ret .= dol_print_date($selected, 'dayhour');
6098 } else {
6099 $ret .= dol_print_date($selected, 'day');
6100 }
6101 }
6102
6103 if (empty($nooutput)) {
6104 print $ret;
6105 }
6106 return $ret;
6107 }
6108
6109
6110 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6111
6122 public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = array(), $include = array())
6123 {
6124 // phpcs:enable
6125 global $langs;
6126
6127 if ($htmlname != "none") {
6128 print '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
6129 print '<input type="hidden" name="action" value="set' . $htmlname . '">';
6130 print '<input type="hidden" name="token" value="' . newToken() . '">';
6131 print $this->select_dolusers($selected, $htmlname, 1, $exclude, 0, $include);
6132 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6133 print '</form>';
6134 } else {
6135 if ($selected) {
6136 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
6137 $theuser = new User($this->db);
6138 $theuser->fetch($selected);
6139 print $theuser->getNomUrl(1);
6140 } else {
6141 print "&nbsp;";
6142 }
6143 }
6144 }
6145
6146
6147 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6148
6162 public function form_modes_reglement($page, $selected = '', $htmlname = 'mode_reglement_id', $filtertype = '', $active = 1, $addempty = 0, $type = '', $nooutput = 0)
6163 {
6164 // phpcs:enable
6165 global $langs;
6166
6167 $out = '';
6168 if ($htmlname != "none") {
6169 $out .= '<form method="POST" action="' . $page . '">';
6170 $out .= '<input type="hidden" name="action" value="setmode">';
6171 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6172 if ($type) {
6173 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
6174 }
6175 $out .= $this->select_types_paiements($selected, $htmlname, $filtertype, 0, $addempty, 0, 0, $active, '', 1);
6176 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6177 $out .= '</form>';
6178 } else {
6179 if ($selected) {
6181 $out .= $this->cache_types_paiements[$selected]['label'];
6182 } else {
6183 $out .= "&nbsp;";
6184 }
6185 }
6186
6187 if ($nooutput) {
6188 return $out;
6189 } else {
6190 print $out;
6191 }
6192 return '';
6193 }
6194
6205 public function formSelectTransportMode($page, $selected = '', $htmlname = 'transport_mode_id', $active = 1, $addempty = 0)
6206 {
6207 global $langs;
6208 if ($htmlname != "none") {
6209 print '<form method="POST" action="' . $page . '">';
6210 print '<input type="hidden" name="action" value="settransportmode">';
6211 print '<input type="hidden" name="token" value="' . newToken() . '">';
6212 $this->selectTransportMode($selected, $htmlname, 0, $addempty, 0, 0, $active);
6213 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6214 print '</form>';
6215 } else {
6216 if ($selected) {
6218 print $this->cache_transport_mode[$selected]['label'];
6219 } else {
6220 print "&nbsp;";
6221 }
6222 }
6223 }
6224
6225 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6226
6235 public function form_multicurrency_code($page, $selected = '', $htmlname = 'multicurrency_code')
6236 {
6237 // phpcs:enable
6238 global $langs;
6239 if ($htmlname != "none") {
6240 print '<form method="POST" action="' . $page . '">';
6241 print '<input type="hidden" name="action" value="setmulticurrencycode">';
6242 print '<input type="hidden" name="token" value="' . newToken() . '">';
6243 print $this->selectMultiCurrency($selected, $htmlname, 0);
6244 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6245 print '</form>';
6246 } else {
6247 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6248 print !empty($selected) ? currency_name($selected, 1) : '&nbsp;';
6249 }
6250 }
6251
6252 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6253
6263 public function form_multicurrency_rate($page, $rate = 0.0, $htmlname = 'multicurrency_tx', $currency = '')
6264 {
6265 // phpcs:enable
6266 global $langs, $mysoc, $conf;
6267
6268 if ($htmlname != "none") {
6269 print '<form method="POST" action="' . $page . '">';
6270 print '<input type="hidden" name="action" value="setmulticurrencyrate">';
6271 print '<input type="hidden" name="token" value="' . newToken() . '">';
6272 print '<input type="text" class="maxwidth75" name="' . $htmlname . '" value="' . (!empty($rate) ? price(price2num($rate, 'CU')) : 1) . '" /> ';
6273 print '<select name="calculation_mode" id="calculation_mode">';
6274 print '<option value="1">Change ' . $langs->trans("PriceUHT") . ' of lines</option>';
6275 print '<option value="2">Change ' . $langs->trans("PriceUHTCurrency") . ' of lines</option>';
6276 print '</select> ';
6277 print ajax_combobox("calculation_mode");
6278 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6279 print '</form>';
6280 } else {
6281 if (!empty($rate)) {
6282 print price($rate, 1, $langs, 0, 0);
6283 if ($currency && $rate != 1) {
6284 print ' &nbsp; <span class="opacitymedium">(' . price($rate, 1, $langs, 0, 0) . ' ' . $currency . ' = 1 ' . $conf->currency . ')</span>';
6285 }
6286 } else {
6287 print 1;
6288 }
6289 }
6290 }
6291
6292
6293 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6294
6310 public function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter = '', $maxvalue = 0, $more = '', $hidelist = 0, $discount_type = 0)
6311 {
6312 // phpcs:enable
6313 global $conf, $langs;
6314 if ($htmlname != "none") {
6315 print '<form method="post" action="' . $page . '">';
6316 print '<input type="hidden" name="action" value="setabsolutediscount">';
6317 print '<input type="hidden" name="token" value="' . newToken() . '">';
6318 print '<div class="inline-block">';
6319 if (!empty($discount_type)) {
6320 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
6321 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL") {
6322 $translationKey = 'HasAbsoluteDiscountFromSupplier'; // If we want deposit to be subtracted to payments only and not to total of final invoice
6323 } else {
6324 $translationKey = 'HasCreditNoteFromSupplier';
6325 }
6326 } else {
6327 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6328 $translationKey = 'HasAbsoluteDiscountFromSupplier';
6329 } else {
6330 $translationKey = 'HasCreditNoteFromSupplier';
6331 }
6332 }
6333 } else {
6334 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
6335 if (!$filter || $filter == "fk_facture_source IS NULL") {
6336 $translationKey = 'CompanyHasAbsoluteDiscount'; // If we want deposit to be subtracted to payments only and not to total of final invoice
6337 } else {
6338 $translationKey = 'CompanyHasCreditNote';
6339 }
6340 } else {
6341 if (!$filter || $filter == "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6342 $translationKey = 'CompanyHasAbsoluteDiscount';
6343 } else {
6344 $translationKey = 'CompanyHasCreditNote';
6345 }
6346 }
6347 }
6348 print $langs->trans($translationKey, price($amount, 0, $langs, 0, 0, -1, $conf->currency));
6349 if (empty($hidelist)) {
6350 print ' ';
6351 }
6352 print '</div>';
6353 if (empty($hidelist)) {
6354 print '<div class="inline-block" style="padding-right: 10px">';
6355 $newfilter = 'discount_type=' . intval($discount_type);
6356 if (!empty($discount_type)) {
6357 $newfilter .= ' AND fk_invoice_supplier IS NULL AND fk_invoice_supplier_line IS NULL'; // Supplier discounts available
6358 } else {
6359 $newfilter .= ' AND fk_facture IS NULL AND fk_facture_line IS NULL'; // Customer discounts available
6360 }
6361 if ($filter) {
6362 $newfilter .= ' AND (' . $filter . ')';
6363 }
6364 // output the combo of discounts
6365 $nbqualifiedlines = $this->select_remises((string) $selected, $htmlname, $newfilter, $socid, $maxvalue);
6366 if ($nbqualifiedlines > 0) {
6367 print ' &nbsp; <input type="submit" class="button smallpaddingimp" value="' . dol_escape_htmltag($langs->trans("UseLine")) . '"';
6368 if (!empty($discount_type) && $filter && $filter != "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6369 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6370 }
6371 if (empty($discount_type) && $filter && $filter != "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6372 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6373 }
6374
6375 print '>';
6376 }
6377 print '</div>';
6378 }
6379 if ($more) {
6380 print '<div class="inline-block">';
6381 print $more;
6382 print '</div>';
6383 }
6384 print '</form>';
6385 } else {
6386 if ($selected) {
6387 print $selected;
6388 } else {
6389 print "0";
6390 }
6391 }
6392 }
6393
6394
6395 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6396
6406 public function form_contacts($page, $societe, $selected = '', $htmlname = 'contactid')
6407 {
6408 // phpcs:enable
6409 global $langs;
6410
6411 if ($htmlname != "none") {
6412 print '<form method="post" action="' . $page . '">';
6413 print '<input type="hidden" name="action" value="set_contact">';
6414 print '<input type="hidden" name="token" value="' . newToken() . '">';
6415 print '<table class="nobordernopadding">';
6416 print '<tr><td>';
6417 print $this->selectcontacts($societe->id, $selected, $htmlname);
6418 $num = $this->num;
6419 if ($num == 0) {
6420 $addcontact = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("AddContact") : $langs->trans("AddContactAddress"));
6421 print '<a href="' . DOL_URL_ROOT . '/contact/card.php?socid=' . $societe->id . '&amp;action=create&amp;backtoreferer=1">' . $addcontact . '</a>';
6422 }
6423 print '</td>';
6424 print '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6425 print '</tr></table></form>';
6426 } else {
6427 if ($selected) {
6428 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
6429 $contact = new Contact($this->db);
6430 $contact->fetch($selected);
6431 print $contact->getFullName($langs);
6432 } else {
6433 print "&nbsp;";
6434 }
6435 }
6436 }
6437
6438 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6439
6456 public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0, $excludeids = array(), $textifnothirdparty = '')
6457 {
6458 // phpcs:enable
6459 global $langs;
6460
6461 $out = '';
6462 if ($htmlname != "none") {
6463 $out .= '<form method="post" action="' . $page . '">';
6464 $out .= '<input type="hidden" name="action" value="set_thirdparty">';
6465 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6466 $out .= $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, 0, 'minwidth100', '', '', 1, array(), false, $excludeids);
6467 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6468 $out .= '</form>';
6469 } else {
6470 if ($selected) {
6471 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
6472 $soc = new Societe($this->db);
6473 $soc->fetch($selected);
6474 $out .= $soc->getNomUrl(0, '');
6475 } else {
6476 $out .= '<span class="opacitymedium">' . $textifnothirdparty . '</span>';
6477 }
6478 }
6479
6480 if ($nooutput) {
6481 return $out;
6482 } else {
6483 print $out;
6484 }
6485
6486 return '';
6487 }
6488
6489 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6490
6499 public function select_currency($selected = '', $htmlname = 'currency_id')
6500 {
6501 // phpcs:enable
6502 print $this->selectCurrency($selected, $htmlname);
6503 }
6504
6514 public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0, $useempty = '')
6515 {
6516 global $langs, $user;
6517
6518 $langs->loadCacheCurrencies('');
6519
6520 $out = '';
6521
6522 if ($selected == 'euro' || $selected == 'euros') {
6523 $selected = 'EUR'; // Pour compatibilite
6524 }
6525
6526 $out .= '<select class="flat maxwidth200onsmartphone minwidth300" name="' . $htmlname . '" id="' . $htmlname . '">';
6527 if ($useempty) {
6528 $out .= '<option value="-1" selected></option>';
6529 }
6530 foreach ($langs->cache_currencies as $code_iso => $currency) {
6531 $labeltoshow = $currency['label'];
6532 if ($mode == 1) {
6533 $labeltoshow .= ' <span class="opacitymedium">(' . $code_iso . ')</span>';
6534 } else {
6535 $labeltoshow .= ' <span class="opacitymedium">(' . $langs->getCurrencySymbol($code_iso) . ')</span>';
6536 }
6537
6538 if ($selected && $selected == $code_iso) {
6539 $out .= '<option value="' . $code_iso . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6540 } else {
6541 $out .= '<option value="' . $code_iso . '" data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6542 }
6543 $out .= $labeltoshow;
6544 $out .= '</option>';
6545 }
6546 $out .= '</select>';
6547 if ($user->admin) {
6548 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
6549 }
6550
6551 // Make select dynamic
6552 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6553 $out .= ajax_combobox($htmlname);
6554
6555 return $out;
6556 }
6557
6570 public function selectMultiCurrency($selected = '', $htmlname = 'multicurrency_code', $useempty = 0, $filter = '', $excludeConfCurrency = false, $morecss = '')
6571 {
6572 global $conf, $langs;
6573
6574 $langs->loadCacheCurrencies(''); // Load ->cache_currencies
6575
6576 $TCurrency = array();
6577
6578 $sql = "SELECT code FROM " . $this->db->prefix() . "multicurrency";
6579 $sql .= " WHERE entity IN ('" . getEntity('mutlicurrency') . "')";
6580 if ($filter) {
6581 $sql .= " AND " . $filter;
6582 }
6583 $resql = $this->db->query($sql);
6584 if ($resql) {
6585 while ($obj = $this->db->fetch_object($resql)) {
6586 $TCurrency[$obj->code] = $obj->code;
6587 }
6588 }
6589
6590 $out = '';
6591 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
6592 if ($useempty) {
6593 $out .= '<option value="">&nbsp;</option>';
6594 }
6595 // If company current currency not in table, we add it into list. Should always be available.
6596 if (!in_array($conf->currency, $TCurrency) && !$excludeConfCurrency) {
6597 $TCurrency[$conf->currency] = $conf->currency;
6598 }
6599 if (count($TCurrency) > 0) {
6600 foreach ($langs->cache_currencies as $code_iso => $currency) {
6601 if (isset($TCurrency[$code_iso])) {
6602 if (!empty($selected) && $selected == $code_iso) {
6603 $out .= '<option value="' . $code_iso . '" selected="selected">';
6604 } else {
6605 $out .= '<option value="' . $code_iso . '">';
6606 }
6607
6608 $out .= $currency['label'];
6609 $out .= ' (' . $langs->getCurrencySymbol($code_iso) . ')';
6610 $out .= '</option>';
6611 }
6612 }
6613 }
6614
6615 $out .= '</select>';
6616
6617 // Make select dynamic
6618 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6619 $out .= ajax_combobox($htmlname);
6620
6621 return $out;
6622 }
6623
6624 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6625
6632 public function load_cache_vatrates($country_code)
6633 {
6634 // phpcs:enable
6635 global $langs, $user;
6636
6637 $num = count($this->cache_vatrates);
6638 if ($num > 0) {
6639 return $num; // Cache already loaded
6640 }
6641
6642 dol_syslog(__METHOD__, LOG_DEBUG);
6643
6644 $sql = "SELECT t.rowid, t.type_vat, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
6645 $sql .= " FROM ".$this->db->prefix()."c_tva as t, ".$this->db->prefix()."c_country as c";
6646 $sql .= " WHERE t.fk_pays = c.rowid";
6647 $sql .= " AND t.active > 0";
6648 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
6649 $sql .= " AND c.code IN (" . $this->db->sanitize($country_code, 1) . ")";
6650 $sql .= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC";
6651
6652 $resql = $this->db->query($sql);
6653 if ($resql) {
6654 $num = $this->db->num_rows($resql);
6655 if ($num) {
6656 for ($i = 0; $i < $num; $i++) {
6657 $obj = $this->db->fetch_object($resql);
6658
6659 $tmparray = array();
6660 $tmparray['rowid'] = $obj->rowid;
6661 $tmparray['type_vat'] = $obj->type_vat;
6662 $tmparray['code'] = $obj->code;
6663 $tmparray['txtva'] = $obj->taux;
6664 $tmparray['nprtva'] = $obj->recuperableonly;
6665 $tmparray['localtax1'] = $obj->localtax1;
6666 $tmparray['localtax1_type'] = $obj->localtax1_type;
6667 $tmparray['localtax2'] = $obj->localtax2;
6668 $tmparray['localtax2_type'] = $obj->localtax1_type;
6669 $tmparray['label'] = $obj->taux . '%' . ($obj->code ? ' (' . $obj->code . ')' : ''); // Label must contains only 0-9 , . % or *
6670 $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
6671 $positiverates = '';
6672 if ($obj->taux) {
6673 $positiverates .= ($positiverates ? '/' : '') . $obj->taux;
6674 }
6675 if ($obj->localtax1) {
6676 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax1;
6677 }
6678 if ($obj->localtax2) {
6679 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax2;
6680 }
6681 if (empty($positiverates)) {
6682 $positiverates = '0';
6683 }
6684 $tmparray['labelpositiverates'] = $positiverates . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
6685
6686 $this->cache_vatrates[$obj->rowid] = $tmparray;
6687 }
6688
6689 return $num;
6690 } else {
6691 $this->error = '<span class="error">';
6692 $this->error .= $langs->trans("ErrorNoVATRateDefinedForSellerCountry", $country_code);
6693 $reg = array();
6694 if (!empty($user) && $user->admin && preg_match('/\'(..)\'/', $country_code, $reg)) {
6695 $langs->load("errors");
6696 $new_country_code = $reg[1];
6697 $country_id = dol_getIdFromCode($this->db, $new_country_code, 'c_pays', 'code', 'rowid');
6698 $this->error .= '<br>'.$langs->trans("ErrorFixThisHere", DOL_URL_ROOT.'/admin/dict.php?id=10'.($country_id > 0 ? '&countryidforinsert='.$country_id : ''));
6699 }
6700 $this->error .= '</span>';
6701 return -1;
6702 }
6703 } else {
6704 $this->error = '<span class="error">' . $this->db->error() . '</span>';
6705 return -2;
6706 }
6707 }
6708
6709 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6710
6733 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)
6734 {
6735 // phpcs:enable
6736 global $langs, $mysoc;
6737
6738 $langs->load('errors');
6739
6740 $return = '';
6741
6742 // Define defaultnpr, defaultttx and defaultcode
6743 $defaultnpr = ($info_bits & 0x01);
6744 $defaultnpr = (preg_match('/\*/', $selectedrate) ? 1 : $defaultnpr);
6745 $defaulttx = str_replace('*', '', $selectedrate);
6746 $defaultcode = '';
6747 $reg = array();
6748 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6749 $defaultcode = $reg[1];
6750 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6751 }
6752 //var_dump($selectedrate.'-'.$defaulttx.'-'.$defaultnpr.'-'.$defaultcode);
6753
6754 // Check parameters
6755 if (is_object($societe_vendeuse) && !$societe_vendeuse->country_code) {
6756 if ($societe_vendeuse->id == $mysoc->id) {
6757 $return .= '<span class="error">' . $langs->trans("ErrorYourCountryIsNotDefined") . '</span>';
6758 } else {
6759 $return .= '<span class="error">' . $langs->trans("ErrorSupplierCountryIsNotDefined") . '</span>';
6760 }
6761 return $return;
6762 }
6763
6764 //var_dump($societe_acheteuse);
6765 //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";
6766 //exit;
6767
6768 // Define list of countries to use to search VAT rates to show
6769 // First we defined code_country to use to find list
6770 if (is_object($societe_vendeuse)) {
6771 $code_country = "'" . $societe_vendeuse->country_code . "'";
6772 } else {
6773 $code_country = "'" . $mysoc->country_code . "'"; // Pour compatibilite ascendente
6774 }
6775 if (getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC')) { // If option to have vat for end customer for services is on
6776 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6777 // If SERVICE_ARE_ECOMMERCE_200238EC=1 combo list vat rate of purchaser and seller countries
6778 // If SERVICE_ARE_ECOMMERCE_200238EC=2 combo list only the vat rate of the purchaser country
6779 $selectVatComboMode = getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC');
6780 if (isInEEC($societe_vendeuse) && isInEEC($societe_acheteuse) && !$societe_acheteuse->isACompany()) {
6781 // We also add the buyer country code
6782 if (is_numeric($type)) {
6783 if ($type == 1) { // We know product is a service
6784 switch ($selectVatComboMode) {
6785 case '1':
6786 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6787 break;
6788 case '2':
6789 $code_country = "'" . $societe_acheteuse->country_code . "'";
6790 break;
6791 }
6792 }
6793 } elseif (!$idprod) { // We don't know type of product
6794 switch ($selectVatComboMode) {
6795 case '1':
6796 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6797 break;
6798 case '2':
6799 $code_country = "'" . $societe_acheteuse->country_code . "'";
6800 break;
6801 }
6802 } else {
6803 $prodstatic = new Product($this->db);
6804 $prodstatic->fetch($idprod);
6805 if ($prodstatic->type == Product::TYPE_SERVICE) { // We know product is a service
6806 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6807 }
6808 }
6809 }
6810 }
6811
6812 // Now we load the list of VAT
6813 $this->load_cache_vatrates($code_country); // If no vat defined, return -1 with message into this->error
6814
6815 // Keep only the VAT qualified for $type_vat
6816 $arrayofvatrates = array();
6817 foreach ($this->cache_vatrates as $cachevalue) {
6818 if (empty($cachevalue['type_vat']) || $cachevalue['type_vat'] != $type_vat) {
6819 $arrayofvatrates[] = $cachevalue;
6820 }
6821 }
6822
6823 $num = count($arrayofvatrates);
6824
6825 if ($num > 0) {
6826 // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '')
6827 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6828 $tmpthirdparty = new Societe($this->db);
6829
6830 $defaulttx = get_default_tva($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6831 $defaultnpr = get_default_npr($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6832
6833 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6834 $defaultcode = $reg[1];
6835 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6836 }
6837 if (empty($defaulttx)) {
6838 $defaultnpr = 0;
6839 }
6840 }
6841
6842 // If we fails to find a default vat rate, we take the last one in list
6843 // Because they are sorted in ascending order, the last one will be the higher one (we suppose the higher one is the current rate)
6844 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6845 if (!getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS')) {
6846 // We take the last one found in list
6847 $defaulttx = $arrayofvatrates[$num - 1]['txtva'];
6848 } else {
6849 // We will use the rate defined into MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS
6850 $defaulttx = '';
6851 if (getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS') != 'none') {
6852 $defaulttx = getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS');
6853 }
6854 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6855 $defaultcode = $reg[1];
6856 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6857 }
6858 }
6859 }
6860
6861 // Disabled if seller is not subject to VAT
6862 $disabled = false;
6863 $title = '';
6864 if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0") {
6865 // Override/enable VAT for expense report regardless of global setting - needed if expense report used for business expenses instead
6866 // of using supplier invoices (this is a very bad idea !)
6867 if (!getDolGlobalString('EXPENSEREPORT_OVERRIDE_VAT')) {
6868 $title = ' title="' . dol_escape_htmltag($langs->trans('VATIsNotUsed')) . '"';
6869 $disabled = true;
6870 }
6871 }
6872
6873 if (!$options_only) {
6874 $return .= '<select class="flat minwidth75imp maxwidth100 right" id="' . $htmlname . '" name="' . $htmlname . '"' . ($disabled ? ' disabled' : '') . $title . '>';
6875 }
6876
6877 $selectedfound = false;
6878 foreach ($arrayofvatrates as $rate) {
6879 // Keep only 0 if seller is not subject to VAT
6880 if ($disabled && $rate['txtva'] != 0) {
6881 continue;
6882 }
6883
6884 // Define key to use into select list
6885 $key = $rate['txtva'];
6886 $key .= $rate['nprtva'] ? '*' : '';
6887 if ($mode > 0 && $rate['code']) {
6888 $key .= ' (' . $rate['code'] . ')';
6889 }
6890 if ($mode < 0) {
6891 $key = $rate['rowid'];
6892 }
6893
6894 $return .= '<option value="' . $key . '"';
6895 if (!$selectedfound) {
6896 if ($defaultcode) { // If defaultcode is defined, we used it in priority to select combo option instead of using rate+npr flag
6897 if ($defaultcode == $rate['code']) {
6898 $return .= ' selected';
6899 $selectedfound = true;
6900 }
6901 } elseif ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr) {
6902 $return .= ' selected';
6903 $selectedfound = true;
6904 }
6905 }
6906 $return .= '>';
6907
6908 // Show label of VAT
6909 if ($mysoc->country_code == 'IN' || getDolGlobalString('MAIN_VAT_LABEL_IS_POSITIVE_RATES')) {
6910 // Label with all localtax and code. For example: x.y / a.b / c.d (CODE)'
6911 $return .= $rate['labelpositiverates'];
6912 } else {
6913 // Simple label
6914 $return .= vatrate($rate['label']);
6915 }
6916
6917 //$return.=($rate['code']?' '.$rate['code']:'');
6918 $return .= (empty($rate['code']) && $rate['nprtva']) ? ' *' : ''; // We show the * (old behaviour only if new vat code is not used)
6919
6920 $return .= '</option>';
6921 }
6922
6923 if (!$options_only) {
6924 $return .= '</select>';
6925 //$return .= ajax_combobox($htmlname); // This break for the moment the dynamic autoselection of a value when selecting a product in object lines
6926 }
6927 } else {
6928 $return .= $this->error;
6929 }
6930
6931 $this->num = $num;
6932 return $return;
6933 }
6934
6935
6936 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6937
6962 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 = '')
6963 {
6964 // phpcs:enable
6965 dol_syslog(__METHOD__ . ': using select_date is deprecated. Use selectDate instead.', LOG_WARNING);
6966 $retstring = $this->selectDate($set_time, $prefix, $h, $m, $empty, $form_name, $d, $addnowlink, $disabled, $fullday, $addplusone, $adddateof);
6967 if (!empty($nooutput)) {
6968 return $retstring;
6969 }
6970 print $retstring;
6971
6972 return '';
6973 }
6974
6990 public function selectDateToDate($set_time = '', $set_time_end = '', $prefix = 're', $empty = 0, $forcenewline = 0)
6991 {
6992 global $langs;
6993
6994 $ret = $this->selectDate($set_time, $prefix . '_start', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("from"), 'tzuserrel');
6995 if ($forcenewline) {
6996 $ret .= '<br>';
6997 }
6998 $ret .= $this->selectDate($set_time_end, $prefix . '_end', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"), 'tzuserrel');
6999 return $ret;
7000 }
7001
7029 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')
7030 {
7031 global $conf, $langs;
7032
7033 if ($gm === 'auto') {
7034 $gm = (empty($conf) ? 'tzserver' : $conf->tzuserinputkey);
7035 }
7036
7037 $retstring = '';
7038
7039 if ($prefix == '') {
7040 $prefix = 're';
7041 }
7042 if ($h == '') {
7043 $h = 0;
7044 }
7045 if ($m == '') {
7046 $m = 0;
7047 }
7048 $emptydate = 0;
7049 $emptyhours = 0;
7050 if ($stepminutes <= 0 || $stepminutes > 30) {
7051 $stepminutes = 1;
7052 }
7053 if ($empty == 1) {
7054 $emptydate = 1;
7055 $emptyhours = 1;
7056 }
7057 if ($empty == 2) {
7058 $emptydate = 0;
7059 $emptyhours = 1;
7060 }
7061 $orig_set_time = $set_time;
7062
7063 if ($set_time === '' && $emptydate == 0) {
7064 include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7065 if ($gm == 'tzuser' || $gm == 'tzuserrel') {
7066 $set_time = dol_now($gm);
7067 } else {
7068 $set_time = dol_now('tzuser') - (getServerTimeZoneInt('now') * 3600); // set_time must be relative to PHP server timezone
7069 }
7070 }
7071
7072 // Analysis of the pre-selection date
7073 $reg = array();
7074 $shour = '';
7075 $smin = '';
7076 $ssec = '';
7077 if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', $set_time, $reg)) { // deprecated usage
7078 // Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'
7079 $syear = (!empty($reg[1]) ? $reg[1] : '');
7080 $smonth = (!empty($reg[2]) ? $reg[2] : '');
7081 $sday = (!empty($reg[3]) ? $reg[3] : '');
7082 $shour = (!empty($reg[4]) ? $reg[4] : '');
7083 $smin = (!empty($reg[5]) ? $reg[5] : '');
7084 } elseif (strval($set_time) != '' && $set_time != -1) {
7085 // set_time est un timestamps (0 possible)
7086 $syear = dol_print_date($set_time, "%Y", $gm);
7087 $smonth = dol_print_date($set_time, "%m", $gm);
7088 $sday = dol_print_date($set_time, "%d", $gm);
7089 if ($orig_set_time != '') {
7090 $shour = dol_print_date($set_time, "%H", $gm);
7091 $smin = dol_print_date($set_time, "%M", $gm);
7092 $ssec = dol_print_date($set_time, "%S", $gm);
7093 }
7094 } else {
7095 // Date est '' ou vaut -1
7096 $syear = '';
7097 $smonth = '';
7098 $sday = '';
7099 $shour = getDolGlobalString('MAIN_DEFAULT_DATE_HOUR', ($h == -1 ? '23' : ''));
7100 $smin = getDolGlobalString('MAIN_DEFAULT_DATE_MIN', ($h == -1 ? '59' : ''));
7101 $ssec = getDolGlobalString('MAIN_DEFAULT_DATE_SEC', ($h == -1 ? '59' : ''));
7102 }
7103 if ($h == 3 || $h == 4) {
7104 $shour = '';
7105 }
7106 if ($m == 3) {
7107 $smin = '';
7108 }
7109
7110 $nowgmt = dol_now('gmt');
7111 //var_dump(dol_print_date($nowgmt, 'dayhourinputnoreduce', 'tzuserrel'));
7112
7113 // You can set MAIN_POPUP_CALENDAR to 'eldy' or 'jquery'
7114 $usecalendar = 'combo';
7115 if (!empty($conf->use_javascript_ajax) && (!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') != "none")) {
7116 $usecalendar = ((!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') == 'eldy') ? 'jquery' : $conf->global->MAIN_POPUP_CALENDAR);
7117 }
7118 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7119 // If we use a text browser or screen reader, we use the 'combo' date selector
7120 $usecalendar = 'html';
7121 }
7122
7123 if ($d) {
7124 // Show date with popup
7125 if ($usecalendar != 'combo') {
7126 $formated_date = '';
7127 //print "e".$set_time." t ".$conf->format_date_short;
7128 if (strval($set_time) != '' && $set_time != -1) {
7129 //$formated_date=dol_print_date($set_time,$conf->format_date_short);
7130 $formated_date = dol_print_date($set_time, $langs->trans("FormatDateShortInput"), $gm); // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7131 }
7132
7133 // Calendrier popup version eldy
7134 if ($usecalendar == "eldy") {
7135 // Input area to enter date manually
7136 $retstring .= '<input id="' . $prefix . '" name="' . $prefix . '" type="text" class="maxwidthdate center" maxlength="11" value="' . $formated_date . '"';
7137 $retstring .= ($disabled ? ' disabled' : '');
7138 $retstring .= ' onChange="dpChangeDay(\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7139 $retstring .= ' autocomplete="off">';
7140
7141 // Icon calendar
7142 $retstringbuttom = '';
7143 if (!$disabled) {
7144 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons"';
7145 $base = DOL_URL_ROOT . '/core/';
7146 $retstringbuttom .= ' onClick="showDP(\'' . $base . '\',\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\',\'' . $langs->defaultlang . '\');"';
7147 $retstringbuttom .= '>' . img_object($langs->trans("SelectDate"), 'calendarday', 'class="datecallink"') . '</button>';
7148 } else {
7149 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
7150 }
7151 $retstring = $retstringbuttom . $retstring;
7152
7153 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
7154 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
7155 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
7156 } elseif ($usecalendar == 'jquery' || $usecalendar == 'html') {
7157 if (!$disabled && $usecalendar != 'html') {
7158 // Output javascript for datepicker
7159 $minYear = getDolGlobalInt('MIN_YEAR_SELECT_DATE', (idate('Y') - 100));
7160 $maxYear = getDolGlobalInt('MAX_YEAR_SELECT_DATE', (idate('Y') + 100));
7161
7162 $retstring .= '<script nonce="' . getNonce() . '" type="text/javascript">';
7163 $retstring .= "$(function(){ $('#" . $prefix . "').datepicker({
7164 dateFormat: '" . $langs->trans("FormatDateShortJQueryInput") . "',
7165 autoclose: true,
7166 todayHighlight: true,
7167 yearRange: '" . $minYear . ":" . $maxYear . "',";
7168 if (!empty($conf->dol_use_jmobile)) {
7169 $retstring .= "
7170 beforeShow: function (input, datePicker) {
7171 input.disabled = true;
7172 },
7173 onClose: function (dateText, datePicker) {
7174 this.disabled = false;
7175 },
7176 ";
7177 }
7178 // Note: We don't need monthNames, monthNamesShort, dayNames, dayNamesShort, dayNamesMin, they are set globally on datepicker component in lib_head.js.php
7179 if (!getDolGlobalString('MAIN_POPUP_CALENDAR_ON_FOCUS')) {
7180 $retstring .= "
7181 showOn: 'button', /* both has problem with autocompletion */
7182 buttonImage: '" . DOL_URL_ROOT . "/theme/" . dol_escape_js($conf->theme) . "/img/object_calendarday.png',
7183 buttonImageOnly: true";
7184 }
7185 $retstring .= "
7186 }) });";
7187 $retstring .= "</script>";
7188 }
7189
7190 // Input area to enter date manually
7191 $retstring .= '<div class="nowraponall inline-block divfordateinput">';
7192 $retstring .= '<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidthdate center" maxlength="11" value="'.$formated_date.'"';
7193 $retstring .= ($disabled ? ' disabled' : '');
7194 $retstring .= ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '');
7195 $retstring .= ' onChange="dpChangeDay(\'' . dol_escape_js($prefix) . '\',\'' . dol_escape_js($langs->trans("FormatDateShortJavaInput")) . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
7196 $retstring .= ' autocomplete="off">';
7197
7198 // Icone calendrier
7199 if ($disabled) {
7200 $retstringbutton = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
7201 $retstring = $retstringbutton . $retstring;
7202 }
7203
7204 $retstring .= '</div>';
7205 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
7206 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
7207 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
7208 } else {
7209 $retstring .= "Bad value of MAIN_POPUP_CALENDAR";
7210 }
7211 } else {
7212 // Show date with combo selects
7213 // Day
7214 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50imp" id="' . $prefix . 'day" name="' . $prefix . 'day">';
7215
7216 if ($emptydate || $set_time == -1) {
7217 $retstring .= '<option value="0" selected>&nbsp;</option>';
7218 }
7219
7220 for ($day = 1; $day <= 31; $day++) {
7221 $retstring .= '<option value="' . $day . '"' . ($day == $sday ? ' selected' : '') . '>' . $day . '</option>';
7222 }
7223
7224 $retstring .= "</select>";
7225
7226 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'month" name="' . $prefix . 'month">';
7227 if ($emptydate || $set_time == -1) {
7228 $retstring .= '<option value="0" selected>&nbsp;</option>';
7229 }
7230
7231 // Month
7232 for ($month = 1; $month <= 12; $month++) {
7233 $retstring .= '<option value="' . $month . '"' . ($month == $smonth ? ' selected' : '') . '>';
7234 $retstring .= dol_print_date(mktime(12, 0, 0, $month, 1, 2000), "%b");
7235 $retstring .= "</option>";
7236 }
7237 $retstring .= "</select>";
7238
7239 // Year
7240 if ($emptydate || $set_time == -1) {
7241 $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 . '">';
7242 } else {
7243 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'year" name="' . $prefix . 'year">';
7244
7245 $syear = (int) $syear;
7246 for ($year = $syear - 10; $year < (int) $syear + 10; $year++) {
7247 $retstring .= '<option value="' . $year . '"' . ($year == $syear ? ' selected' : '') . '>' . $year . '</option>';
7248 }
7249 $retstring .= "</select>\n";
7250 }
7251 }
7252 }
7253
7254 if ($d && $h) {
7255 $retstring .= (($h == 2 || $h == 4) ? '<br>' : ' ');
7256 $retstring .= '<span class="nowraponall">';
7257 }
7258
7259 if ($h) {
7260 $hourstart = 0;
7261 $hourend = 24;
7262 if ($openinghours != '') {
7263 $openinghours = explode(',', $openinghours);
7264 $hourstart = $openinghours[0];
7265 $hourend = $openinghours[1];
7266 if ($hourend < $hourstart) {
7267 $hourend = $hourstart;
7268 }
7269 }
7270 // Show hour
7271 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'hour' : '') . '" id="' . $prefix . 'hour" name="' . $prefix . 'hour">';
7272 if ($emptyhours) {
7273 $retstring .= '<option value="-1">&nbsp;</option>';
7274 }
7275 for ($hour = $hourstart; $hour < $hourend; $hour++) {
7276 if (strlen($hour) < 2) {
7277 $hour = "0" . $hour;
7278 }
7279 $retstring .= '<option value="' . $hour . '"' . (($hour == $shour) ? ' selected' : '') . '>' . $hour;
7280 //$retstring .= (empty($conf->dol_optimize_smallscreen) ? '' : 'H');
7281 $retstring .= '</option>';
7282 }
7283 $retstring .= '</select>';
7284 //if ($m && empty($conf->dol_optimize_smallscreen)) $retstring .= ":";
7285 if ($m) {
7286 $retstring .= ":";
7287 }
7288 }
7289
7290 if ($m) {
7291 // Show minutes
7292 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'min' : '') . '" id="' . $prefix . 'min" name="' . $prefix . 'min">';
7293 if ($emptyhours) {
7294 $retstring .= '<option value="-1">&nbsp;</option>';
7295 }
7296 for ($min = 0; $min < 60; $min += $stepminutes) {
7297 $min_str = sprintf("%02d", $min);
7298 $retstring .= '<option value="' . $min_str . '"' . (($min_str == $smin) ? ' selected' : '') . '>' . $min_str . '</option>';
7299 }
7300 $retstring .= '</select>';
7301
7302 $retstring .= '<input type="hidden" name="' . $prefix . 'sec" value="' . $ssec . '">';
7303 }
7304
7305 if ($d && $h) {
7306 $retstring .= '</span>';
7307 }
7308
7309 // Add a "Now" link
7310 if (!empty($conf->use_javascript_ajax) && $addnowlink) {
7311 // Script which will be inserted in the onClick of the "Now" link
7312 $reset_scripts = "";
7313 if ($addnowlink == 2) { // local computer time
7314 // pad add leading 0 on numbers
7315 $reset_scripts .= "Number.prototype.pad = function(size) {
7316 var s = String(this);
7317 while (s.length < (size || 2)) {s = '0' + s;}
7318 return s;
7319 };
7320 var d = new Date();";
7321 }
7322
7323 // Generate the date part, depending on the use or not of the javascript calendar
7324 if ($addnowlink == 1) { // server time expressed in user time setup
7325 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7326 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7327 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7328 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7329 } elseif ($addnowlink == 2) {
7330 /* Disabled because the output does not use the string format defined by FormatDateShort key to forge the value into #prefix.
7331 * This break application for foreign languages.
7332 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(d.toLocaleDateString(\''.str_replace('_', '-', $langs->defaultlang).'\'));';
7333 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(d.getDate().pad());';
7334 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(parseInt(d.getMonth().pad()) + 1);';
7335 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(d.getFullYear());';
7336 */
7337 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7338 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7339 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7340 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7341 }
7342 /*if ($usecalendar == "eldy")
7343 {
7344 $base=DOL_URL_ROOT.'/core/';
7345 $reset_scripts .= 'resetDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');';
7346 }
7347 else
7348 {
7349 $reset_scripts .= 'this.form.elements[\''.$prefix.'day\'].value=formatDate(new Date(), \'d\'); ';
7350 $reset_scripts .= 'this.form.elements[\''.$prefix.'month\'].value=formatDate(new Date(), \'M\'); ';
7351 $reset_scripts .= 'this.form.elements[\''.$prefix.'year\'].value=formatDate(new Date(), \'yyyy\'); ';
7352 }*/
7353 // Update the hour part
7354 if ($h) {
7355 if ($fullday) {
7356 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7357 }
7358 //$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); ';
7359 if ($addnowlink == 1) {
7360 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7361 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7362 } elseif ($addnowlink == 2) {
7363 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(d.getHours().pad());';
7364 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7365 }
7366
7367 if ($fullday) {
7368 $reset_scripts .= ' } ';
7369 }
7370 }
7371 // Update the minute part
7372 if ($m) {
7373 if ($fullday) {
7374 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7375 }
7376 //$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); ';
7377 if ($addnowlink == 1) {
7378 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7379 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7380 } elseif ($addnowlink == 2) {
7381 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(d.getMinutes().pad());';
7382 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7383 }
7384 if ($fullday) {
7385 $reset_scripts .= ' } ';
7386 }
7387 }
7388 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7389 if ($reset_scripts && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7390 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonNow" type="button" name="_useless" value="now" onClick="' . $reset_scripts . '">';
7391 $retstring .= $langs->trans("Now");
7392 $retstring .= '</button> ';
7393 }
7394 }
7395
7396 // Add a "Plus one hour" link
7397 if ($conf->use_javascript_ajax && $addplusone) {
7398 // Script which will be inserted in the onClick of the "Add plusone" link
7399 $reset_scripts = "";
7400
7401 // Generate the date part, depending on the use or not of the javascript calendar
7402 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'dayinputnoreduce', 'tzuserrel') . '\');';
7403 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7404 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7405 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7406 // Update the hour part
7407 if ($h) {
7408 if ($fullday) {
7409 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7410 }
7411 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7412 if ($fullday) {
7413 $reset_scripts .= ' } ';
7414 }
7415 }
7416 // Update the minute part
7417 if ($m) {
7418 if ($fullday) {
7419 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7420 }
7421 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7422 if ($fullday) {
7423 $reset_scripts .= ' } ';
7424 }
7425 }
7426 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7427 if ($reset_scripts && empty($conf->dol_optimize_smallscreen)) {
7428 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonPlusOne" type="button" name="_useless2" value="plusone" onClick="' . $reset_scripts . '">';
7429 $retstring .= $langs->trans("DateStartPlusOne");
7430 $retstring .= '</button> ';
7431 }
7432 }
7433
7434 // Add a link to set data
7435 if ($conf->use_javascript_ajax && !empty($adddateof)) {
7436 if (!is_array($adddateof)) {
7437 $arrayofdateof = array(array('adddateof' => $adddateof, 'labeladddateof' => $labeladddateof));
7438 } else {
7439 $arrayofdateof = $adddateof;
7440 }
7441 foreach ($arrayofdateof as $valuedateof) {
7442 $tmpadddateof = empty($valuedateof['adddateof']) ? 0 : $valuedateof['adddateof'];
7443 $tmplabeladddateof = empty($valuedateof['labeladddateof']) ? '' : $valuedateof['labeladddateof'];
7444 $tmparray = dol_getdate($tmpadddateof);
7445 if (empty($tmplabeladddateof)) {
7446 $tmplabeladddateof = $langs->trans("DateInvoice");
7447 }
7448 $reset_scripts = 'console.log(\'Click on now link\'); ';
7449 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date($tmpadddateof, 'dayinputnoreduce').'\');';
7450 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.$tmparray['mday'].'\');';
7451 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.$tmparray['mon'].'\');';
7452 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.$tmparray['year'].'\');';
7453 $retstring .= ' - <button class="dpInvisibleButtons datenowlink" id="dateofinvoice" type="button" name="_dateofinvoice" value="now" onclick="'.$reset_scripts.'">'.$tmplabeladddateof.'</button>';
7454 }
7455 }
7456
7457 return $retstring;
7458 }
7459
7468 public function selectTypeDuration($prefix, $selected = 'i', $excludetypes = array())
7469 {
7470 global $langs;
7471
7472 $TDurationTypes = array(
7473 'y' => $langs->trans('Years'),
7474 'm' => $langs->trans('Month'),
7475 'w' => $langs->trans('Weeks'),
7476 'd' => $langs->trans('Days'),
7477 'h' => $langs->trans('Hours'),
7478 'i' => $langs->trans('Minutes')
7479 );
7480
7481 // Removed undesired duration types
7482 foreach ($excludetypes as $value) {
7483 unset($TDurationTypes[$value]);
7484 }
7485
7486 $retstring = '<select class="flat minwidth75 maxwidth100" id="select_' . $prefix . 'type_duration" name="' . $prefix . 'type_duration">';
7487 foreach ($TDurationTypes as $key => $typeduration) {
7488 $retstring .= '<option value="' . $key . '"';
7489 if ($key == $selected) {
7490 $retstring .= " selected";
7491 }
7492 $retstring .= ">" . $typeduration . "</option>";
7493 }
7494 $retstring .= "</select>";
7495
7496 $retstring .= ajax_combobox('select_' . $prefix . 'type_duration');
7497
7498 return $retstring;
7499 }
7500
7501 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
7502
7516 public function select_duration($prefix, $iSecond = '', $disabled = 0, $typehour = 'select', $minunderhours = 0, $nooutput = 0)
7517 {
7518 // phpcs:enable
7519 global $langs;
7520
7521 $retstring = '<span class="nowraponall">';
7522
7523 $hourSelected = '';
7524 $minSelected = '';
7525
7526 // Hours
7527 if ($iSecond != '') {
7528 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7529
7530 $hourSelected = convertSecondToTime($iSecond, 'allhour');
7531 $minSelected = convertSecondToTime($iSecond, 'min');
7532 }
7533
7534 if ($typehour == 'select') {
7535 $retstring .= '<select class="flat" id="select_' . $prefix . 'hour" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . '>';
7536 for ($hour = 0; $hour < 25; $hour++) { // For a duration, we allow 24 hours
7537 $retstring .= '<option value="' . $hour . '"';
7538 if (is_numeric($hourSelected) && $hourSelected == $hour) {
7539 $retstring .= " selected";
7540 }
7541 $retstring .= ">" . $hour . "</option>";
7542 }
7543 $retstring .= "</select>";
7544 } elseif ($typehour == 'text' || $typehour == 'textselect') {
7545 $retstring .= '<input placeholder="' . $langs->trans('HourShort') . '" type="number" min="0" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputhour right" value="' . (($hourSelected != '') ? ((int) $hourSelected) : '') . '">';
7546 } else {
7547 return 'BadValueForParameterTypeHour';
7548 }
7549
7550 if ($typehour != 'text') {
7551 $retstring .= ' ' . $langs->trans('HourShort');
7552 } else {
7553 $retstring .= '<span class="">:</span>';
7554 }
7555
7556 // Minutes
7557 if ($minunderhours) {
7558 $retstring .= '<br>';
7559 } else {
7560 if ($typehour != 'text') {
7561 $retstring .= '<span class="hideonsmartphone">&nbsp;</span>';
7562 }
7563 }
7564
7565 if ($typehour == 'select' || $typehour == 'textselect') {
7566 $retstring .= '<select class="flat" id="select_' . $prefix . 'min" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . '>';
7567 for ($min = 0; $min <= 55; $min += 5) {
7568 $retstring .= '<option value="' . $min . '"';
7569 if (is_numeric($minSelected) && $minSelected == $min) {
7570 $retstring .= ' selected';
7571 }
7572 $retstring .= '>' . $min . '</option>';
7573 }
7574 $retstring .= "</select>";
7575 } elseif ($typehour == 'text') {
7576 $retstring .= '<input placeholder="' . $langs->trans('MinuteShort') . '" type="number" min="0" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputminute right" value="' . (($minSelected != '') ? ((int) $minSelected) : '') . '">';
7577 }
7578
7579 if ($typehour != 'text') {
7580 $retstring .= ' ' . $langs->trans('MinuteShort');
7581 }
7582
7583 $retstring .= "</span>";
7584
7585 if (!empty($nooutput)) {
7586 return $retstring;
7587 }
7588
7589 print $retstring;
7590
7591 return '';
7592 }
7593
7613 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)
7614 {
7615 global $langs, $conf;
7616
7617 $out = '';
7618
7619 // check parameters
7620 if (is_null($ajaxoptions)) {
7621 $ajaxoptions = array();
7622 }
7623
7624 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7625 $placeholder = '';
7626
7627 if ($selected && empty($selected_input_value)) {
7628 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7629 $tickettmpselect = new Ticket($this->db);
7630 $tickettmpselect->fetch($selected);
7631 $selected_input_value = $tickettmpselect->ref;
7632 unset($tickettmpselect);
7633 }
7634
7635 $urloption = '';
7636 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/ticket/ajax/tickets.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7637
7638 if (empty($hidelabel)) {
7639 $out .= $langs->trans("RefOrLabel") . ' : ';
7640 } elseif ($hidelabel > 1) {
7641 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7642 if ($hidelabel == 2) {
7643 $out .= img_picto($langs->trans("Search"), 'search');
7644 }
7645 }
7646 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7647 if ($hidelabel == 3) {
7648 $out .= img_picto($langs->trans("Search"), 'search');
7649 }
7650 } else {
7651 $out .= $this->selectTicketsList($selected, $htmlname, $filtertype, $limit, '', $status, 0, $showempty, $forcecombo, $morecss);
7652 }
7653
7654 if (empty($nooutput)) {
7655 print $out;
7656 } else {
7657 return $out;
7658 }
7659 return '';
7660 }
7661
7662
7679 public function selectTicketsList($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7680 {
7681 global $langs, $conf;
7682
7683 $out = '';
7684 $outarray = array();
7685
7686 $selectFields = " p.rowid, p.ref, p.message";
7687
7688 $sql = "SELECT ";
7689 $sql .= $selectFields;
7690 $sql .= " FROM " . $this->db->prefix() . "ticket as p";
7691 $sql .= ' WHERE p.entity IN (' . getEntity('ticket') . ')';
7692
7693 // Add criteria on ref/label
7694 if ($filterkey != '') {
7695 $sql .= ' AND (';
7696 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7697 // For natural search
7698 $search_crit = explode(' ', $filterkey);
7699 $i = 0;
7700 if (count($search_crit) > 1) {
7701 $sql .= "(";
7702 }
7703 foreach ($search_crit as $crit) {
7704 if ($i > 0) {
7705 $sql .= " AND ";
7706 }
7707 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.subject LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7708 $sql .= ")";
7709 $i++;
7710 }
7711 if (count($search_crit) > 1) {
7712 $sql .= ")";
7713 }
7714 $sql .= ')';
7715 }
7716
7717 $sql .= $this->db->plimit($limit, 0);
7718
7719 // Build output string
7720 dol_syslog(get_class($this) . "::selectTicketsList search tickets", LOG_DEBUG);
7721 $result = $this->db->query($sql);
7722 if ($result) {
7723 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7724 require_once DOL_DOCUMENT_ROOT . '/core/lib/ticket.lib.php';
7725
7726 $num = $this->db->num_rows($result);
7727
7728 $events = array();
7729
7730 if (!$forcecombo) {
7731 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7732 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt('TICKET_USE_SEARCH_TO_SELECT'));
7733 }
7734
7735 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7736
7737 $textifempty = '';
7738 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7739 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7740 if (getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7741 if ($showempty && !is_numeric($showempty)) {
7742 $textifempty = $langs->trans($showempty);
7743 } else {
7744 $textifempty .= $langs->trans("All");
7745 }
7746 } else {
7747 if ($showempty && !is_numeric($showempty)) {
7748 $textifempty = $langs->trans($showempty);
7749 }
7750 }
7751 if ($showempty) {
7752 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7753 }
7754
7755 $i = 0;
7756 while ($num && $i < $num) {
7757 $opt = '';
7758 $optJson = array();
7759 $objp = $this->db->fetch_object($result);
7760
7761 $this->constructTicketListOption($objp, $opt, $optJson, $selected, $filterkey);
7762 // Add new entry
7763 // "key" value of json key array is used by jQuery automatically as selected value
7764 // "label" value of json key array is used by jQuery automatically as text for combo box
7765 $out .= $opt;
7766 array_push($outarray, $optJson);
7767
7768 $i++;
7769 }
7770
7771 $out .= '</select>';
7772
7773 $this->db->free($result);
7774
7775 if (empty($outputmode)) {
7776 return $out;
7777 }
7778 return $outarray;
7779 } else {
7780 dol_print_error($this->db);
7781 }
7782
7783 return array();
7784 }
7785
7797 protected function constructTicketListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7798 {
7799 $outkey = '';
7800 $outref = '';
7801 $outtype = '';
7802
7803 $outkey = $objp->rowid;
7804 $outref = $objp->ref;
7805
7806 $opt = '<option value="' . $objp->rowid . '"';
7807 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7808 $opt .= '>';
7809 $opt .= $objp->ref;
7810 $objRef = $objp->ref;
7811 if (!empty($filterkey) && $filterkey != '') {
7812 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
7813 }
7814
7815 $opt .= "</option>\n";
7816 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
7817 }
7818
7838 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)
7839 {
7840 global $langs, $conf;
7841
7842 $out = '';
7843
7844 // check parameters
7845 if (is_null($ajaxoptions)) {
7846 $ajaxoptions = array();
7847 }
7848
7849 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7850 $placeholder = '';
7851
7852 if ($selected && empty($selected_input_value)) {
7853 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7854 $projecttmpselect = new Project($this->db);
7855 $projecttmpselect->fetch($selected);
7856 $selected_input_value = $projecttmpselect->ref;
7857 unset($projecttmpselect);
7858 }
7859
7860 $urloption = '';
7861 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/projet/ajax/projects.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7862
7863 if (empty($hidelabel)) {
7864 $out .= $langs->trans("RefOrLabel") . ' : ';
7865 } elseif ($hidelabel > 1) {
7866 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7867 if ($hidelabel == 2) {
7868 $out .= img_picto($langs->trans("Search"), 'search');
7869 }
7870 }
7871 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7872 if ($hidelabel == 3) {
7873 $out .= img_picto($langs->trans("Search"), 'search');
7874 }
7875 } else {
7876 $out .= $this->selectProjectsList($selected, $htmlname, $filtertype, $limit, '', $status, 0, $showempty, $forcecombo, $morecss);
7877 }
7878
7879 if (empty($nooutput)) {
7880 print $out;
7881 } else {
7882 return $out;
7883 }
7884 return '';
7885 }
7886
7903 public function selectProjectsList($selected = '', $htmlname = 'projectid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7904 {
7905 global $langs, $conf;
7906
7907 $out = '';
7908 $outarray = array();
7909
7910 $selectFields = " p.rowid, p.ref";
7911
7912 $sql = "SELECT ";
7913 $sql .= $selectFields;
7914 $sql .= " FROM " . $this->db->prefix() . "projet as p";
7915 $sql .= ' WHERE p.entity IN (' . getEntity('project') . ')';
7916
7917 // Add criteria on ref/label
7918 if ($filterkey != '') {
7919 $sql .= ' AND (';
7920 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7921 // For natural search
7922 $search_crit = explode(' ', $filterkey);
7923 $i = 0;
7924 if (count($search_crit) > 1) {
7925 $sql .= "(";
7926 }
7927 foreach ($search_crit as $crit) {
7928 if ($i > 0) {
7929 $sql .= " AND ";
7930 }
7931 $sql .= "p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7932 $sql .= "";
7933 $i++;
7934 }
7935 if (count($search_crit) > 1) {
7936 $sql .= ")";
7937 }
7938 $sql .= ')';
7939 }
7940
7941 $sql .= $this->db->plimit($limit, 0);
7942
7943 // Build output string
7944 dol_syslog(get_class($this) . "::selectProjectsList search projects", LOG_DEBUG);
7945 $result = $this->db->query($sql);
7946 if ($result) {
7947 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7948 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
7949
7950 $num = $this->db->num_rows($result);
7951
7952 $events = array();
7953
7954 if (!$forcecombo) {
7955 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7956 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt('PROJECT_USE_SEARCH_TO_SELECT'));
7957 }
7958
7959 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7960
7961 $textifempty = '';
7962 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7963 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7964 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
7965 if ($showempty && !is_numeric($showempty)) {
7966 $textifempty = $langs->trans($showempty);
7967 } else {
7968 $textifempty .= $langs->trans("All");
7969 }
7970 } else {
7971 if ($showempty && !is_numeric($showempty)) {
7972 $textifempty = $langs->trans($showempty);
7973 }
7974 }
7975 if ($showempty) {
7976 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7977 }
7978
7979 $i = 0;
7980 while ($num && $i < $num) {
7981 $opt = '';
7982 $optJson = array();
7983 $objp = $this->db->fetch_object($result);
7984
7985 $this->constructProjectListOption($objp, $opt, $optJson, $selected, $filterkey);
7986 // Add new entry
7987 // "key" value of json key array is used by jQuery automatically as selected value
7988 // "label" value of json key array is used by jQuery automatically as text for combo box
7989 $out .= $opt;
7990 array_push($outarray, $optJson);
7991
7992 $i++;
7993 }
7994
7995 $out .= '</select>';
7996
7997 $this->db->free($result);
7998
7999 if (empty($outputmode)) {
8000 return $out;
8001 }
8002 return $outarray;
8003 } else {
8004 dol_print_error($this->db);
8005 }
8006
8007 return array();
8008 }
8009
8021 protected function constructProjectListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
8022 {
8023 $outkey = '';
8024 $outref = '';
8025 $outtype = '';
8026
8027 $label = $objp->label;
8028
8029 $outkey = $objp->rowid;
8030 $outref = $objp->ref;
8031 $outlabel = $objp->label;
8032 $outtype = $objp->fk_product_type;
8033
8034 $opt = '<option value="' . $objp->rowid . '"';
8035 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
8036 $opt .= '>';
8037 $opt .= $objp->ref;
8038 $objRef = $objp->ref;
8039 if (!empty($filterkey) && $filterkey != '') {
8040 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
8041 }
8042
8043 $opt .= "</option>\n";
8044 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
8045 }
8046
8047
8067 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)
8068 {
8069 global $langs, $conf;
8070
8071 $out = '';
8072
8073 // check parameters
8074 if (is_null($ajaxoptions)) {
8075 $ajaxoptions = array();
8076 }
8077
8078 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
8079 $placeholder = '';
8080
8081 if ($selected && empty($selected_input_value)) {
8082 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
8083 $adherenttmpselect = new Adherent($this->db);
8084 $adherenttmpselect->fetch($selected);
8085 $selected_input_value = $adherenttmpselect->ref;
8086 unset($adherenttmpselect);
8087 }
8088
8089 $urloption = '';
8090
8091 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/adherents/ajax/adherents.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
8092
8093 if (empty($hidelabel)) {
8094 $out .= $langs->trans("RefOrLabel") . ' : ';
8095 } elseif ($hidelabel > 1) {
8096 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
8097 if ($hidelabel == 2) {
8098 $out .= img_picto($langs->trans("Search"), 'search');
8099 }
8100 }
8101 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
8102 if ($hidelabel == 3) {
8103 $out .= img_picto($langs->trans("Search"), 'search');
8104 }
8105 } else {
8106 $filterkey = '';
8107
8108 $out .= $this->selectMembersList($selected, $htmlname, $filtertype, $limit, $filterkey, $status, 0, $showempty, $forcecombo, $morecss);
8109 }
8110
8111 if (empty($nooutput)) {
8112 print $out;
8113 } else {
8114 return $out;
8115 }
8116 return '';
8117 }
8118
8135 public function selectMembersList($selected = '', $htmlname = 'adherentid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
8136 {
8137 global $langs, $conf;
8138
8139 $out = '';
8140 $outarray = array();
8141
8142 $selectFields = " p.rowid, p.ref, p.firstname, p.lastname, p.fk_adherent_type";
8143
8144 $sql = "SELECT ";
8145 $sql .= $selectFields;
8146 $sql .= " FROM " . $this->db->prefix() . "adherent as p";
8147 $sql .= ' WHERE p.entity IN (' . getEntity('adherent') . ')';
8148
8149 // Add criteria on ref/label
8150 if ($filterkey != '') {
8151 $sql .= ' AND (';
8152 $prefix = !getDolGlobalString('MEMBER_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
8153 // For natural search
8154 $search_crit = explode(' ', $filterkey);
8155 $i = 0;
8156 if (count($search_crit) > 1) {
8157 $sql .= "(";
8158 }
8159 foreach ($search_crit as $crit) {
8160 if ($i > 0) {
8161 $sql .= " AND ";
8162 }
8163 $sql .= "(p.firstname LIKE '" . $this->db->escape($prefix . $crit) . "%'";
8164 $sql .= " OR p.lastname LIKE '" . $this->db->escape($prefix . $crit) . "%')";
8165 $i++;
8166 }
8167 if (count($search_crit) > 1) {
8168 $sql .= ")";
8169 }
8170 $sql .= ')';
8171 }
8172 if ($status != -1) {
8173 $sql .= ' AND statut = ' . ((int) $status);
8174 }
8175 $sql .= $this->db->plimit($limit, 0);
8176
8177 // Build output string
8178 dol_syslog(get_class($this) . "::selectMembersList search adherents", LOG_DEBUG);
8179 $result = $this->db->query($sql);
8180 if ($result) {
8181 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
8182 require_once DOL_DOCUMENT_ROOT . '/core/lib/member.lib.php';
8183
8184 $num = $this->db->num_rows($result);
8185
8186 $events = array();
8187
8188 if (!$forcecombo) {
8189 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8190 $out .= ajax_combobox($htmlname, $events, getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT') ? $conf->global->PROJECT_USE_SEARCH_TO_SELECT : '');
8191 }
8192
8193 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
8194
8195 $textifempty = '';
8196 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
8197 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8198 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
8199 if ($showempty && !is_numeric($showempty)) {
8200 $textifempty = $langs->trans($showempty);
8201 } else {
8202 $textifempty .= $langs->trans("All");
8203 }
8204 } else {
8205 if ($showempty && !is_numeric($showempty)) {
8206 $textifempty = $langs->trans($showempty);
8207 }
8208 }
8209 if ($showempty) {
8210 $out .= '<option value="-1" selected>' . $textifempty . '</option>';
8211 }
8212
8213 $i = 0;
8214 while ($num && $i < $num) {
8215 $opt = '';
8216 $optJson = array();
8217 $objp = $this->db->fetch_object($result);
8218
8219 $this->constructMemberListOption($objp, $opt, $optJson, $selected, $filterkey);
8220
8221 // Add new entry
8222 // "key" value of json key array is used by jQuery automatically as selected value
8223 // "label" value of json key array is used by jQuery automatically as text for combo box
8224 $out .= $opt;
8225 array_push($outarray, $optJson);
8226
8227 $i++;
8228 }
8229
8230 $out .= '</select>';
8231
8232 $this->db->free($result);
8233
8234 if (empty($outputmode)) {
8235 return $out;
8236 }
8237 return $outarray;
8238 } else {
8239 dol_print_error($this->db);
8240 }
8241
8242 return array();
8243 }
8244
8256 protected function constructMemberListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
8257 {
8258 $outkey = '';
8259 $outlabel = '';
8260 $outtype = '';
8261
8262 $outkey = $objp->rowid;
8263 $outlabel = dolGetFirstLastname($objp->firstname, $objp->lastname);
8264 $outtype = $objp->fk_adherent_type;
8265
8266 $opt = '<option value="' . $objp->rowid . '"';
8267 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
8268 $opt .= '>';
8269 if (!empty($filterkey) && $filterkey != '') {
8270 $outlabel = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $outlabel, 1);
8271 }
8272 $opt .= $outlabel;
8273 $opt .= "</option>\n";
8274
8275 $optJson = array('key' => $outkey, 'value' => $outlabel, 'type' => $outtype);
8276 }
8277
8298 public function selectForForms($objectdesc, $htmlname, $preSelectedValue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '', $objectfield = '')
8299 {
8300 global $conf, $extrafields, $user;
8301
8302 // Example of common usage for a link to a thirdparty
8303
8304 // We got this in a modulebuilder form of "MyObject" of module "mymodule".
8305 // ->fields is array( ... "fk_soc" => array("type"=>"integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))" ...)
8306 // $objectdesc = 'Societe'
8307 // $objectfield = 'myobject@mymodule:fk_soc' ('fk_soc' is code to retrieve myobject->fields['fk_soc'])
8308
8309 // We got this when showing an extrafields on resource that is a link to societe
8310 // extrafields 'link_to_societe' of Resource is 'link' to 'Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))" ...)'
8311 // $objectdesc = 'Societe'
8312 // $objectfield = 'resource:options_link_to_societe'
8313
8314 // With old usage:
8315 // $objectdesc = 'Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))'
8316 // $objectfield = ''
8317
8318 //var_dump($objectdesc.' '.$objectfield);
8319 //debug_print_backtrace();
8320
8321 $objectdescorig = $objectdesc;
8322 $objecttmp = null;
8323 $InfoFieldList = array();
8324 $classname = '';
8325 $filter = ''; // Ensure filter has value (for static analysis)
8326 $sortfield = ''; // Ensure filter has value (for static analysis)
8327
8328 if ($objectfield) { // We must retrieve the objectdesc from the field or extrafield
8329 // Example: $objectfield = 'product:options_package' or 'myobject@mymodule:options_myfield'
8330 $tmparray = explode(':', $objectfield);
8331
8332 // Get instance of object from $element
8333 $objectforfieldstmp = fetchObjectByElement(0, strtolower($tmparray[0]));
8334
8335 if (is_object($objectforfieldstmp)) {
8336 $objectdesc = '';
8337
8338 $reg = array();
8339 if (preg_match('/^options_(.*)$/', $tmparray[1], $reg)) {
8340 // For a property in extrafields
8341 $key = $reg[1];
8342 // fetch optionals attributes and labels
8343 $extrafields->fetch_name_optionals_label($objectforfieldstmp->table_element);
8344
8345 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key]) && $extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key] == 'link') {
8346 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options'])) {
8347 $tmpextrafields = array_keys($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options']);
8348 $objectdesc = $tmpextrafields[0];
8349 }
8350 }
8351 } else {
8352 // For a property in ->fields
8353 if (array_key_exists($tmparray[1], $objectforfieldstmp->fields)) {
8354 $objectdesc = $objectforfieldstmp->fields[$tmparray[1]]['type'];
8355 $objectdesc = preg_replace('/^integer[^:]*:/', '', $objectdesc);
8356 }
8357 }
8358 }
8359 }
8360
8361 if ($objectdesc) {
8362 // Example of value for $objectdesc:
8363 // Bom:bom/class/bom.class.php:0:t.status=1
8364 // Bom:bom/class/bom.class.php:0:t.status=1:ref
8365 // Bom:bom/class/bom.class.php:0:(t.status:=:1) OR (t.field2:=:2):ref
8366 $InfoFieldList = explode(":", $objectdesc, 4);
8367 $vartmp = (empty($InfoFieldList[3]) ? '' : $InfoFieldList[3]);
8368 $reg = array();
8369 if (preg_match('/^.*:(\w*)$/', $vartmp, $reg)) {
8370 $InfoFieldList[4] = $reg[1]; // take the sort field
8371 }
8372 $InfoFieldList[3] = preg_replace('/:\w*$/', '', $vartmp); // take the filter field
8373
8374 $classname = $InfoFieldList[0];
8375 $classpath = empty($InfoFieldList[1]) ? '' : $InfoFieldList[1];
8376 //$addcreatebuttonornot = empty($InfoFieldList[2]) ? 0 : $InfoFieldList[2];
8377 $filter = empty($InfoFieldList[3]) ? '' : $InfoFieldList[3];
8378 $sortfield = empty($InfoFieldList[4]) ? '' : $InfoFieldList[4];
8379
8380 // Load object according to $id and $element
8381 $objecttmp = fetchObjectByElement(0, strtolower($InfoFieldList[0]));
8382
8383 // Fallback to another solution to get $objecttmp
8384 if (empty($objecttmp) && !empty($classpath)) {
8385 dol_include_once($classpath);
8386
8387 if ($classname && class_exists($classname)) {
8388 $objecttmp = new $classname($this->db);
8389 }
8390 }
8391 }
8392
8393 // Make some replacement in $filter. May not be used if we used the ajax mode with $objectfield. In such a case
8394 // we propagate the $objectfield and not the filter and replacement is done by the ajax/selectobject.php component.
8395 $sharedentities = (is_object($objecttmp) && property_exists($objecttmp, 'element')) ? getEntity($objecttmp->element) : strtolower($classname);
8396 $filter = str_replace(
8397 array('__ENTITY__', '__SHARED_ENTITIES__', '__USER_ID__'),
8398 array($conf->entity, $sharedentities, $user->id),
8399 $filter
8400 );
8401
8402 if (!is_object($objecttmp)) {
8403 dol_syslog('selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc, LOG_WARNING);
8404 return 'selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc;
8405 }
8406 '@phan-var-force CommonObject $objecttmp';
8407
8408 //var_dump($filter);
8409 $prefixforautocompletemode = $objecttmp->element;
8410 if ($prefixforautocompletemode == 'societe') {
8411 $prefixforautocompletemode = 'company';
8412 }
8413 if ($prefixforautocompletemode == 'product') {
8414 $prefixforautocompletemode = 'produit';
8415 }
8416 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8417
8418 dol_syslog(get_class($this) . "::selectForForms filter=" . $filter, LOG_DEBUG);
8419
8420 // Generate the combo HTML component
8421 $out = '';
8422 if (!empty($conf->use_javascript_ajax) && getDolGlobalString($confkeyforautocompletemode) && !$forcecombo) {
8423 // No immediate load of all database
8424 $placeholder = '';
8425
8426 if ($preSelectedValue && empty($selected_input_value)) {
8427 $objecttmp->fetch($preSelectedValue);
8428 $selected_input_value = ($prefixforautocompletemode == 'company' ? $objecttmp->name : $objecttmp->ref);
8429
8430 $oldValueForShowOnCombobox = 0;
8431 foreach ($objecttmp->fields as $fieldK => $fielV) {
8432 if (!array_key_exists('showoncombobox', $fielV) || !$fielV['showoncombobox'] || empty($objecttmp->$fieldK)) {
8433 continue;
8434 }
8435
8436 if (!$oldValueForShowOnCombobox) {
8437 $selected_input_value = '';
8438 }
8439
8440 $selected_input_value .= $oldValueForShowOnCombobox ? ' - ' : '';
8441 $selected_input_value .= $objecttmp->$fieldK;
8442 $oldValueForShowOnCombobox = empty($fielV['showoncombobox']) ? 0 : $fielV['showoncombobox'];
8443 }
8444 }
8445
8446 // Set url and param to call to get json of the search results
8447 $urlforajaxcall = DOL_URL_ROOT . '/core/ajax/selectobject.php';
8448 $urloption = 'htmlname=' . urlencode($htmlname) . '&outjson=1&objectdesc=' . urlencode($objectdescorig) . '&objectfield='.urlencode($objectfield) . ($sortfield ? '&sortfield=' . urlencode($sortfield) : '');
8449
8450 // Activate the auto complete using ajax call.
8451 $out .= ajax_autocompleter((string) $preSelectedValue, $htmlname, $urlforajaxcall, $urloption, getDolGlobalInt($confkeyforautocompletemode), 0);
8452 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
8453 $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) . '"' : '') . ' />';
8454 } else {
8455 // Immediate load of table record.
8456 $out .= $this->selectForFormsList($objecttmp, $htmlname, $preSelectedValue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, 0, $disabled, $sortfield, $filter);
8457 }
8458
8459 return $out;
8460 }
8461
8462
8483 public function selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $outputmode = 0, $disabled = 0, $sortfield = '', $filter = '')
8484 {
8485 global $langs, $user, $hookmanager;
8486
8487 //print "$htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, $outputmode, $disabled";
8488
8489 $prefixforautocompletemode = $objecttmp->element;
8490 if ($prefixforautocompletemode == 'societe') {
8491 $prefixforautocompletemode = 'company';
8492 }
8493 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8494
8495 if (!empty($objecttmp->fields)) { // For object that declare it, it is better to use declared fields (like societe, contact, ...)
8496 $tmpfieldstoshow = '';
8497 foreach ($objecttmp->fields as $key => $val) {
8498 if (! (int) dol_eval($val['enabled'], 1, 1, '1')) {
8499 continue;
8500 }
8501 if (!empty($val['showoncombobox'])) {
8502 $tmpfieldstoshow .= ($tmpfieldstoshow ? ',' : '') . 't.' . $key;
8503 }
8504 }
8505 if ($tmpfieldstoshow) {
8506 $fieldstoshow = $tmpfieldstoshow;
8507 }
8508 } else {
8509 // For backward compatibility
8510 $objecttmp->fields['ref'] = array('type' => 'varchar(30)', 'label' => 'Ref', 'showoncombobox' => 1);
8511 }
8512
8513 if (empty($fieldstoshow)) {
8514 if (isset($objecttmp->fields['ref'])) {
8515 $fieldstoshow = 't.ref';
8516 } else {
8517 $langs->load("errors");
8518 $this->error = $langs->trans("ErrorNoFieldWithAttributeShowoncombobox");
8519 return $langs->trans('ErrorNoFieldWithAttributeShowoncombobox');
8520 }
8521 }
8522
8523 $out = '';
8524 $outarray = array();
8525 $tmparray = array();
8526
8527 $num = 0;
8528
8529 // Search data
8530 $sql = "SELECT t.rowid, " . $fieldstoshow . " FROM " . $this->db->prefix() . $objecttmp->table_element . " as t";
8531 if (!empty($objecttmp->isextrafieldmanaged)) {
8532 $sql .= " LEFT JOIN " . $this->db->prefix() . $objecttmp->table_element . "_extrafields as e ON t.rowid=e.fk_object";
8533 }
8534 if (isset($objecttmp->ismultientitymanaged)) {
8535 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8536 $tmparray = explode('@', $objecttmp->ismultientitymanaged);
8537 $sql .= " INNER JOIN " . $this->db->prefix() . $tmparray[1] . " as parenttable ON parenttable.rowid = t." . $tmparray[0];
8538 }
8539 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8540 if (!$user->hasRight('societe', 'client', 'voir')) {
8541 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
8542 }
8543 }
8544 }
8545
8546 // Add where from hooks
8547 $parameters = array(
8548 'object' => $objecttmp,
8549 'htmlname' => $htmlname,
8550 'filter' => $filter,
8551 'searchkey' => $searchkey
8552 );
8553
8554 $reshook = $hookmanager->executeHooks('selectForFormsListWhere', $parameters); // Note that $action and $object may have been modified by hook
8555 if (!empty($hookmanager->resPrint)) {
8556 $sql .= $hookmanager->resPrint;
8557 } else {
8558 $sql .= " WHERE 1=1";
8559 if (isset($objecttmp->ismultientitymanaged)) {
8560 if ($objecttmp->ismultientitymanaged == 1) {
8561 $sql .= " AND t.entity IN (" . getEntity($objecttmp->table_element) . ")";
8562 }
8563 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8564 $sql .= " AND parenttable.entity = t." . $tmparray[0];
8565 }
8566 if ($objecttmp->ismultientitymanaged == 1 && !empty($user->socid)) {
8567 if ($objecttmp->element == 'societe') {
8568 $sql .= " AND t.rowid = " . ((int) $user->socid);
8569 } else {
8570 $sql .= " AND t.fk_soc = " . ((int) $user->socid);
8571 }
8572 }
8573 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8574 if (!$user->hasRight('societe', 'client', 'voir')) {
8575 $sql .= " AND t.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
8576 }
8577 }
8578 }
8579 if ($searchkey != '') {
8580 $sql .= natural_search(explode(',', $fieldstoshow), $searchkey);
8581 }
8582
8583 if ($filter) { // Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
8584 $errormessage = '';
8585 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
8586 if ($errormessage) {
8587 return 'Error forging a SQL request from an universal criteria: ' . $errormessage;
8588 }
8589 }
8590 }
8591 $sql .= $this->db->order($sortfield ? $sortfield : $fieldstoshow, "ASC");
8592 //$sql.=$this->db->plimit($limit, 0);
8593 //print $sql;
8594
8595 // Build output string
8596 $resql = $this->db->query($sql);
8597 if ($resql) {
8598 // Construct $out and $outarray
8599 $out .= '<select id="' . $htmlname . '" class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ($moreparams ? ' ' . $moreparams : '') . ' name="' . $htmlname . '">' . "\n";
8600
8601 // 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
8602 $textifempty = '&nbsp;';
8603
8604 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8605 if (getDolGlobalInt($confkeyforautocompletemode)) {
8606 if ($showempty && !is_numeric($showempty)) {
8607 $textifempty = $langs->trans($showempty);
8608 } else {
8609 $textifempty .= $langs->trans("All");
8610 }
8611 }
8612 if ($showempty) {
8613 $out .= '<option value="-1">' . $textifempty . '</option>' . "\n";
8614 }
8615
8616 $num = $this->db->num_rows($resql);
8617 $i = 0;
8618 if ($num) {
8619 while ($i < $num) {
8620 $obj = $this->db->fetch_object($resql);
8621 $label = '';
8622 $labelhtml = '';
8623 $tmparray = explode(',', $fieldstoshow);
8624 $oldvalueforshowoncombobox = 0;
8625 foreach ($tmparray as $key => $val) {
8626 $val = preg_replace('/t\./', '', $val);
8627 $label .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8628 $labelhtml .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8629 $label .= $obj->$val;
8630 $labelhtml .= $obj->$val;
8631
8632 $oldvalueforshowoncombobox = empty($objecttmp->fields[$val]['showoncombobox']) ? 0 : $objecttmp->fields[$val]['showoncombobox'];
8633 }
8634 if (empty($outputmode)) {
8635 if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid) {
8636 $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>';
8637 } else {
8638 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
8639 }
8640 } else {
8641 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label));
8642 }
8643
8644 $i++;
8645 if (($i % 10) == 0) {
8646 $out .= "\n";
8647 }
8648 }
8649 }
8650
8651 $out .= '</select>' . "\n";
8652
8653 if (!$forcecombo) {
8654 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8655 $out .= ajax_combobox($htmlname, array(), getDolGlobalInt($confkeyforautocompletemode, 0));
8656 }
8657 } else {
8658 dol_print_error($this->db);
8659 }
8660
8661 $this->result = array('nbofelement' => $num);
8662
8663 if ($outputmode) {
8664 return $outarray;
8665 }
8666 return $out;
8667 }
8668
8669
8693 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)
8694 {
8695 global $conf, $langs;
8696
8697 // Do we want a multiselect ?
8698 //$jsbeautify = 0;
8699 //if (preg_match('/^multi/',$htmlname)) $jsbeautify = 1;
8700 $jsbeautify = 1;
8701
8702 if ($value_as_key) {
8703 $array = array_combine($array, $array);
8704 }
8705
8706 '@phan-var-force array{label:string,data-html:string,disable?:int<0,1>,css?:string} $array'; // Array combine breaks information
8707
8708 $out = '';
8709
8710 if ($addjscombo < 0) {
8711 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8712 $addjscombo = 1;
8713 } else {
8714 $addjscombo = 0;
8715 }
8716 }
8717 $idname = str_replace(array('[', ']'), array('', ''), $htmlname);
8718 $out .= '<select id="' . preg_replace('/^\./', '', $idname) . '" ' . ($disabled ? 'disabled="disabled" ' : '') . 'class="flat ' . (preg_replace('/^\./', '', $htmlname)) . ($morecss ? ' ' . $morecss : '') . ' selectformat"';
8719 $out .= ' name="' . preg_replace('/^\./', '', $htmlname) . '" ' . ($moreparam ? $moreparam : '');
8720 $out .= '>'."\n";
8721
8722 if ($show_empty) {
8723 $textforempty = ' ';
8724 if (!empty($conf->use_javascript_ajax)) {
8725 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
8726 }
8727 if (!is_numeric($show_empty)) {
8728 $textforempty = $show_empty;
8729 }
8730 $out .= '<option class="optiongrey" ' . ($moreparamonempty ? $moreparamonempty . ' ' : '') . 'value="' . (((int) $show_empty) < 0 ? $show_empty : -1) . '"' . ($id == $show_empty ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
8731 }
8732 if (is_array($array)) {
8733 // Translate
8734 if ($translate) {
8735 foreach ($array as $key => $value) {
8736 if (!is_array($value)) {
8737 $array[$key] = $langs->trans($value);
8738 } else {
8739 $array[$key]['label'] = $langs->trans($value['label']);
8740 }
8741 }
8742 }
8743 // Sort
8744 if ($sort == 'ASC') {
8745 asort($array);
8746 } elseif ($sort == 'DESC') {
8747 arsort($array);
8748 }
8749
8750 foreach ($array as $key => $tmpvalue) {
8751 if (is_array($tmpvalue)) {
8752 $value = $tmpvalue['label'];
8753 //$valuehtml = empty($tmpvalue['data-html']) ? $value : $tmpvalue['data-html'];
8754 $disabled = empty($tmpvalue['disabled']) ? '' : ' disabled';
8755 $style = empty($tmpvalue['css']) ? '' : ' class="' . $tmpvalue['css'] . '"';
8756 } else {
8757 $value = $tmpvalue;
8758 //$valuehtml = $tmpvalue;
8759 $disabled = '';
8760 $style = '';
8761 }
8762 if (!empty($disablebademail)) {
8763 if (($disablebademail == 1 && !preg_match('/&lt;.+@.+&gt;/', $value))
8764 || ($disablebademail == 2 && preg_match('/---/', $value))) {
8765 $disabled = ' disabled';
8766 $style = ' class="warning"';
8767 }
8768 }
8769 if ($key_in_label) {
8770 if (empty($nohtmlescape)) {
8771 $selectOptionValue = dol_escape_htmltag($key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value));
8772 } else {
8773 $selectOptionValue = $key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value);
8774 }
8775 } else {
8776 if (empty($nohtmlescape)) {
8777 $selectOptionValue = dol_escape_htmltag($maxlen ? dol_trunc($value, $maxlen) : $value);
8778 } else {
8779 $selectOptionValue = $maxlen ? dol_trunc($value, $maxlen) : $value;
8780 }
8781 if ($value == '' || $value == '-') {
8782 $selectOptionValue = '&nbsp;';
8783 }
8784 }
8785 $out .= '<option value="' . $key . '"';
8786 $out .= $style . $disabled;
8787 if (is_array($id)) {
8788 if (in_array($key, $id) && !$disabled) {
8789 $out .= ' selected'; // To preselect a value
8790 }
8791 } else {
8792 $id = (string) $id; // if $id = 0, then $id = '0'
8793 if ($id != '' && (($id == (string) $key) || ($id == 'ifone' && count($array) == 1)) && !$disabled) {
8794 $out .= ' selected'; // To preselect a value
8795 }
8796 }
8797 if (!empty($nohtmlescape)) { // deprecated. Use instead the key 'data-html' into input $array, managed at next step to use HTML content.
8798 $out .= ' data-html="' . dol_escape_htmltag($selectOptionValue) . '"';
8799 }
8800
8801 if (is_array($tmpvalue)) {
8802 foreach ($tmpvalue as $keyforvalue => $valueforvalue) {
8803 if ($keyforvalue == 'labelhtml') {
8804 $keyforvalue = 'data-html';
8805 }
8806 if (preg_match('/^data-/', $keyforvalue)) { // The best solution if you want to use HTML values into the list is to use data-html.
8807 $out .= ' '.dol_escape_htmltag($keyforvalue).'="'.dol_escape_htmltag($valueforvalue).'"';
8808 }
8809 }
8810 }
8811 $out .= '>';
8812 $out .= $selectOptionValue;
8813 $out .= "</option>\n";
8814 }
8815 }
8816 $out .= "</select>";
8817
8818 // Add code for jquery to use multiselect
8819 if ($addjscombo && $jsbeautify) {
8820 // Enhance with select2
8821 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8822 $out .= ajax_combobox($idname, array(), 0, 0, 'resolve', (((int) $show_empty) < 0 ? (string) $show_empty : '-1'), $morecss);
8823 }
8824
8825 return $out;
8826 }
8827
8846 public static function selectArrayAjax($htmlname, $url, $id = '', $moreparam = '', $moreparamtourl = '', $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0)
8847 {
8848 global $conf, $langs;
8849 global $delayedhtmlcontent; // Will be used later outside of this function
8850
8851 // TODO Use an internal dolibarr component instead of select2
8852 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8853 return '';
8854 }
8855
8856 $out = '<select type="text" class="' . $htmlname . ($morecss ? ' ' . $morecss : '') . '" ' . ($moreparam ? $moreparam . ' ' : '') . 'name="' . $htmlname . '"></select>';
8857
8858 $outdelayed = '';
8859 if (!empty($conf->use_javascript_ajax)) {
8860 $tmpplugin = 'select2';
8861 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8862 <script nonce="' . getNonce() . '">
8863 $(document).ready(function () {
8864
8865 ' . ($callurlonselect ? 'var saveRemoteData = [];' : '') . '
8866
8867 $(".' . $htmlname . '").select2({
8868 ajax: {
8869 dir: "ltr",
8870 url: "' . $url . '",
8871 dataType: \'json\',
8872 delay: 250,
8873 data: function (params) {
8874 return {
8875 q: params.term, // search term
8876 page: params.page
8877 }
8878 },
8879 processResults: function (data) {
8880 // parse the results into the format expected by Select2.
8881 // since we are using custom formatting functions we do not need to alter the remote JSON data
8882 //console.log(data);
8883 saveRemoteData = data;
8884 /* format json result for select2 */
8885 result = []
8886 $.each( data, function( key, value ) {
8887 result.push({id: key, text: value.text});
8888 });
8889 //return {results:[{id:\'none\', text:\'aa\'}, {id:\'rrr\', text:\'Red\'},{id:\'bbb\', text:\'Search a into projects\'}], more:false}
8890 //console.log(result);
8891 return {results: result, more: false}
8892 },
8893 cache: true
8894 },
8895 language: select2arrayoflanguage,
8896 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8897 placeholder: "' . dol_escape_js($placeholder) . '",
8898 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8899 minimumInputLength: ' . ((int) $minimumInputLength) . ',
8900 formatResult: function (result, container, query, escapeMarkup) {
8901 return escapeMarkup(result.text);
8902 },
8903 });
8904
8905 ' . ($callurlonselect ? '
8906 /* Code to execute a GET when we select a value */
8907 $(".' . $htmlname . '").change(function() {
8908 var selected = $(".' . $htmlname . '").val();
8909 console.log("We select in selectArrayAjax the entry "+selected)
8910 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8911 $.each( saveRemoteData, function( key, value ) {
8912 if (key == selected)
8913 {
8914 console.log("selectArrayAjax - Do a redirect to "+value.url)
8915 location.assign(value.url);
8916 }
8917 });
8918 });' : '') . '
8919
8920 });
8921 </script>';
8922 }
8923
8924 if ($acceptdelayedhtml) {
8925 $delayedhtmlcontent .= $outdelayed;
8926 } else {
8927 $out .= $outdelayed;
8928 }
8929 return $out;
8930 }
8931
8951 public static function selectArrayFilter($htmlname, $array, $id = '', $moreparam = '', $disableFiltering = 0, $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0, $textfortitle = '')
8952 {
8953 global $conf, $langs;
8954 global $delayedhtmlcontent; // Will be used later outside of this function
8955
8956 // TODO Use an internal dolibarr component instead of select2
8957 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8958 return '';
8959 }
8960
8961 $out = '<select type="text"'.($textfortitle ? ' title="'.dol_escape_htmltag($textfortitle).'"' : '').' id="'.$htmlname.'" class="'.$htmlname.($morecss ? ' ' . $morecss : '').'"'.($moreparam ? ' '.$moreparam : '').' name="'.$htmlname.'"><option></option></select>';
8962
8963 $formattedarrayresult = array();
8964
8965 foreach ($array as $key => $value) {
8966 $o = new stdClass();
8967 $o->id = $key;
8968 $o->text = $value['text'];
8969 $o->url = $value['url'];
8970 $formattedarrayresult[] = $o;
8971 }
8972
8973 $outdelayed = '';
8974 if (!empty($conf->use_javascript_ajax)) {
8975 $tmpplugin = 'select2';
8976 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8977 <script nonce="' . getNonce() . '">
8978 $(document).ready(function () {
8979 var data = ' . json_encode($formattedarrayresult) . ';
8980
8981 ' . ($callurlonselect ? 'var saveRemoteData = ' . json_encode($array) . ';' : '') . '
8982
8983 $(".' . $htmlname . '").select2({
8984 data: data,
8985 language: select2arrayoflanguage,
8986 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8987 placeholder: "' . dol_escape_js($placeholder) . '",
8988 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8989 minimumInputLength: ' . $minimumInputLength . ',
8990 formatResult: function (result, container, query, escapeMarkup) {
8991 return escapeMarkup(result.text);
8992 },
8993 matcher: function (params, data) {
8994
8995 if(! data.id) return null;';
8996
8997 if ($callurlonselect) {
8998 // We forge the url with 'sall='
8999 $outdelayed .= '
9000
9001 var urlBase = data.url;
9002 var separ = urlBase.indexOf("?") >= 0 ? "&" : "?";
9003 /* console.log("params.term="+params.term); */
9004 /* console.log("params.term encoded="+encodeURIComponent(params.term)); */
9005 saveRemoteData[data.id].url = urlBase + separ + "search_all=" + encodeURIComponent(params.term.replace(/\"/g, ""));';
9006 }
9007
9008 if (!$disableFiltering) {
9009 $outdelayed .= '
9010
9011 if(data.text.match(new RegExp(params.term))) {
9012 return data;
9013 }
9014
9015 return null;';
9016 } else {
9017 $outdelayed .= '
9018
9019 return data;';
9020 }
9021
9022 $outdelayed .= '
9023 }
9024 });
9025
9026 ' . ($callurlonselect ? '
9027 /* Code to execute a GET when we select a value */
9028 $(".' . $htmlname . '").change(function() {
9029 var selected = $(".' . $htmlname . '").val();
9030 console.log("We select "+selected)
9031
9032 $(".' . $htmlname . '").val(""); /* reset visible combo value */
9033 $.each( saveRemoteData, function( key, value ) {
9034 if (key == selected)
9035 {
9036 console.log("selectArrayFilter - Do a redirect to "+value.url)
9037 location.assign(value.url);
9038 }
9039 });
9040 });' : '') . '
9041
9042 });
9043 </script>';
9044 }
9045
9046 if ($acceptdelayedhtml) {
9047 $delayedhtmlcontent .= $outdelayed;
9048 } else {
9049 $out .= $outdelayed;
9050 }
9051 return $out;
9052 }
9053
9072 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)
9073 {
9074 global $conf, $langs;
9075
9076 $out = '';
9077
9078 if ($addjscombo < 0) {
9079 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
9080 $addjscombo = 1;
9081 } else {
9082 $addjscombo = 0;
9083 }
9084 }
9085
9086 $useenhancedmultiselect = 0;
9087 if (!empty($conf->use_javascript_ajax) && !defined('MAIN_DO_NOT_USE_JQUERY_MULTISELECT') && (getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT'))) {
9088 if ($addjscombo) {
9089 $useenhancedmultiselect = 1; // Use the js multiselect in one line. Possible only if $addjscombo not 0.
9090 }
9091 }
9092
9093 // We need a hidden field because when using the multiselect, if we unselect all, there is no
9094 // variable submitted at all, so no way to make a difference between variable not submitted and variable
9095 // submitted to nothing.
9096 $out .= '<input type="hidden" name="'.$htmlname.'_multiselect" value="1">';
9097 // Output select component
9098 $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";
9099 if (is_array($array) && !empty($array)) {
9100 if ($value_as_key) {
9101 $array = array_combine($array, $array);
9102 }
9103
9104 if (!empty($array)) {
9105 foreach ($array as $key => $value) {
9106 $tmpkey = $key;
9107 $tmpvalue = $value;
9108 $tmpcolor = '';
9109 $tmppicto = '';
9110 $tmplabelhtml = '';
9111 if (is_array($value) && array_key_exists('id', $value) && array_key_exists('label', $value)) {
9112 $tmpkey = $value['id'];
9113 $tmpvalue = empty($value['label']) ? '' : $value['label'];
9114 $tmpcolor = empty($value['color']) ? '' : $value['color'];
9115 $tmppicto = empty($value['picto']) ? '' : $value['picto'];
9116 $tmplabelhtml = empty($value['labelhtml']) ? (empty($value['data-html']) ? '' : $value['data-html']) : $value['labelhtml'];
9117 }
9118 $newval = ($translate ? $langs->trans($tmpvalue) : $tmpvalue);
9119 $newval = ($key_in_label ? $tmpkey . ' - ' . $newval : $newval);
9120
9121 $out .= '<option value="' . $tmpkey . '"';
9122 if (is_array($selected) && !empty($selected) && in_array((string) $tmpkey, $selected) && ((string) $tmpkey != '')) {
9123 $out .= ' selected';
9124 }
9125 if (!empty($tmplabelhtml)) {
9126 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
9127 } else {
9128 $tmplabelhtml = ($tmppicto ? img_picto('', $tmppicto, 'class="pictofixedwidth" style="color: #' . $tmpcolor . '"') : '') . $newval;
9129 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
9130 }
9131 $out .= '>';
9132 $out .= dol_htmlentitiesbr($newval);
9133 $out .= '</option>' . "\n";
9134 }
9135 }
9136 }
9137 $out .= '</select>' . "\n";
9138
9139 // Add code for jquery to use multiselect
9140 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT')) {
9141 $out .= "\n" . '<!-- JS CODE TO ENABLE select for id ' . $htmlname . ', addjscombo=' . $addjscombo . ' -->';
9142 $out .= "\n" . '<script nonce="' . getNonce() . '">' . "\n";
9143 if ($addjscombo == 1) {
9144 $tmpplugin = !getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT;
9145 $out .= 'function formatResult(record, container) {' . "\n";
9146 // If property data-html set, we decode html entities and use this.
9147 // Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, '', 0, 1) when building the select option.
9148 $out .= ' if ($(record.element).attr("data-html") != undefined && typeof htmlEntityDecodeJs === "function") {';
9149 //$out .= ' console.log("aaa");';
9150 $out .= ' return htmlEntityDecodeJs($(record.element).attr("data-html"));';
9151 $out .= ' }'."\n";
9152 $out .= ' return record.text;';
9153 $out .= '}' . "\n";
9154 $out .= 'function formatSelection(record) {' . "\n";
9155 if ($elemtype == 'category') {
9156 $out .= 'return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';';
9157 } else {
9158 $out .= 'return record.text;';
9159 }
9160 $out .= '}' . "\n";
9161 $out .= '$(document).ready(function () {
9162 $(\'#' . $htmlname . '\').' . $tmpplugin . '({';
9163 if ($placeholder) {
9164 $out .= '
9165 placeholder: {
9166 id: \'-1\',
9167 text: \'' . dol_escape_js($placeholder) . '\'
9168 },';
9169 }
9170 $out .= ' dir: \'ltr\',
9171 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag (ko with multiselect) */
9172 dropdownCssClass: \'' . $morecss . '\', /* Line to add class on the new <span class="select2-selection...> tag (ok with multiselect). Need full version of select2. */
9173 // Specify format function for dropdown item
9174 formatResult: formatResult,
9175 templateResult: formatResult, /* For 4.0 */
9176 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
9177 // Specify format function for selected item
9178 formatSelection: formatSelection,
9179 templateSelection: formatSelection /* For 4.0 */
9180 });
9181
9182 /* Add also morecss to the css .select2 that is after the #htmlname, for component that are show dynamically after load, because select2 set
9183 the size only if component is not hidden by default on load */
9184 $(\'#' . $htmlname . ' + .select2\').addClass(\'' . $morecss . '\');
9185 });' . "\n";
9186 } elseif ($addjscombo == 2 && !defined('DISABLE_MULTISELECT')) {
9187 // Add other js lib
9188 // TODO external lib multiselect/jquery.multi-select.js must have been loaded to use this multiselect plugin
9189 // ...
9190 $out .= 'console.log(\'addjscombo=2 for htmlname=' . $htmlname . '\');';
9191 $out .= '$(document).ready(function () {
9192 $(\'#' . $htmlname . '\').multiSelect({
9193 containerHTML: \'<div class="multi-select-container">\',
9194 menuHTML: \'<div class="multi-select-menu">\',
9195 buttonHTML: \'<span class="multi-select-button ' . $morecss . '">\',
9196 menuItemHTML: \'<label class="multi-select-menuitem">\',
9197 activeClass: \'multi-select-container--open\',
9198 noneText: \'' . $placeholder . '\'
9199 });
9200 })';
9201 }
9202 $out .= '</script>';
9203 }
9204
9205 return $out;
9206 }
9207
9208
9220 public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage, $pos = '')
9221 {
9222 global $langs, $user;
9223
9224 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
9225 return '';
9226 }
9227 if (empty($array)) {
9228 return '';
9229 }
9230
9231 $tmpvar = "MAIN_SELECTEDFIELDS_" . $varpage; // To get list of saved selected fields to show
9232
9233 if (!empty($user->conf->$tmpvar)) { // A list of fields was already customized for user
9234 $tmparray = explode(',', $user->conf->$tmpvar);
9235 foreach ($array as $key => $val) {
9236 //var_dump($key);
9237 //var_dump($tmparray);
9238 if (in_array($key, $tmparray)) {
9239 $array[$key]['checked'] = 1;
9240 } else {
9241 $array[$key]['checked'] = 0;
9242 }
9243 }
9244 } else { // There is no list of fields already customized for user
9245 foreach ($array as $key => $val) {
9246 if (!empty($array[$key]['checked']) && $array[$key]['checked'] < 0) {
9247 $array[$key]['checked'] = 0;
9248 }
9249 }
9250 }
9251
9252 $listoffieldsforselection = '';
9253 $listcheckedstring = '';
9254
9255 foreach ($array as $key => $val) {
9256 // var_dump($val);
9257 // var_dump(array_key_exists('enabled', $val));
9258 // var_dump(!$val['enabled']);
9259 if (array_key_exists('enabled', $val) && isset($val['enabled']) && !$val['enabled']) {
9260 unset($array[$key]); // We don't want this field
9261 continue;
9262 }
9263 if (!empty($val['type']) && $val['type'] == 'separate') {
9264 // Field remains in array but we don't add it into $listoffieldsforselection
9265 //$listoffieldsforselection .= '<li>-----</li>';
9266 continue;
9267 }
9268 if (!empty($val['label']) && $val['label']) {
9269 if (!empty($val['langfile']) && is_object($langs)) {
9270 $langs->load($val['langfile']);
9271 }
9272
9273 // Note: $val['checked'] <> 0 means we must show the field into the combo list @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset
9274 $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>';
9275 $listcheckedstring .= (empty($val['checked']) ? '' : $key . ',');
9276 }
9277 }
9278
9279 $out = '<!-- Component multiSelectArrayWithCheckbox ' . $htmlname . ' -->
9280
9281 <dl class="dropdown">
9282 <dt>
9283 <a href="#' . $htmlname . '">
9284 ' . img_picto('', 'list') . '
9285 </a>
9286 <input type="hidden" class="' . $htmlname . '" name="' . $htmlname . '" value="' . $listcheckedstring . '">
9287 </dt>
9288 <dd class="dropdowndd">
9289 <div class="multiselectcheckbox'.$htmlname.'">
9290 <ul class="'.$htmlname.($pos == '1' ? 'left' : '').'">
9291 <li><input class="inputsearch_dropdownselectedfields width90p minwidth200imp" style="width:90%;" type="text" placeholder="'.$langs->trans('Search').'"></li>
9292 '.$listoffieldsforselection.'
9293 </ul>
9294 </div>
9295 </dd>
9296 </dl>
9297
9298 <script nonce="' . getNonce() . '" type="text/javascript">
9299 jQuery(document).ready(function () {
9300 $(\'.multiselectcheckbox' . $htmlname . ' input[type="checkbox"]\').on(\'click\', function () {
9301 console.log("A new field was added/removed, we edit field input[name=formfilteraction]");
9302
9303 $("input:hidden[name=formfilteraction]").val(\'listafterchangingselectedfields\'); // Update field so we know we changed something on selected fields after POST
9304
9305 var title = $(this).val() + ",";
9306 if ($(this).is(\':checked\')) {
9307 $(\'.' . $htmlname . '\').val(title + $(\'.' . $htmlname . '\').val());
9308 }
9309 else {
9310 $(\'.' . $htmlname . '\').val( $(\'.' . $htmlname . '\').val().replace(title, \'\') )
9311 }
9312 // Now, we submit page
9313 //$(this).parents(\'form:first\').submit();
9314 });
9315 $("input.inputsearch_dropdownselectedfields").on("keyup", function() {
9316 var value = $(this).val().toLowerCase();
9317 $(\'.multiselectcheckbox'.$htmlname.' li > label\').filter(function() {
9318 $(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
9319 });
9320 });
9321
9322
9323 });
9324 </script>
9325
9326 ';
9327 return $out;
9328 }
9329
9339 public function showCategories($id, $type, $rendermode = 0, $nolink = 0)
9340 {
9341 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
9342
9343 $cat = new Categorie($this->db);
9344 $categories = $cat->containing($id, $type);
9345
9346 if ($rendermode == 1) {
9347 $toprint = array();
9348 foreach ($categories as $c) {
9349 $ways = $c->print_all_ways(' &gt;&gt; ', ($nolink ? 'none' : ''), 0, 1); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
9350 foreach ($ways as $way) {
9351 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . $way . '</li>';
9352 }
9353 }
9354 if (empty($toprint)) {
9355 return '';
9356 } else {
9357 return '<div class="select2-container-multi-dolibarr"><ul class="select2-choices-dolibarr">' . implode(' ', $toprint) . '</ul></div>';
9358 }
9359 }
9360
9361 if ($rendermode == 0) {
9362 $arrayselected = array();
9363 $cate_arbo = $this->select_all_categories($type, '', 'parent', 64, 0, 3);
9364 foreach ($categories as $c) {
9365 $arrayselected[] = $c->id;
9366 }
9367
9368 return $this->multiselectarray('categories', $cate_arbo, $arrayselected, 0, 0, '', 0, '100%', 'disabled', 'category');
9369 }
9370
9371 return 'ErrorBadValueForParameterRenderMode'; // Should not happened
9372 }
9373
9383 public function showLinkedObjectBlock($object, $morehtmlright = '', $compatibleImportElementsList = array(), $title = 'RelatedObjects')
9384 {
9385 global $conf, $langs, $hookmanager;
9386 global $action;
9387
9388 $object->fetchObjectLinked();
9389
9390 // Bypass the default method
9391 $hookmanager->initHooks(array('commonobject'));
9392 $parameters = array(
9393 'morehtmlright' => $morehtmlright,
9394 'compatibleImportElementsList' => &$compatibleImportElementsList,
9395 );
9396 $reshook = $hookmanager->executeHooks('showLinkedObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9397
9398 $nbofdifferenttypes = count($object->linkedObjects);
9399
9400 if (empty($reshook)) {
9401 print '<!-- showLinkedObjectBlock -->';
9402 print load_fiche_titre($langs->trans($title), $morehtmlright, '', 0, '', 'showlinkedobjectblock');
9403
9404
9405 print '<div class="div-table-responsive-no-min">';
9406 print '<table class="noborder allwidth" data-block="showLinkedObject" data-element="' . $object->element . '" data-elementid="' . $object->id . '" >';
9407
9408 print '<tr class="liste_titre">';
9409 print '<td>' . $langs->trans("Type") . '</td>';
9410 print '<td>' . $langs->trans("Ref") . '</td>';
9411 print '<td class="center"></td>';
9412 print '<td class="center">' . $langs->trans("Date") . '</td>';
9413 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9414 print '<td class="right">' . $langs->trans("Status") . '</td>';
9415 print '<td></td>';
9416 print '</tr>';
9417
9418 $nboftypesoutput = 0;
9419
9420 foreach ($object->linkedObjects as $objecttype => $objects) {
9421 $tplpath = $element = $subelement = $objecttype;
9422
9423 // to display import button on tpl
9424 $showImportButton = false;
9425 if (!empty($compatibleImportElementsList) && in_array($element, $compatibleImportElementsList)) {
9426 $showImportButton = true;
9427 }
9428
9429 $regs = array();
9430 if ($objecttype != 'supplier_proposal' && preg_match('/^([^_]+)_([^_]+)/i', $objecttype, $regs)) {
9431 $element = $regs[1];
9432 $subelement = $regs[2];
9433 $tplpath = $element . '/' . $subelement;
9434 }
9435 $tplname = 'linkedobjectblock';
9436
9437 // To work with non standard path
9438 if ($objecttype == 'facture') {
9439 $tplpath = 'compta/' . $element;
9440 if (!isModEnabled('invoice')) {
9441 continue; // Do not show if module disabled
9442 }
9443 } elseif ($objecttype == 'facturerec') {
9444 $tplpath = 'compta/facture';
9445 $tplname = 'linkedobjectblockForRec';
9446 if (!isModEnabled('invoice')) {
9447 continue; // Do not show if module disabled
9448 }
9449 } elseif ($objecttype == 'propal') {
9450 $tplpath = 'comm/' . $element;
9451 if (!isModEnabled('propal')) {
9452 continue; // Do not show if module disabled
9453 }
9454 } elseif ($objecttype == 'supplier_proposal') {
9455 if (!isModEnabled('supplier_proposal')) {
9456 continue; // Do not show if module disabled
9457 }
9458 } elseif ($objecttype == 'shipping' || $objecttype == 'shipment' || $objecttype == 'expedition') {
9459 $tplpath = 'expedition';
9460 if (!isModEnabled('shipping')) {
9461 continue; // Do not show if module disabled
9462 }
9463 } elseif ($objecttype == 'reception') {
9464 $tplpath = 'reception';
9465 if (!isModEnabled('reception')) {
9466 continue; // Do not show if module disabled
9467 }
9468 } elseif ($objecttype == 'delivery') {
9469 $tplpath = 'delivery';
9470 if (!getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) {
9471 continue; // Do not show if sub module disabled
9472 }
9473 } elseif ($objecttype == 'ficheinter') {
9474 $tplpath = 'fichinter';
9475 if (!isModEnabled('intervention')) {
9476 continue; // Do not show if module disabled
9477 }
9478 } elseif ($objecttype == 'invoice_supplier') {
9479 $tplpath = 'fourn/facture';
9480 } elseif ($objecttype == 'order_supplier') {
9481 $tplpath = 'fourn/commande';
9482 } elseif ($objecttype == 'expensereport') {
9483 $tplpath = 'expensereport';
9484 } elseif ($objecttype == 'subscription') {
9485 $tplpath = 'adherents';
9486 } elseif ($objecttype == 'conferenceorbooth') {
9487 $tplpath = 'eventorganization';
9488 } elseif ($objecttype == 'conferenceorboothattendee') {
9489 $tplpath = 'eventorganization';
9490 } elseif ($objecttype == 'mo') {
9491 $tplpath = 'mrp';
9492 if (!isModEnabled('mrp')) {
9493 continue; // Do not show if module disabled
9494 }
9495 } elseif ($objecttype == 'project_task') {
9496 $tplpath = 'projet/tasks';
9497 }
9498
9499 global $linkedObjectBlock;
9500 $linkedObjectBlock = $objects;
9501
9502 // Output template part (modules that overwrite templates must declare this into descriptor)
9503 $dirtpls = array_merge($conf->modules_parts['tpl'], array('/' . $tplpath . '/tpl'));
9504 foreach ($dirtpls as $reldir) {
9505 $reldir = rtrim($reldir, '/');
9506 if ($nboftypesoutput == ($nbofdifferenttypes - 1)) { // No more type to show after
9507 global $noMoreLinkedObjectBlockAfter;
9508 $noMoreLinkedObjectBlockAfter = 1;
9509 }
9510
9511 $res = @include dol_buildpath($reldir . '/' . $tplname . '.tpl.php');
9512 if ($res) {
9513 $nboftypesoutput++;
9514 break;
9515 }
9516 }
9517 }
9518
9519 if (!$nboftypesoutput) {
9520 print '<tr><td colspan="7"><span class="opacitymedium">' . $langs->trans("None") . '</span></td></tr>';
9521 }
9522
9523 print '</table>';
9524
9525 if (!empty($compatibleImportElementsList)) {
9526 $res = @include dol_buildpath('core/tpl/objectlinked_lineimport.tpl.php');
9527 }
9528
9529 print '</div>';
9530 }
9531
9532 return $nbofdifferenttypes;
9533 }
9534
9544 public function showLinkToObjectBlock($object, $restrictlinksto = array(), $excludelinksto = array(), $nooutput = 0)
9545 {
9546 global $conf, $langs, $hookmanager;
9547 global $action;
9548
9549 $form = new Form($this->db);
9550
9551 $linktoelem = '';
9552 $linktoelemlist = '';
9553 $listofidcompanytoscan = '';
9554
9555 if (!is_object($object->thirdparty)) {
9556 $object->fetch_thirdparty();
9557 }
9558
9559 $possiblelinks = array();
9560 if (is_object($object->thirdparty) && !empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
9561 $listofidcompanytoscan = $object->thirdparty->id;
9562 if (($object->thirdparty->parent > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PARENT_IN_LINKTO')) {
9563 $listofidcompanytoscan .= ',' . $object->thirdparty->parent;
9564 }
9565 if (($object->fk_project > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PROJECT_THIRDPARY_IN_LINKTO')) {
9566 include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
9567 $tmpproject = new Project($this->db);
9568 $tmpproject->fetch($object->fk_project);
9569 if ($tmpproject->socid > 0 && ($tmpproject->socid != $object->thirdparty->id)) {
9570 $listofidcompanytoscan .= ',' . $tmpproject->socid;
9571 }
9572 unset($tmpproject);
9573 }
9574
9575 $possiblelinks = array(
9576 'propal' => array(
9577 'enabled' => isModEnabled('propal'),
9578 'perms' => 1,
9579 'label' => 'LinkToProposal',
9580 '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') . ')'),
9581 'shipping' => array(
9582 'enabled' => isModEnabled('shipping'),
9583 'perms' => 1,
9584 'label' => 'LinkToExpedition',
9585 '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') . ')'),
9586 'order' => array(
9587 'enabled' => isModEnabled('order'),
9588 'perms' => 1,
9589 'label' => 'LinkToOrder',
9590 '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') . ')'),
9591 'invoice' => array(
9592 'enabled' => isModEnabled('invoice'),
9593 'perms' => 1,
9594 'label' => 'LinkToInvoice',
9595 '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') . ')'),
9596 'invoice_template' => array(
9597 'enabled' => isModEnabled('invoice'),
9598 'perms' => 1,
9599 'label' => 'LinkToTemplateInvoice',
9600 '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') . ')'),
9601 'contrat' => array(
9602 'enabled' => isModEnabled('contract'),
9603 'perms' => 1,
9604 'label' => 'LinkToContract',
9605 '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
9606 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'
9607 ),
9608 'fichinter' => array(
9609 'enabled' => isModEnabled('intervention'),
9610 'perms' => 1,
9611 'label' => 'LinkToIntervention',
9612 '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') . ')'),
9613 'supplier_proposal' => array(
9614 'enabled' => isModEnabled('supplier_proposal'),
9615 'perms' => 1,
9616 'label' => 'LinkToSupplierProposal',
9617 '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') . ')'),
9618 'order_supplier' => array(
9619 'enabled' => isModEnabled("supplier_order"),
9620 'perms' => 1,
9621 'label' => 'LinkToSupplierOrder',
9622 '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') . ')'),
9623 'invoice_supplier' => array(
9624 'enabled' => isModEnabled("supplier_invoice"),
9625 'perms' => 1, 'label' => 'LinkToSupplierInvoice',
9626 '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') . ')'),
9627 'ticket' => array(
9628 'enabled' => isModEnabled('ticket'),
9629 'perms' => 1,
9630 'label' => 'LinkToTicket',
9631 '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') . ')'),
9632 'mo' => array(
9633 'enabled' => isModEnabled('mrp'),
9634 'perms' => 1,
9635 'label' => 'LinkToMo',
9636 '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') . ')')
9637 );
9638 }
9639
9640 if ($object->table_element == 'commande_fournisseur') {
9641 $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').')';
9642 } elseif ($object->table_element == 'mrp_mo') {
9643 $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').')';
9644 }
9645
9646 $reshook = 0; // Ensure $reshook is defined for static analysis
9647 if (!empty($listofidcompanytoscan)) { // If empty, we don't have criteria to scan the object we can link to
9648 // Can complete the possiblelink array
9649 $hookmanager->initHooks(array('commonobject'));
9650 $parameters = array('listofidcompanytoscan' => $listofidcompanytoscan, 'possiblelinks' => $possiblelinks);
9651 $reshook = $hookmanager->executeHooks('showLinkToObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9652 }
9653
9654 if (empty($reshook)) {
9655 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9656 $possiblelinks = array_merge($possiblelinks, $hookmanager->resArray);
9657 }
9658 } elseif ($reshook > 0) {
9659 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9660 $possiblelinks = $hookmanager->resArray;
9661 }
9662 }
9663
9664 // Build the html part with possible suggested links
9665 $htmltoenteralink = '';
9666 foreach ($possiblelinks as $key => $possiblelink) {
9667 $num = 0;
9668
9669 if (empty($possiblelink['enabled'])) {
9670 continue;
9671 }
9672
9673 if (!empty($possiblelink['perms']) && (empty($restrictlinksto) || in_array($key, $restrictlinksto)) && (empty($excludelinksto) || !in_array($key, $excludelinksto))) {
9674 $htmltoenteralink .= '<div id="' . $key . 'list"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display:none"') . '>';
9675
9676 // Section for free ref input
9677 if (!getDolGlobalString('MAIN_HIDE_LINK_BY_REF_IN_LINKTO')) {
9678 $htmltoenteralink .= '<br>'."\n";
9679 $htmltoenteralink .= '<!-- form to add a link from anywhere -->'."\n";
9680 $htmltoenteralink .= '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinkedbyref' . $key . '">';
9681 $htmltoenteralink .= '<input type="hidden" name="id" value="' . $object->id . '">';
9682 $htmltoenteralink .= '<input type="hidden" name="action" value="addlinkbyref">';
9683 $htmltoenteralink .= '<input type="hidden" name="token" value="' . newToken() . '">';
9684 $htmltoenteralink .= '<input type="hidden" name="addlink" value="' . $key . '">';
9685 $htmltoenteralink .= '<table class="noborder">';
9686 $htmltoenteralink .= '<tr>';
9687 //print '<td>' . $langs->trans("Ref") . '</td>';
9688 $htmltoenteralink .= '<td class="center"><input type="text" placeholder="'.dol_escape_htmltag($langs->trans("Ref")).'" name="reftolinkto" value="' . dol_escape_htmltag(GETPOST('reftolinkto', 'alpha')) . '">&nbsp;';
9689 $htmltoenteralink .= '<input type="submit" class="button small valignmiddle" value="' . $langs->trans('ToLink') . '">&nbsp;';
9690 $htmltoenteralink .= '<input type="submit" class="button small" name="cancel" value="' . $langs->trans('Cancel') . '"></td>';
9691 $htmltoenteralink .= '</tr>';
9692 $htmltoenteralink .= '</table>';
9693 $htmltoenteralink .= '</form>';
9694 }
9695
9696 $sql = $possiblelink['sql'];
9697
9698 $resqllist = $this->db->query($sql);
9699 if ($resqllist) {
9700 $num = $this->db->num_rows($resqllist);
9701 $i = 0;
9702
9703 if ($num > 0) {
9704 // Section for free predefined list
9705 $htmltoenteralink .= '<br>';
9706 $htmltoenteralink .= '<!-- form to add a link from object to same thirdparty -->'."\n";
9707 $htmltoenteralink .= '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinked' . $key . '">';
9708 $htmltoenteralink .= '<input type="hidden" name="action" value="addlink">';
9709 $htmltoenteralink .= '<input type="hidden" name="token" value="' . newToken() . '">';
9710 $htmltoenteralink .= '<input type="hidden" name="id" value="' . $object->id . '">';
9711 $htmltoenteralink .= '<input type="hidden" name="addlink" value="' . $key . '">';
9712 $htmltoenteralink .= '<table class="noborder">';
9713 $htmltoenteralink .= '<tr class="liste_titre">';
9714 $htmltoenteralink .= '<td class="nowrap"></td>';
9715 $htmltoenteralink .= '<td>' . $langs->trans("Ref") . '</td>';
9716 $htmltoenteralink .= '<td>' . $langs->trans("RefCustomer") . '</td>';
9717 $htmltoenteralink .= '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9718 $htmltoenteralink .= '<td>' . $langs->trans("Company") . '</td>';
9719 $htmltoenteralink .= '</tr>';
9720 while ($i < $num) {
9721 $objp = $this->db->fetch_object($resqllist);
9722
9723 $htmltoenteralink .= '<tr class="oddeven">';
9724 $htmltoenteralink .= '<td>';
9725 $htmltoenteralink .= '<input type="checkbox" name="idtolinkto[' . $key . '_' . $objp->rowid . ']" id="' . $key . '_' . $objp->rowid . '" value="' . $objp->rowid . '">';
9726 $htmltoenteralink .= '</td>';
9727 $htmltoenteralink .= '<td><label for="' . $key . '_' . $objp->rowid . '">' . $objp->ref . '</label></td>';
9728 $htmltoenteralink .= '<td>' . (!empty($objp->ref_client) ? $objp->ref_client : (!empty($objp->ref_supplier) ? $objp->ref_supplier : '')) . '</td>';
9729 $htmltoenteralink .= '<td class="right">';
9730 if ($possiblelink['label'] == 'LinkToContract') {
9731 $htmltoenteralink .= $form->textwithpicto('', $langs->trans("InformationOnLinkToContract")) . ' ';
9732 }
9733 $htmltoenteralink .= '<span class="amount">' . (isset($objp->total_ht) ? price($objp->total_ht) : '') . '</span>';
9734 $htmltoenteralink .= '</td>';
9735 $htmltoenteralink .= '<td>' . $objp->name . '</td>';
9736 $htmltoenteralink .= '</tr>';
9737 $i++;
9738 }
9739 $htmltoenteralink .= '</table>';
9740 $htmltoenteralink .= '<div class="center">';
9741 if ($num) {
9742 $htmltoenteralink .= '<input type="submit" class="button valignmiddle marginleftonly marginrightonly small" value="' . $langs->trans('ToLink') . '">';
9743 }
9744 if (empty($conf->use_javascript_ajax)) {
9745 $htmltoenteralink .= '<input type="submit" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9746 } else {
9747 $htmltoenteralink .= '<input type="submit" onclick="jQuery(\'#' . $key . 'list\').toggle(); return false;" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9748 }
9749 $htmltoenteralink .= '</form>';
9750 }
9751
9752 $this->db->free($resqllist);
9753 } else {
9754 dol_print_error($this->db);
9755 }
9756 $htmltoenteralink .= '</div>';
9757
9758
9759 // Complete the list for the combo box
9760 if ($num > 0 || !getDolGlobalString('MAIN_HIDE_LINK_BY_REF_IN_LINKTO')) {
9761 $linktoelemlist .= '<li><a href="#linkto' . $key . '" class="linkto dropdowncloseonclick" rel="' . $key . '">' . $langs->trans($possiblelink['label']) . ' (' . $num . ')</a></li>';
9762 // } else $linktoelem.=$langs->trans($possiblelink['label']);
9763 } else {
9764 $linktoelemlist .= '<li><span class="linktodisabled">' . $langs->trans($possiblelink['label']) . ' (0)</span></li>';
9765 }
9766 }
9767 }
9768
9769 if ($linktoelemlist) {
9770 $linktoelem = '
9771 <dl class="dropdown" id="linktoobjectname">
9772 ';
9773 if (!empty($conf->use_javascript_ajax)) {
9774 $linktoelem .= '<dt><a href="#linktoobjectname"><span class="fas fa-link paddingrightonly"></span>' . $langs->trans("LinkTo") . '...</a></dt>';
9775 }
9776 $linktoelem .= '<dd>
9777 <div class="multiselectlinkto">
9778 <ul class="ulselectedfields">' . $linktoelemlist . '
9779 </ul>
9780 </div>
9781 </dd>
9782 </dl>';
9783 } else {
9784 $linktoelem = '';
9785 }
9786
9787 if (!empty($conf->use_javascript_ajax)) {
9788 print '<!-- Add js to show linkto box -->
9789 <script nonce="' . getNonce() . '">
9790 jQuery(document).ready(function() {
9791 jQuery(".linkto").click(function() {
9792 console.log("We choose to show/hide links for rel="+jQuery(this).attr(\'rel\')+" so #"+jQuery(this).attr(\'rel\')+"list");
9793 jQuery("#"+jQuery(this).attr(\'rel\')+"list").toggle();
9794 });
9795 });
9796 </script>
9797 ';
9798 }
9799
9800 if ($nooutput) {
9801 return array('linktoelem' => $linktoelem, 'htmltoenteralink' => $htmltoenteralink);
9802 } else {
9803 print $htmltoenteralink;
9804 }
9805
9806 return $linktoelem;
9807 }
9808
9823 public function selectyesno($htmlname, $value = '', $option = 0, $disabled = false, $useempty = 0, $addjscombo = 0, $morecss = 'width75', $labelyes = 'Yes', $labelno = 'No')
9824 {
9825 global $langs;
9826
9827 $yes = "yes";
9828 $no = "no";
9829 if ($option) {
9830 $yes = "1";
9831 $no = "0";
9832 }
9833
9834 $disabled = ($disabled ? ' disabled' : '');
9835
9836 $resultyesno = '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '"' . $disabled . '>' . "\n";
9837 if ($useempty) {
9838 $resultyesno .= '<option value="-1"' . (($value < 0) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
9839 }
9840 if (("$value" == 'yes') || ($value == 1)) {
9841 $resultyesno .= '<option value="' . $yes . '" selected>' . $langs->trans($labelyes) . '</option>' . "\n";
9842 $resultyesno .= '<option value="' . $no . '">' . $langs->trans($labelno) . '</option>' . "\n";
9843 } else {
9844 $selected = (($useempty && $value != '0' && $value != 'no') ? '' : ' selected');
9845 $resultyesno .= '<option value="' . $yes . '">' . $langs->trans($labelyes) . '</option>' . "\n";
9846 $resultyesno .= '<option value="' . $no . '"' . $selected . '>' . $langs->trans($labelno) . '</option>' . "\n";
9847 }
9848 $resultyesno .= '</select>' . "\n";
9849
9850 if ($addjscombo) {
9851 $resultyesno .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($useempty < 0 ? (string) $useempty : '-1'), $morecss);
9852 }
9853
9854 return $resultyesno;
9855 }
9856
9857 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
9858
9868 public function select_export_model($selected = '', $htmlname = 'exportmodelid', $type = '', $useempty = 0)
9869 {
9870 // phpcs:enable
9871 $sql = "SELECT rowid, label";
9872 $sql .= " FROM " . $this->db->prefix() . "export_model";
9873 $sql .= " WHERE type = '" . $this->db->escape($type) . "'";
9874 $sql .= " ORDER BY rowid";
9875 $result = $this->db->query($sql);
9876 if ($result) {
9877 print '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
9878 if ($useempty) {
9879 print '<option value="-1">&nbsp;</option>';
9880 }
9881
9882 $num = $this->db->num_rows($result);
9883 $i = 0;
9884 while ($i < $num) {
9885 $obj = $this->db->fetch_object($result);
9886 if ($selected == $obj->rowid) {
9887 print '<option value="' . $obj->rowid . '" selected>';
9888 } else {
9889 print '<option value="' . $obj->rowid . '">';
9890 }
9891 print $obj->label;
9892 print '</option>';
9893 $i++;
9894 }
9895 print "</select>";
9896 } else {
9897 dol_print_error($this->db);
9898 }
9899 }
9900
9919 public function showrefnav($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $morehtmlright = '')
9920 {
9921 global $conf, $langs, $hookmanager, $extralanguages;
9922
9923 $ret = '';
9924 if (empty($fieldid)) {
9925 $fieldid = 'rowid';
9926 }
9927 if (empty($fieldref)) {
9928 $fieldref = 'ref';
9929 }
9930
9931 // Preparing gender's display if there is one
9932 $addgendertxt = '';
9933 if (property_exists($object, 'gender') && !empty($object->gender)) {
9934 $addgendertxt = ' ';
9935 switch ($object->gender) {
9936 case 'man':
9937 $addgendertxt .= '<i class="fas fa-mars"></i>';
9938 break;
9939 case 'woman':
9940 $addgendertxt .= '<i class="fas fa-venus"></i>';
9941 break;
9942 case 'other':
9943 $addgendertxt .= '<i class="fas fa-transgender"></i>';
9944 break;
9945 }
9946 }
9947
9948 // Add where from hooks
9949 if (is_object($hookmanager)) {
9950 $parameters = array('showrefnav' => true);
9951 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
9952 $object->next_prev_filter .= $hookmanager->resPrint;
9953 }
9954
9955 $previous_ref = $next_ref = '';
9956 if ($shownav) {
9957 //print "paramid=$paramid,morehtml=$morehtml,shownav=$shownav,$fieldid,$fieldref,$morehtmlref,$moreparam";
9958 $object->load_previous_next_ref((isset($object->next_prev_filter) ? $object->next_prev_filter : ''), $fieldid, $nodbprefix);
9959
9960 $navurl = $_SERVER["PHP_SELF"];
9961 // Special case for project/task page
9962 if ($paramid == 'project_ref') {
9963 if (preg_match('/\/tasks\/(task|contact|note|document)\.php/', $navurl)) { // TODO Remove this when nav with project_ref on task pages are ok
9964 $navurl = preg_replace('/\/tasks\/(task|contact|time|note|document)\.php/', '/tasks.php', $navurl);
9965 $paramid = 'ref';
9966 }
9967 }
9968
9969 // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox
9970 // accesskey is for Mac: CTRL + key for all browsers
9971 $stringforfirstkey = $langs->trans("KeyboardShortcut");
9972 if ($conf->browser->name == 'chrome') {
9973 $stringforfirstkey .= ' ALT +';
9974 } elseif ($conf->browser->name == 'firefox') {
9975 $stringforfirstkey .= ' ALT + SHIFT +';
9976 } else {
9977 $stringforfirstkey .= ' CTL +';
9978 }
9979
9980 $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>';
9981 $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>';
9982 }
9983
9984 //print "xx".$previous_ref."x".$next_ref;
9985 $ret .= '<!-- Start banner content --><div style="vertical-align: middle">';
9986
9987 // Right part of banner
9988 if ($morehtmlright) {
9989 $ret .= '<div class="inline-block floatleft">' . $morehtmlright . '</div>';
9990 }
9991
9992 if ($previous_ref || $next_ref || $morehtml) {
9993 $ret .= '<div class="pagination paginationref"><ul class="right">';
9994 }
9995 if ($morehtml && getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2) {
9996 $ret .= '<!-- morehtml --><li class="noborder litext' . (($shownav && $previous_ref && $next_ref) ? ' clearbothonsmartphone' : '') . '">' . $morehtml . '</li>';
9997 }
9998 if ($shownav && ($previous_ref || $next_ref)) {
9999 $ret .= '<li class="pagination">' . $previous_ref . '</li>';
10000 $ret .= '<li class="pagination">' . $next_ref . '</li>';
10001 }
10002 if ($previous_ref || $next_ref || $morehtml) {
10003 $ret .= '</ul></div>';
10004 }
10005
10006 // Status
10007 $parameters = array('morehtmlstatus' => $morehtmlstatus);
10008 $reshook = $hookmanager->executeHooks('moreHtmlStatus', $parameters, $object); // Note that $action and $object may have been modified by hook
10009 if (empty($reshook)) {
10010 $morehtmlstatus .= $hookmanager->resPrint;
10011 } else {
10012 $morehtmlstatus = $hookmanager->resPrint;
10013 }
10014 if ($morehtmlstatus) {
10015 $ret .= '<div class="statusref">' . $morehtmlstatus . '</div>';
10016 }
10017
10018 $parameters = array();
10019 $reshook = $hookmanager->executeHooks('moreHtmlRef', $parameters, $object); // Note that $action and $object may have been modified by hook
10020 if (empty($reshook)) {
10021 $morehtmlref .= $hookmanager->resPrint;
10022 } elseif ($reshook > 0) {
10023 $morehtmlref = $hookmanager->resPrint;
10024 }
10025
10026 // Left part of banner
10027 if ($morehtmlleft) {
10028 if ($conf->browser->layout == 'phone') {
10029 $ret .= '<!-- morehtmlleft --><div class="floatleft">' . $morehtmlleft . '</div>';
10030 } else {
10031 $ret .= '<!-- morehtmlleft --><div class="inline-block floatleft">' . $morehtmlleft . '</div>';
10032 }
10033 }
10034
10035 //if ($conf->browser->layout == 'phone') $ret.='<div class="clearboth"></div>';
10036 $ret .= '<div class="inline-block floatleft valignmiddle maxwidth750 marginbottomonly refid' . (($shownav && ($previous_ref || $next_ref)) ? ' refidpadding' : '') . '">';
10037
10038 // For thirdparty, contact, user, member, the ref is the id, so we show something else
10039 if ($object->element == 'societe') {
10040 $ret .= dol_htmlentities($object->name);
10041
10042 // List of extra languages
10043 $arrayoflangcode = array();
10044 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
10045 $arrayoflangcode[] = getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE');
10046 }
10047
10048 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
10049 if (!is_object($extralanguages)) {
10050 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
10051 $extralanguages = new ExtraLanguages($this->db);
10052 }
10053 $extralanguages->fetch_name_extralanguages('societe');
10054
10055 if (!empty($extralanguages->attributes['societe']['name'])) {
10056 $object->fetchValuesForExtraLanguages();
10057
10058 $htmltext = '';
10059 // If there is extra languages
10060 foreach ($arrayoflangcode as $extralangcode) {
10061 $htmltext .= picto_from_langcode($extralangcode, 'class="pictoforlang paddingright"');
10062 if ($object->array_languages['name'][$extralangcode]) {
10063 $htmltext .= $object->array_languages['name'][$extralangcode];
10064 } else {
10065 $htmltext .= '<span class="opacitymedium">' . $langs->trans("SwitchInEditModeToAddTranslation") . '</span>';
10066 }
10067 }
10068 $ret .= '<!-- Show translations of name -->' . "\n";
10069 $ret .= $this->textwithpicto('', $htmltext, -1, 'language', 'opacitymedium paddingleft');
10070 }
10071 }
10072 } elseif ($object->element == 'member') {
10073 '@phan-var-force Adherent $object';
10074 $ret .= $object->ref . '<br>';
10075 $fullname = $object->getFullName($langs);
10076 if ($object->morphy == 'mor' && $object->societe) {
10077 $ret .= dol_htmlentities($object->societe) . ((!empty($fullname) && $object->societe != $fullname) ? ' (' . dol_htmlentities($fullname) . $addgendertxt . ')' : '');
10078 } else {
10079 $ret .= dol_htmlentities($fullname) . $addgendertxt . ((!empty($object->societe) && $object->societe != $fullname) ? ' (' . dol_htmlentities($object->societe) . ')' : '');
10080 }
10081 } elseif (in_array($object->element, array('contact', 'user'))) {
10082 $ret .= dol_htmlentities($object->getFullName($langs)) . $addgendertxt;
10083 } elseif ($object->element == 'usergroup') {
10084 $ret .= dol_htmlentities($object->name);
10085 } elseif (in_array($object->element, array('action', 'agenda'))) {
10086 '@phan-var-force ActionComm $object';
10087 $ret .= $object->ref . '<br>' . $object->label;
10088 } elseif (in_array($object->element, array('adherent_type'))) {
10089 $ret .= $object->label;
10090 } elseif ($object->element == 'ecm_directories') {
10091 $ret .= '';
10092 } elseif ($fieldref != 'none') {
10093 $ret .= dol_htmlentities(!empty($object->$fieldref) ? $object->$fieldref : "");
10094 }
10095 if ($morehtmlref) {
10096 // don't add a additional space, when "$morehtmlref" starts with a HTML div tag
10097 if (substr($morehtmlref, 0, 4) != '<div') {
10098 $ret .= ' ';
10099 }
10100
10101 $ret .= $morehtmlref;
10102 }
10103
10104 $ret .= '</div>';
10105
10106 $ret .= '</div><!-- End banner content -->';
10107
10108 return $ret;
10109 }
10110
10111
10120 public function showbarcode(&$object, $width = 100, $morecss = '')
10121 {
10122 global $conf;
10123
10124 //Check if barcode is filled in the card
10125 if (empty($object->barcode)) {
10126 return '';
10127 }
10128
10129 // Complete object if not complete
10130 if (empty($object->barcode_type_code) || empty($object->barcode_type_coder)) {
10131 // @phan-suppress-next-line PhanPluginUnknownObjectMethodCall
10132 $result = $object->fetch_barcode();
10133 //Check if fetch_barcode() failed
10134 if ($result < 1) {
10135 return '<!-- ErrorFetchBarcode -->';
10136 }
10137 }
10138
10139 // Barcode image @phan-suppress-next-line PhanUndeclaredProperty
10140 $url = DOL_URL_ROOT . '/viewimage.php?modulepart=barcode&generator=' . urlencode($object->barcode_type_coder) . '&code=' . urlencode($object->barcode) . '&encoding=' . urlencode($object->barcode_type_code);
10141 $out = '<!-- url barcode = ' . $url . ' -->';
10142 $out .= '<img src="' . $url . '"' . ($morecss ? ' class="' . $morecss . '"' : '') . '>';
10143
10144 return $out;
10145 }
10146
10164 public static function showphoto($modulepart, $object, $width = 100, $height = 0, $caneditfield = 0, $cssclass = 'photowithmargin', $imagesize = '', $addlinktofullsize = 1, $cache = 0, $forcecapture = '', $noexternsourceoverwrite = 0)
10165 {
10166 global $conf, $langs;
10167
10168 $entity = (empty($object->entity) ? $conf->entity : $object->entity);
10169 $id = (empty($object->id) ? $object->rowid : $object->id); // @phan-suppress-current-line PhanUndeclaredProperty (->rowid)
10170
10171 $dir = '';
10172 $file = '';
10173 $originalfile = '';
10174 $altfile = '';
10175 $email = '';
10176 $capture = '';
10177 if ($modulepart == 'societe') {
10178 $dir = $conf->societe->multidir_output[$entity];
10179 if (!empty($object->logo)) {
10180 if (dolIsAllowedForPreview($object->logo)) {
10181 if ((string) $imagesize == 'mini') {
10182 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_mini'); // getImageFileNameForSize include the thumbs
10183 } elseif ((string) $imagesize == 'small') {
10184 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_small');
10185 } else {
10186 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
10187 }
10188 $originalfile = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
10189 }
10190 }
10191 $email = $object->email;
10192 } elseif ($modulepart == 'contact') {
10193 $dir = $conf->societe->multidir_output[$entity] . '/contact';
10194 if (!empty($object->photo)) {
10195 if (dolIsAllowedForPreview($object->photo)) {
10196 if ((string) $imagesize == 'mini') {
10197 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10198 } elseif ((string) $imagesize == 'small') {
10199 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10200 } else {
10201 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
10202 }
10203 $originalfile = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
10204 }
10205 }
10206 $email = $object->email;
10207 $capture = 'user';
10208 } elseif ($modulepart == 'userphoto') {
10209 $dir = $conf->user->dir_output;
10210 if (!empty($object->photo)) {
10211 if (dolIsAllowedForPreview($object->photo)) {
10212 if ((string) $imagesize == 'mini') {
10213 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10214 } elseif ((string) $imagesize == 'small') {
10215 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10216 } else {
10217 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
10218 }
10219 $originalfile = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
10220 }
10221 }
10222 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
10223 $altfile = $object->id . ".jpg"; // For backward compatibility
10224 }
10225 $email = $object->email;
10226 $capture = 'user';
10227 } elseif ($modulepart == 'memberphoto') {
10228 $dir = $conf->adherent->dir_output;
10229 if (!empty($object->photo)) {
10230 if (dolIsAllowedForPreview($object->photo)) {
10231 if ((string) $imagesize == 'mini') {
10232 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
10233 } elseif ((string) $imagesize == 'small') {
10234 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
10235 } else {
10236 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
10237 }
10238 $originalfile = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
10239 }
10240 }
10241 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
10242 $altfile = $object->id . ".jpg"; // For backward compatibility
10243 }
10244 $email = $object->email;
10245 $capture = 'user';
10246 } else {
10247 // Generic case to show photos
10248 // TODO Implement this method in previous objects so we can always use this generic method.
10249 if ($modulepart != "unknown" && method_exists($object, 'getDataToShowPhoto')) {
10250 $tmpdata = $object->getDataToShowPhoto($modulepart, $imagesize);
10251
10252 $dir = $tmpdata['dir'];
10253 $file = $tmpdata['file'];
10254 $originalfile = $tmpdata['originalfile'];
10255 $altfile = $tmpdata['altfile'];
10256 $email = $tmpdata['email'];
10257 $capture = $tmpdata['capture'];
10258 }
10259 }
10260
10261 if ($forcecapture) {
10262 $capture = $forcecapture;
10263 }
10264
10265 $ret = '';
10266
10267 if ($dir) {
10268 if ($file && file_exists($dir . "/" . $file)) {
10269 if ($addlinktofullsize) {
10270 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
10271 if ($urladvanced) {
10272 $ret .= '<a href="' . $urladvanced . '">';
10273 } else {
10274 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
10275 }
10276 }
10277 $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 . '">';
10278 if ($addlinktofullsize) {
10279 $ret .= '</a>';
10280 }
10281 } elseif ($altfile && file_exists($dir . "/" . $altfile)) {
10282 if ($addlinktofullsize) {
10283 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
10284 if ($urladvanced) {
10285 $ret .= '<a href="' . $urladvanced . '">';
10286 } else {
10287 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
10288 }
10289 }
10290 $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 . '">';
10291 if ($addlinktofullsize) {
10292 $ret .= '</a>';
10293 }
10294 } else {
10295 $nophoto = '/public/theme/common/nophoto.png';
10296 $defaultimg = 'identicon'; // For gravatar
10297 if (in_array($modulepart, array('societe', 'userphoto', 'contact', 'memberphoto'))) { // For modules that need a special image when photo not found
10298 if ($modulepart == 'societe' || ($modulepart == 'memberphoto' && !empty($object->morphy) && strpos($object->morphy, 'mor') !== false)) {
10299 $nophoto = 'company';
10300 } else {
10301 $nophoto = '/public/theme/common/user_anonymous.png';
10302 if (!empty($object->gender) && $object->gender == 'man') {
10303 $nophoto = '/public/theme/common/user_man.png';
10304 }
10305 if (!empty($object->gender) && $object->gender == 'woman') {
10306 $nophoto = '/public/theme/common/user_woman.png';
10307 }
10308 }
10309 }
10310
10311 if (isModEnabled('gravatar') && $email && empty($noexternsourceoverwrite)) {
10312 // see https://gravatar.com/site/implement/images/php/
10313 $ret .= '<!-- Put link to gravatar -->';
10314 $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
10315 } else {
10316 if ($nophoto == 'company') {
10317 $ret .= '<div class="divforspanimg valignmiddle center photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . '>' . img_picto('', 'company') . '</div>';
10318 //$ret .= '<div class="difforspanimgright"></div>';
10319 } else {
10320 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . $nophoto . '">';
10321 }
10322 }
10323 }
10324
10325 if ($caneditfield) {
10326 if ($object->photo) {
10327 $ret .= "<br>\n";
10328 }
10329 $ret .= '<table class="nobordernopadding centpercent">';
10330 if ($object->photo) {
10331 $ret .= '<tr><td><input type="checkbox" class="flat photodelete" name="deletephoto" id="photodelete"> <label for="photodelete">' . $langs->trans("Delete") . '</label><br><br></td></tr>';
10332 }
10333 $ret .= '<tr><td class="tdoverflow">';
10334 $maxfilesizearray = getMaxFileSizeArray();
10335 $maxmin = $maxfilesizearray['maxmin'];
10336 if ($maxmin > 0) {
10337 $ret .= '<input type="hidden" name="MAX_FILE_SIZE" value="' . ($maxmin * 1024) . '">'; // MAX_FILE_SIZE must precede the field type=file
10338 }
10339 $ret .= '<input type="file" class="flat maxwidth200onsmartphone" name="photo" id="photoinput" accept="image/*"' . ($capture ? ' capture="' . $capture . '"' : '') . '>';
10340 $ret .= '</td></tr>';
10341 $ret .= '</table>';
10342 }
10343 }
10344
10345 return $ret;
10346 }
10347
10348 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
10349
10366 public function select_dolgroups($selected = 0, $htmlname = 'groupid', $show_empty = 0, $exclude = '', $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0', $multiple = false, $morecss = 'minwidth200')
10367 {
10368 // phpcs:enable
10369 global $conf, $user, $langs;
10370
10371 // Allow excluding groups
10372 $excludeGroups = null;
10373 if (is_array($exclude)) {
10374 $excludeGroups = implode(",", $exclude);
10375 }
10376 // Allow including groups
10377 $includeGroups = null;
10378 if (is_array($include)) {
10379 $includeGroups = implode(",", $include);
10380 }
10381
10382 if (!is_array($selected)) {
10383 $selected = array($selected);
10384 }
10385
10386 $out = '';
10387
10388 // Build sql to search groups
10389 $sql = "SELECT ug.rowid, ug.nom as name";
10390 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10391 $sql .= ", e.label";
10392 }
10393 $sql .= " FROM " . $this->db->prefix() . "usergroup as ug ";
10394 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10395 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid=ug.entity";
10396 if ($force_entity) {
10397 $sql .= " WHERE ug.entity IN (0, " . $force_entity . ")";
10398 } else {
10399 $sql .= " WHERE ug.entity IS NOT NULL";
10400 }
10401 } else {
10402 $sql .= " WHERE ug.entity IN (0, " . $conf->entity . ")";
10403 }
10404 if (is_array($exclude) && $excludeGroups) {
10405 $sql .= " AND ug.rowid NOT IN (" . $this->db->sanitize($excludeGroups) . ")";
10406 }
10407 if (is_array($include) && $includeGroups) {
10408 $sql .= " AND ug.rowid IN (" . $this->db->sanitize($includeGroups) . ")";
10409 }
10410 $sql .= " ORDER BY ug.nom ASC";
10411
10412 dol_syslog(get_class($this) . "::select_dolgroups", LOG_DEBUG);
10413 $resql = $this->db->query($sql);
10414 if ($resql) {
10415 // Enhance with select2
10416 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10417
10418 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
10419
10420 $num = $this->db->num_rows($resql);
10421 $i = 0;
10422 if ($num) {
10423 if ($show_empty && !$multiple) {
10424 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
10425 }
10426
10427 while ($i < $num) {
10428 $obj = $this->db->fetch_object($resql);
10429 $disableline = 0;
10430 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
10431 $disableline = 1;
10432 }
10433
10434 $label = $obj->name;
10435 $labelhtml = $obj->name;
10436 if (isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1) {
10437 $label .= " (" . $obj->label . ")";
10438 $labelhtml .= ' <span class="opacitymedium">(' . $obj->label . ')</span>';
10439 }
10440
10441 $out .= '<option value="' . $obj->rowid . '"';
10442 if ($disableline) {
10443 $out .= ' disabled';
10444 }
10445 if ((isset($selected[0]) && is_object($selected[0]) && $selected[0]->id == $obj->rowid)
10446 || ((!isset($selected[0]) || !is_object($selected[0])) && !empty($selected) && in_array($obj->rowid, $selected))) {
10447 $out .= ' selected';
10448 }
10449 $out .= ' data-html="'.dol_escape_htmltag($labelhtml).'"';
10450 $out .= '>';
10451 $out .= $label;
10452 $out .= '</option>';
10453 $i++;
10454 }
10455 } else {
10456 if ($show_empty) {
10457 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '></option>' . "\n";
10458 }
10459 $out .= '<option value="" disabled>' . $langs->trans("NoUserGroupDefined") . '</option>';
10460 }
10461 $out .= '</select>';
10462
10463 $out .= ajax_combobox($htmlname);
10464 } else {
10465 dol_print_error($this->db);
10466 }
10467
10468 return $out;
10469 }
10470
10471
10478 public function showFilterButtons($pos = '')
10479 {
10480 $out = '<div class="nowraponall">';
10481 $out .= '<button type="submit" class="liste_titre button_search reposition" name="button_search_x" value="x"><span class="fas fa-search"></span></button>';
10482 $out .= '<button type="submit" class="liste_titre button_removefilter reposition" name="button_removefilter_x" value="x"><span class="fas fa-times"></span></button>';
10483 $out .= '</div>';
10484
10485 return $out;
10486 }
10487
10496 public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10497 {
10498 global $conf;
10499
10500 $out = '';
10501
10502 if (!empty($conf->use_javascript_ajax)) {
10503 $out .= '<div class="inline-block checkallactions"><input type="checkbox" id="' . $cssclass . 's" name="' . $cssclass . 's" class="checkallactions"></div>';
10504 }
10505 $out .= '<script nonce="' . getNonce() . '">
10506 $(document).ready(function() {
10507 $("#' . $cssclass . 's").click(function() {
10508 if($(this).is(\':checked\')){
10509 console.log("We check all ' . $cssclass . ' and trigger the change method");
10510 $(".' . $cssclass . '").prop(\'checked\', true).trigger(\'change\');
10511 }
10512 else
10513 {
10514 console.log("We uncheck all");
10515 $(".' . $cssclass . '").prop(\'checked\', false).trigger(\'change\');
10516 }' . "\n";
10517 if ($calljsfunction) {
10518 $out .= 'if (typeof initCheckForSelect == \'function\') { initCheckForSelect(0, "' . $massactionname . '", "' . $cssclass . '"); } else { console.log("No function initCheckForSelect found. Call won\'t be done."); }';
10519 }
10520 $out .= ' });
10521 $(".' . $cssclass . '").change(function() {
10522 $(this).closest("tr").toggleClass("highlight", this.checked);
10523 });
10524 });
10525 </script>';
10526
10527 return $out;
10528 }
10529
10539 public function showFilterAndCheckAddButtons($addcheckuncheckall = 0, $cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10540 {
10541 $out = $this->showFilterButtons();
10542 if ($addcheckuncheckall) {
10543 $out .= $this->showCheckAddButtons($cssclass, $calljsfunction, $massactionname);
10544 }
10545 return $out;
10546 }
10547
10561 public function selectExpenseCategories($selected = '', $htmlname = 'fk_c_exp_tax_cat', $useempty = 0, $excludeid = array(), $target = '', $default_selected = 0, $params = array(), $info_admin = 1)
10562 {
10563 global $langs, $user;
10564
10565 $out = '';
10566 $sql = "SELECT rowid, label FROM " . $this->db->prefix() . "c_exp_tax_cat WHERE active = 1";
10567 $sql .= " AND entity IN (0," . getEntity('exp_tax_cat') . ")";
10568 if (!empty($excludeid)) {
10569 $sql .= " AND rowid NOT IN (" . $this->db->sanitize(implode(',', $excludeid)) . ")";
10570 }
10571 $sql .= " ORDER BY label";
10572
10573 $resql = $this->db->query($sql);
10574 if ($resql) {
10575 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp maxwidth200">';
10576 if ($useempty) {
10577 $out .= '<option value="0">&nbsp;</option>';
10578 }
10579
10580 while ($obj = $this->db->fetch_object($resql)) {
10581 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . $langs->trans($obj->label) . '</option>';
10582 }
10583 $out .= '</select>';
10584 $out .= ajax_combobox('select_' . $htmlname);
10585
10586 if (!empty($htmlname) && $user->admin && $info_admin) {
10587 $out .= ' ' . info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
10588 }
10589
10590 if (!empty($target)) {
10591 $sql = "SELECT c.id FROM " . $this->db->prefix() . "c_type_fees as c WHERE c.code = 'EX_KME' AND c.active = 1";
10592 $resql = $this->db->query($sql);
10593 if ($resql) {
10594 if ($this->db->num_rows($resql) > 0) {
10595 $obj = $this->db->fetch_object($resql);
10596 $out .= '<script nonce="' . getNonce() . '">
10597 $(function() {
10598 $("select[name=' . $target . ']").on("change", function() {
10599 var current_val = $(this).val();
10600 if (current_val == ' . $obj->id . ') {';
10601 if (!empty($default_selected) || !empty($selected)) {
10602 $out .= '$("select[name=' . $htmlname . ']").val("' . ($default_selected > 0 ? $default_selected : $selected) . '");';
10603 }
10604
10605 $out .= '
10606 $("select[name=' . $htmlname . ']").change();
10607 }
10608 });
10609
10610 $("select[name=' . $htmlname . ']").change(function() {
10611
10612 if ($("select[name=' . $target . ']").val() == ' . $obj->id . ') {
10613 // get price of kilometer to fill the unit price
10614 $.ajax({
10615 method: "POST",
10616 dataType: "json",
10617 data: { fk_c_exp_tax_cat: $(this).val(), token: \'' . currentToken() . '\' },
10618 url: "' . (DOL_URL_ROOT . '/expensereport/ajax/ajaxik.php?' . implode('&', $params)) . '",
10619 }).done(function( data, textStatus, jqXHR ) {
10620 console.log(data);
10621 if (typeof data.up != "undefined") {
10622 $("input[name=value_unit]").val(data.up);
10623 $("select[name=' . $htmlname . ']").attr("title", data.title);
10624 } else {
10625 $("input[name=value_unit]").val("");
10626 $("select[name=' . $htmlname . ']").attr("title", "");
10627 }
10628 });
10629 }
10630 });
10631 });
10632 </script>';
10633 }
10634 }
10635 }
10636 } else {
10637 dol_print_error($this->db);
10638 }
10639
10640 return $out;
10641 }
10642
10651 public function selectExpenseRanges($selected = '', $htmlname = 'fk_range', $useempty = 0)
10652 {
10653 global $conf, $langs;
10654
10655 $out = '';
10656 $sql = "SELECT rowid, range_ik FROM " . $this->db->prefix() . "c_exp_tax_range";
10657 $sql .= " WHERE entity = " . $conf->entity . " AND active = 1";
10658
10659 $resql = $this->db->query($sql);
10660 if ($resql) {
10661 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10662 if ($useempty) {
10663 $out .= '<option value="0"></option>';
10664 }
10665
10666 while ($obj = $this->db->fetch_object($resql)) {
10667 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . price($obj->range_ik, 0, $langs, 1, 0) . '</option>';
10668 }
10669 $out .= '</select>';
10670 } else {
10671 dol_print_error($this->db);
10672 }
10673
10674 return $out;
10675 }
10676
10687 public function selectExpense($selected = '', $htmlname = 'fk_c_type_fees', $useempty = 0, $allchoice = 1, $useid = 0)
10688 {
10689 global $langs;
10690
10691 $out = '';
10692 $sql = "SELECT id, code, label";
10693 $sql .= " FROM ".$this->db->prefix()."c_type_fees";
10694 $sql .= " WHERE active = 1";
10695
10696 $resql = $this->db->query($sql);
10697 if ($resql) {
10698 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10699 if ($useempty) {
10700 $out .= '<option value="0"></option>';
10701 }
10702 if ($allchoice) {
10703 $out .= '<option value="-1">' . $langs->trans('AllExpenseReport') . '</option>';
10704 }
10705
10706 $field = 'code';
10707 if ($useid) {
10708 $field = 'id';
10709 }
10710
10711 while ($obj = $this->db->fetch_object($resql)) {
10712 $key = $langs->trans($obj->code);
10713 $out .= '<option ' . ($selected == $obj->{$field} ? 'selected="selected"' : '') . ' value="' . $obj->{$field} . '">' . ($key != $obj->code ? $key : $obj->label) . '</option>';
10714 }
10715 $out .= '</select>';
10716
10717 $out .= ajax_combobox('select_'.$htmlname);
10718 } else {
10719 dol_print_error($this->db);
10720 }
10721
10722 return $out;
10723 }
10724
10743 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)
10744 {
10745 global $user, $conf, $langs;
10746
10747 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
10748
10749 if (is_null($usertofilter)) {
10750 $usertofilter = $user;
10751 }
10752
10753 $out = '';
10754
10755 $hideunselectables = false;
10756 if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
10757 $hideunselectables = true;
10758 }
10759
10760 if (empty($projectsListId)) {
10761 if (!$usertofilter->hasRight('projet', 'all', 'lire')) {
10762 $projectstatic = new Project($this->db);
10763 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertofilter, 0, 1);
10764 }
10765 }
10766
10767 // Search all projects
10768 $sql = "SELECT f.rowid, f.ref as fref, 'nolabel' as flabel, p.rowid as pid, f.ref,
10769 p.title, p.fk_soc, p.fk_statut, p.public,";
10770 $sql .= ' s.nom as name';
10771 $sql .= ' FROM ' . $this->db->prefix() . 'projet as p';
10772 $sql .= ' LEFT JOIN ' . $this->db->prefix() . 'societe as s ON s.rowid = p.fk_soc,';
10773 $sql .= ' ' . $this->db->prefix() . 'facture as f';
10774 $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
10775 $sql .= " AND f.fk_projet = p.rowid AND f.fk_statut=0"; //Brouillons seulement
10776 //if ($projectsListId) $sql.= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")";
10777 //if ($socid == 0) $sql.= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
10778 //if ($socid > 0) $sql.= " AND (p.fk_soc=".((int) $socid)." OR p.fk_soc IS NULL)";
10779 $sql .= " ORDER BY p.ref, f.ref ASC";
10780
10781 $resql = $this->db->query($sql);
10782 if ($resql) {
10783 // Use select2 selector
10784 if (!empty($conf->use_javascript_ajax)) {
10785 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10786 $comboenhancement = ajax_combobox($htmlname, array(), 0, $forcefocus);
10787 $out .= $comboenhancement;
10788 $morecss = 'minwidth200imp maxwidth500';
10789 }
10790
10791 if (empty($option_only)) {
10792 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10793 }
10794 if (!empty($show_empty)) {
10795 $out .= '<option value="0" class="optiongrey">';
10796 if (!is_numeric($show_empty)) {
10797 $out .= $show_empty;
10798 } else {
10799 $out .= '&nbsp;';
10800 }
10801 $out .= '</option>';
10802 }
10803 $num = $this->db->num_rows($resql);
10804 $i = 0;
10805 if ($num) {
10806 while ($i < $num) {
10807 $obj = $this->db->fetch_object($resql);
10808 // 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.
10809 if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$usertofilter->hasRight('societe', 'lire')) {
10810 // Do nothing
10811 } else {
10812 if ($discard_closed == 1 && $obj->fk_statut == Project::STATUS_CLOSED) {
10813 $i++;
10814 continue;
10815 }
10816
10817 $labeltoshow = '';
10818
10819 if ($showproject == 'all') {
10820 $labeltoshow .= dol_trunc($obj->ref, 18); // Invoice ref
10821 if ($obj->name) {
10822 $labeltoshow .= ' - ' . $obj->name; // Soc name
10823 }
10824
10825 $disabled = 0;
10826 if ($obj->fk_statut == Project::STATUS_DRAFT) {
10827 $disabled = 1;
10828 $labeltoshow .= ' - ' . $langs->trans("Draft");
10829 } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
10830 if ($discard_closed == 2) {
10831 $disabled = 1;
10832 }
10833 $labeltoshow .= ' - ' . $langs->trans("Closed");
10834 } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
10835 $disabled = 1;
10836 $labeltoshow .= ' - ' . $langs->trans("LinkedToAnotherCompany");
10837 }
10838 }
10839
10840 if (!empty($selected) && $selected == $obj->rowid) {
10841 $out .= '<option value="' . $obj->rowid . '" selected';
10842 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10843 $out .= '>' . $labeltoshow . '</option>';
10844 } else {
10845 if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
10846 $resultat = '';
10847 } else {
10848 $resultat = '<option value="' . $obj->rowid . '"';
10849 if ($disabled) {
10850 $resultat .= ' disabled';
10851 }
10852 //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
10853 //else $labeltoshow.=' ('.$langs->trans("Private").')';
10854 $resultat .= '>';
10855 $resultat .= $labeltoshow;
10856 $resultat .= '</option>';
10857 }
10858 $out .= $resultat;
10859 }
10860 }
10861 $i++;
10862 }
10863 }
10864 if (empty($option_only)) {
10865 $out .= '</select>';
10866 }
10867
10868 $this->db->free($resql);
10869
10870 return $out;
10871 } else {
10872 dol_print_error($this->db);
10873 return '';
10874 }
10875 }
10876
10890 public function selectInvoiceRec($selected = '', $htmlname = 'facrecid', $maxlength = 24, $option_only = 0, $show_empty = '1', $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500')
10891 {
10892 global $conf, $langs;
10893
10894 $out = '';
10895
10896 dol_syslog('FactureRec::fetch', LOG_DEBUG);
10897
10898 $sql = 'SELECT f.rowid, f.entity, f.titre as title, f.suspended, f.fk_soc';
10899 //$sql.= ', el.fk_source';
10900 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_rec as f';
10901 $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
10902 $sql .= " ORDER BY f.titre ASC";
10903
10904 $resql = $this->db->query($sql);
10905 if ($resql) {
10906 // Use select2 selector
10907 if (!empty($conf->use_javascript_ajax)) {
10908 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10909 $comboenhancement = ajax_combobox($htmlname, array(), 0, $forcefocus);
10910 $out .= $comboenhancement;
10911 $morecss = 'minwidth200imp maxwidth500';
10912 }
10913
10914 if (empty($option_only)) {
10915 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10916 }
10917 if (!empty($show_empty)) {
10918 $out .= '<option value="0" class="optiongrey">';
10919 if (!is_numeric($show_empty)) {
10920 $out .= $show_empty;
10921 } else {
10922 $out .= '&nbsp;';
10923 }
10924 $out .= '</option>';
10925 }
10926 $num = $this->db->num_rows($resql);
10927 if ($num) {
10928 while ($obj = $this->db->fetch_object($resql)) {
10929 $labeltoshow = dol_trunc($obj->title, 18); // Invoice ref
10930
10931 $disabled = 0;
10932 if (!empty($obj->suspended)) {
10933 $disabled = 1;
10934 $labeltoshow .= ' - ' . $langs->trans("Closed");
10935 }
10936
10937
10938 if (!empty($selected) && $selected == $obj->rowid) {
10939 $out .= '<option value="' . $obj->rowid . '" selected';
10940 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10941 $out .= '>' . $labeltoshow . '</option>';
10942 } else {
10943 if ($disabled && ($selected != $obj->rowid)) {
10944 $resultat = '';
10945 } else {
10946 $resultat = '<option value="' . $obj->rowid . '"';
10947 if ($disabled) {
10948 $resultat .= ' disabled';
10949 }
10950 $resultat .= '>';
10951 $resultat .= $labeltoshow;
10952 $resultat .= '</option>';
10953 }
10954 $out .= $resultat;
10955 }
10956 }
10957 }
10958 if (empty($option_only)) {
10959 $out .= '</select>';
10960 }
10961
10962 print $out;
10963
10964 $this->db->free($resql);
10965 return $num;
10966 } else {
10967 $this->errors[] = $this->db->lasterror;
10968 return -1;
10969 }
10970 }
10971
10981 public function searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput = array(), $search_component_params_hidden = '')
10982 {
10983 global $langs;
10984
10985 if ($search_component_params_hidden != '' && !preg_match('/^\‍(.*\‍)$/', $search_component_params_hidden)) { // If $search_component_params_hidden does not start and end with ()
10986 $search_component_params_hidden = '(' . $search_component_params_hidden . ')';
10987 }
10988
10989 $ret = '';
10990
10991 $ret .= '<div class="divadvancedsearchfieldcomp centpercent inline-block">';
10992 $ret .= '<a href="#" class="dropdownsearch-toggle unsetcolor">';
10993 $ret .= '<span class="fas fa-filter linkobject boxfilter paddingright pictofixedwidth" title="' . dol_escape_htmltag($langs->trans("Filters")) . '" id="idsubimgproductdistribution"></span>';
10994 $ret .= '</a>';
10995
10996 $ret .= '<div class="divadvancedsearchfieldcompinput inline-block minwidth500 maxwidth300onsmartphone">';
10997
10998 // Show select fields as tags.
10999 $ret .= '<div id="divsearch_component_params" name="divsearch_component_params" class="noborderbottom search_component_params inline-block valignmiddle">';
11000
11001 if ($search_component_params_hidden) {
11002 // Split the criteria on each AND
11003 //var_dump($search_component_params_hidden);
11004
11005 $arrayofandtags = dolForgeExplodeAnd($search_component_params_hidden);
11006
11007 // $arrayofandtags is now array( '...' , '...', ...)
11008 // Show each AND part
11009 foreach ($arrayofandtags as $tmpkey => $tmpval) {
11010 $errormessage = '';
11011 $searchtags = forgeSQLFromUniversalSearchCriteria($tmpval, $errormessage, 1, 1);
11012 if ($errormessage) {
11013 $this->error = 'ERROR in parsing search string: '.$errormessage;
11014 }
11015 // Remove first and last parenthesis but only if first is the opening and last the closing of the same group
11016 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
11017 $searchtags = removeGlobalParenthesis($searchtags);
11018
11019 $ret .= '<span class="marginleftonlyshort valignmiddle tagsearch" data-ufilterid="'.($tmpkey + 1).'" data-ufilter="'.dol_escape_htmltag($tmpval).'">';
11020 $ret .= '<span class="tagsearchdelete select2-selection__choice__remove" data-ufilterid="'.($tmpkey + 1).'">x</span> ';
11021 $ret .= dol_escape_htmltag($searchtags);
11022 $ret .= '</span>';
11023 }
11024 }
11025
11026 //$ret .= '<button type="submit" class="liste_titre button_search paddingleftonly" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
11027
11028 //$ret .= search_component_params
11029 //$texttoshow = '<div class="opacitymedium inline-block search_component_searchtext">'.$langs->trans("Search").'</div>';
11030 //$ret .= '<div class="search_component inline-block valignmiddle">'.$texttoshow.'</div>';
11031
11032 $show_search_component_params_hidden = 1;
11033 if ($show_search_component_params_hidden) {
11034 $ret .= '<input type="hidden" name="show_search_component_params_hidden" value="1">';
11035 }
11036 $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%')) -->";
11037 $ret .= '<input type="hidden" id="search_component_params_hidden" name="search_component_params_hidden" value="' . dol_escape_htmltag($search_component_params_hidden) . '">';
11038 // $ret .= "<!-- sql= ".forgeSQLFromUniversalSearchCriteria($search_component_params_hidden, $errormessage)." -->";
11039
11040 // For compatibility with forms that show themself the search criteria in addition of this component, we output these fields
11041 foreach ($arrayofcriterias as $criteria) {
11042 foreach ($criteria as $criteriafamilykey => $criteriafamilyval) {
11043 if (in_array('search_' . $criteriafamilykey, $arrayofinputfieldsalreadyoutput)) {
11044 continue;
11045 }
11046 if (in_array($criteriafamilykey, array('rowid', 'ref_ext', 'entity', 'extraparams'))) {
11047 continue;
11048 }
11049 if (in_array($criteriafamilyval['type'], array('date', 'datetime', 'timestamp'))) {
11050 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_start">';
11051 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startyear">';
11052 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startmonth">';
11053 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startday">';
11054 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_end">';
11055 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endyear">';
11056 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endmonth">';
11057 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endday">';
11058 } else {
11059 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '">';
11060 }
11061 }
11062 }
11063
11064 $ret .= '</div>';
11065
11066 $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";
11067 $ret .= '<input type="text" placeholder="' . $langs->trans("Filters") . '" id="search_component_params_input" name="search_component_params_input" class="noborderbottom search_component_input" value="">';
11068
11069 $ret .= '</div>';
11070 $ret .= '</div>';
11071
11072 $ret .= '<script>
11073 jQuery(".tagsearchdelete").click(function(e) {
11074 var filterid = $(this).parents().attr("data-ufilterid");
11075 console.log("We click to delete the criteria nb "+filterid);
11076
11077 // Regenerate the search_component_params_hidden with all data-ufilter except the one to delete, and post the page
11078 var newparamstring = \'\';
11079 $(\'.tagsearch\').each(function(index, element) {
11080 tmpfilterid = $(this).attr("data-ufilterid");
11081 if (tmpfilterid != filterid) {
11082 // We keep this criteria
11083 if (newparamstring == \'\') {
11084 newparamstring = $(this).attr("data-ufilter");
11085 } else {
11086 newparamstring = newparamstring + \' AND \' + $(this).attr("data-ufilter");
11087 }
11088 }
11089 });
11090 console.log("newparamstring = "+newparamstring);
11091
11092 jQuery("#search_component_params_hidden").val(newparamstring);
11093
11094 // We repost the form
11095 $(this).closest(\'form\').submit();
11096 });
11097
11098 jQuery("#search_component_params_input").keydown(function(e) {
11099 console.log("We press a key on the filter field that is "+jQuery("#search_component_params_input").val());
11100 console.log(e.which);
11101 if (jQuery("#search_component_params_input").val() == "" && e.which == 8) {
11102 /* We click on back when the input field is already empty */
11103 event.preventDefault();
11104 jQuery("#divsearch_component_params .tagsearch").last().remove();
11105 /* Regenerate content of search_component_params_hidden from remaining .tagsearch */
11106 var s = "";
11107 jQuery("#divsearch_component_params .tagsearch").each(function( index ) {
11108 if (s != "") {
11109 s = s + " AND ";
11110 }
11111 s = s + $(this).attr("data-ufilter");
11112 });
11113 console.log("New value for search_component_params_hidden = "+s);
11114 jQuery("#search_component_params_hidden").val(s);
11115 }
11116 });
11117
11118 </script>
11119 ';
11120
11121 return $ret;
11122 }
11123
11133 public function selectModelMail($prefix, $modelType = '', $default = 0, $addjscombo = 0)
11134 {
11135 global $langs, $user;
11136
11137 $retstring = '';
11138
11139 $TModels = array();
11140
11141 include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
11142 $formmail = new FormMail($this->db);
11143 $result = $formmail->fetchAllEMailTemplate($modelType, $user, $langs);
11144
11145 if ($default) {
11146 $TModels[0] = $langs->trans('DefaultMailModel');
11147 }
11148 if ($result > 0) {
11149 foreach ($formmail->lines_model as $model) {
11150 $TModels[$model->id] = $model->label;
11151 }
11152 }
11153
11154 $retstring .= '<select class="flat" id="select_' . $prefix . 'model_mail" name="' . $prefix . 'model_mail">';
11155
11156 foreach ($TModels as $id_model => $label_model) {
11157 $retstring .= '<option value="' . $id_model . '"';
11158 $retstring .= ">" . $label_model . "</option>";
11159 }
11160
11161 $retstring .= "</select>";
11162
11163 if ($addjscombo) {
11164 $retstring .= ajax_combobox('select_' . $prefix . 'model_mail');
11165 }
11166
11167 return $retstring;
11168 }
11169
11181 public function buttonsSaveCancel($save_label = 'Save', $cancel_label = 'Cancel', $morebuttons = array(), $withoutdiv = false, $morecss = '', $dol_openinpopup = '')
11182 {
11183 global $langs;
11184
11185 $buttons = array();
11186
11187 $save = array(
11188 'name' => 'save',
11189 'label_key' => $save_label,
11190 );
11191
11192 if ($save_label == 'Create' || $save_label == 'Add') {
11193 $save['name'] = 'add';
11194 } elseif ($save_label == 'Modify') {
11195 $save['name'] = 'edit';
11196 }
11197
11198 $cancel = array(
11199 'name' => 'cancel',
11200 'label_key' => 'Cancel',
11201 );
11202
11203 !empty($save_label) ? $buttons[] = $save : '';
11204
11205 if (!empty($morebuttons)) {
11206 $buttons[] = $morebuttons;
11207 }
11208
11209 !empty($cancel_label) ? $buttons[] = $cancel : '';
11210
11211 $retstring = $withoutdiv ? '' : '<div class="center">';
11212
11213 foreach ($buttons as $button) {
11214 $addclass = empty($button['addclass']) ? '' : $button['addclass'];
11215 $retstring .= '<input type="submit" class="button button-' . $button['name'] . ($morecss ? ' ' . $morecss : '') . ' ' . $addclass . '" name="' . $button['name'] . '" value="' . dol_escape_htmltag($langs->trans($button['label_key'])) . '">';
11216 }
11217 $retstring .= $withoutdiv ? '' : '</div>';
11218
11219 if ($dol_openinpopup) {
11220 $retstring .= '<!-- buttons are shown into a $dol_openinpopup=' . dol_escape_htmltag($dol_openinpopup) . ' context, so we enable the close of dialog on cancel -->' . "\n";
11221 $retstring .= '<script nonce="' . getNonce() . '">';
11222 $retstring .= 'jQuery(".button-cancel").click(function(e) {
11223 e.preventDefault(); console.log(\'We click on cancel in iframe popup ' . dol_escape_js($dol_openinpopup) . '\');
11224 window.parent.jQuery(\'#idfordialog' . dol_escape_js($dol_openinpopup) . '\').dialog(\'close\');
11225 });';
11226 $retstring .= '</script>';
11227 }
11228
11229 return $retstring;
11230 }
11231
11232
11233 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
11234
11241 {
11242 // phpcs:enable
11243 global $langs;
11244
11245 $num = count($this->cache_invoice_subtype);
11246 if ($num > 0) {
11247 return 0; // Cache already loaded
11248 }
11249
11250 dol_syslog(__METHOD__, LOG_DEBUG);
11251
11252 $sql = "SELECT rowid, code, label as label";
11253 $sql .= " FROM " . MAIN_DB_PREFIX . 'c_invoice_subtype';
11254 $sql .= " WHERE active = 1";
11255
11256 $resql = $this->db->query($sql);
11257 if ($resql) {
11258 $num = $this->db->num_rows($resql);
11259 $i = 0;
11260 while ($i < $num) {
11261 $obj = $this->db->fetch_object($resql);
11262
11263 // If translation exists, we use it, otherwise we take the default wording
11264 $label = ($langs->trans("InvoiceSubtype" . $obj->rowid) != "InvoiceSubtype" . $obj->rowid) ? $langs->trans("InvoiceSubtype" . $obj->rowid) : (($obj->label != '-') ? $obj->label : '');
11265 $this->cache_invoice_subtype[$obj->rowid]['rowid'] = $obj->rowid;
11266 $this->cache_invoice_subtype[$obj->rowid]['code'] = $obj->code;
11267 $this->cache_invoice_subtype[$obj->rowid]['label'] = $label;
11268 $i++;
11269 }
11270
11271 $this->cache_invoice_subtype = dol_sort_array($this->cache_invoice_subtype, 'code', 'asc', 0, 0, 1);
11272
11273 return $num;
11274 } else {
11275 dol_print_error($this->db);
11276 return -1;
11277 }
11278 }
11279
11280
11291 public function getSelectInvoiceSubtype($selected = 0, $htmlname = 'subtypeid', $addempty = 0, $noinfoadmin = 0, $morecss = '')
11292 {
11293 global $langs, $user;
11294
11295 $out = '';
11296 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
11297
11299
11300 $out .= '<select id="' . $htmlname . '" class="flat selectsubtype' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
11301 if ($addempty) {
11302 $out .= '<option value="0">&nbsp;</option>';
11303 }
11304
11305 foreach ($this->cache_invoice_subtype as $rowid => $subtype) {
11306 $label = $subtype['label'];
11307 $out .= '<option value="' . $subtype['rowid'] . '"';
11308 if ($selected == $subtype['rowid']) {
11309 $out .= ' selected="selected"';
11310 }
11311 $out .= '>';
11312 $out .= $label;
11313 $out .= '</option>';
11314 }
11315
11316 $out .= '</select>';
11317 if ($user->admin && empty($noinfoadmin)) {
11318 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
11319 }
11320 $out .= ajax_combobox($htmlname);
11321
11322 return $out;
11323 }
11324}
$id
Definition account.php:39
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:640
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:49
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:457
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:306
ajax_event($htmlname, $events)
Add event management script.
Definition ajax.lib.php:560
$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.
showLinkToObjectBlock($object, $restrictlinksto=array(), $excludelinksto=array(), $nooutput=0)
Show block with links "to link to" other objects.
selectModelMail($prefix, $modelType='', $default=0, $addjscombo=0)
selectModelMail
showFilterButtons($pos='')
Return HTML to show the search and clear search button.
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.
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...
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, $warehouseId=0)
Return list of products for customer.
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_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.
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, $warehouseId=0)
Return list of products for a customer.
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.
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.
selectyesno($htmlname, $value='', $option=0, $disabled=false, $useempty=0, $addjscombo=0, $morecss='width75', $labelyes='Yes', $labelno='No')
Return an html string with a select combo box to choose yes or no.
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.
textwithpicto($text, $htmltext, $direction=1, $type='help', $extracss='valignmiddle', $noencodehtmltext=0, $notabs=3, $tooltiptrigger='', $forcenowrap=0)
Show a text with a picto and a tooltip on picto.
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:85
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.
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)
dol_print_phone($phone, $countrycode='', $cid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0, $morecss='paddingright')
Format phone numbers according to country.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles=1, $removeclassattribute=1, $cleanalsojavascript=0, $allowiframe=0, $allowed_tags=array(), $allowlink=0, $allowscript=0)
Clean a string to keep only desirable HTML tags.
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_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_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.
dol_print_email($email, $cid=0, $socid=0, $addlink=0, $max=64, $showinvalid=1, $withpicto=0, $morecss='paddingrightonly')
Show EMail link formatted for HTML output.
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 a 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.