dolibarr 19.0.3
html.form.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
5 * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
6 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
7 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com>
8 * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
9 * Copyright (C) 2006 Marc Barilley/Ocebo <marc@ocebo.com>
10 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerker@telenet.be>
11 * Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
12 * Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
13 * Copyright (C) 2010-2021 Philippe Grand <philippe.grand@atoo-net.com>
14 * Copyright (C) 2011 Herve Prot <herve.prot@symeos.com>
15 * Copyright (C) 2012-2016 Marcos García <marcosgdf@gmail.com>
16 * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
17 * Copyright (C) 2012-2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
18 * Copyright (C) 2014-2023 Alexandre Spangaro <aspangaro@open-dsi.fr>
19 * Copyright (C) 2018-2022 Ferran Marcet <fmarcet@2byte.es>
20 * Copyright (C) 2018-2021 Frédéric France <frederic.france@netlogic.fr>
21 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
22 * Copyright (C) 2018 Christophe Battarel <christophe@altairis.fr>
23 * Copyright (C) 2018 Josep Lluis Amador <joseplluis@lliuretic.cat>
24 * Copyright (C) 2023 Joachim Kueter <git-jk@bloxera.com>
25 * Copyright (C) 2023 Nick Fragoulis
26 *
27 * This program is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License as published by
29 * the Free Software Foundation; either version 3 of the License, or
30 * (at your option) any later version.
31 *
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with this program. If not, see <https://www.gnu.org/licenses/>.
39 */
40
54class Form
55{
59 public $db;
60
64 public $error = '';
65
69 public $errors = array();
70
71 // Some properties used to return data by some methods
72 public $result;
73 public $num;
74
75 // Cache arrays
76 public $cache_types_paiements = array();
77 public $cache_conditions_paiements = array();
78 public $cache_transport_mode = array();
79 public $cache_availability = array();
80 public $cache_demand_reason = array();
81 public $cache_types_fees = array();
82 public $cache_vatrates = array();
83 public $cache_invoice_subtype = array();
84
85
91 public function __construct($db)
92 {
93 $this->db = $db;
94 }
95
112 public function editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata = 'string', $moreparam = '', $fieldrequired = 0, $notabletag = 0, $paramid = 'id', $help = '')
113 {
114 global $conf, $langs;
115
116 $ret = '';
117
118 // TODO change for compatibility
119 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;/', $typeofdata)) {
120 if (!empty($perm)) {
121 $tmp = explode(':', $typeofdata);
122 $ret .= '<div class="editkey_' . $tmp[0] . (!empty($tmp[1]) ? ' ' . $tmp[1] : '') . '" id="' . $htmlname . '">';
123 if ($fieldrequired) {
124 $ret .= '<span class="fieldrequired">';
125 }
126 if ($help) {
127 $ret .= $this->textwithpicto($langs->trans($text), $help);
128 } else {
129 $ret .= $langs->trans($text);
130 }
131 if ($fieldrequired) {
132 $ret .= '</span>';
133 }
134 $ret .= '</div>' . "\n";
135 } else {
136 if ($fieldrequired) {
137 $ret .= '<span class="fieldrequired">';
138 }
139 if ($help) {
140 $ret .= $this->textwithpicto($langs->trans($text), $help);
141 } else {
142 $ret .= $langs->trans($text);
143 }
144 if ($fieldrequired) {
145 $ret .= '</span>';
146 }
147 }
148 } else {
149 if (empty($notabletag) && $perm) {
150 $ret .= '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
151 }
152 if ($fieldrequired) {
153 $ret .= '<span class="fieldrequired">';
154 }
155 if ($help) {
156 $ret .= $this->textwithpicto($langs->trans($text), $help);
157 } else {
158 $ret .= $langs->trans($text);
159 }
160 if ($fieldrequired) {
161 $ret .= '</span>';
162 }
163 if (!empty($notabletag)) {
164 $ret .= ' ';
165 }
166 if (empty($notabletag) && $perm) {
167 $ret .= '</td>';
168 }
169 if (empty($notabletag) && $perm) {
170 $ret .= '<td class="right">';
171 }
172 if ($htmlname && GETPOST('action', 'aZ09') != 'edit' . $htmlname && $perm) {
173 $ret .= '<a class="editfielda reposition" href="' . $_SERVER["PHP_SELF"] . '?action=edit' . $htmlname . '&token=' . newToken() . '&' . $paramid . '=' . $object->id . $moreparam . '">' . img_edit($langs->trans('Edit'), ($notabletag ? 0 : 1)) . '</a>';
174 }
175 if (!empty($notabletag) && $notabletag == 1) {
176 if ($text) {
177 $ret .= ' : ';
178 } else {
179 $ret .= ' ';
180 }
181 }
182 if (!empty($notabletag) && $notabletag == 3) {
183 $ret .= ' ';
184 }
185 if (empty($notabletag) && $perm) {
186 $ret .= '</td>';
187 }
188 if (empty($notabletag) && $perm) {
189 $ret .= '</tr></table>';
190 }
191 }
192
193 return $ret;
194 }
195
219 public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 1, $formatfunc = '', $paramid = 'id', $gm = 'auto', $moreoptions = array(), $editaction = '')
220 {
221 global $conf, $langs;
222
223 $ret = '';
224
225 // Check parameters
226 if (empty($typeofdata)) {
227 return 'ErrorBadParameter typeofdata is empty';
228 }
229 // Clean paramater $typeofdata
230 if ($typeofdata == 'datetime') {
231 $typeofdata = 'dayhour';
232 }
233 $reg = array();
234 if (preg_match('/^(\w+)\‍((\d+)\‍)$/', $typeofdata, $reg)) {
235 if ($reg[1] == 'varchar') {
236 $typeofdata = 'string';
237 } elseif ($reg[1] == 'int') {
238 $typeofdata = 'numeric';
239 } else {
240 return 'ErrorBadParameter ' . $typeofdata;
241 }
242 }
243
244 // When option to edit inline is activated
245 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;|day|datepicker|dayhour|datehourpicker/', $typeofdata)) { // TODO add jquery timepicker and support select
246 $ret .= $this->editInPlace($object, $value, $htmlname, $perm, $typeofdata, $editvalue, $extObject, $custommsg);
247 } else {
248 if ($editaction == '') {
249 $editaction = GETPOST('action', 'aZ09');
250 }
251 $editmode = ($editaction == 'edit' . $htmlname);
252 if ($editmode) { // edit mode
253 $ret .= "\n";
254 $ret .= '<form method="post" action="' . $_SERVER["PHP_SELF"] . ($moreparam ? '?' . $moreparam : '') . '">';
255 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
256 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
257 $ret .= '<input type="hidden" name="' . $paramid . '" value="' . $object->id . '">';
258 if (empty($notabletag)) {
259 $ret .= '<table class="nobordernopadding centpercent">';
260 }
261 if (empty($notabletag)) {
262 $ret .= '<tr><td>';
263 }
264 if (preg_match('/^(string|safehtmlstring|email|phone|url)/', $typeofdata)) {
265 $tmp = explode(':', $typeofdata);
266 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($editvalue ? $editvalue : $value) . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
267 } elseif (preg_match('/^(integer)/', $typeofdata)) {
268 $tmp = explode(':', $typeofdata);
269 $valuetoshow = price2num($editvalue ? $editvalue : $value, 0);
270 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . $valuetoshow . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
271 } elseif (preg_match('/^(numeric|amount)/', $typeofdata)) {
272 $tmp = explode(':', $typeofdata);
273 $valuetoshow = price2num($editvalue ? $editvalue : $value);
274 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($valuetoshow != '' ? price($valuetoshow) : '') . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
275 } elseif (preg_match('/^(checkbox)/', $typeofdata)) {
276 $tmp = explode(':', $typeofdata);
277 $ret .= '<input type="checkbox" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($value ? $value : 'on') . '"' . ($value ? ' checked' : '') . (empty($tmp[1]) ? '' : $tmp[1]) . '/>';
278 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) { // if wysiwyg is enabled $typeofdata = 'ckeditor'
279 $tmp = explode(':', $typeofdata);
280 $cols = (empty($tmp[2]) ? '' : $tmp[2]);
281 $morealt = '';
282 if (preg_match('/%/', $cols)) {
283 $morealt = ' style="width: ' . $cols . '"';
284 $cols = '';
285 }
286 $valuetoshow = ($editvalue ? $editvalue : $value);
287 $ret .= '<textarea id="' . $htmlname . '" name="' . $htmlname . '" wrap="soft" rows="' . (empty($tmp[1]) ? '20' : $tmp[1]) . '"' . ($cols ? ' cols="' . $cols . '"' : 'class="quatrevingtpercent"') . $morealt . '" autofocus>';
288 // textarea convert automatically entities chars into simple chars.
289 // So we convert & into &amp; so a string like 'a &lt; <b>b</b><br>é<br>&lt;script&gt;alert('X');&lt;script&gt;' stay a correct html and is not converted by textarea component when wysiwig is off.
290 $valuetoshow = str_replace('&', '&amp;', $valuetoshow);
291 $ret .= dol_htmlwithnojs(dol_string_neverthesehtmltags($valuetoshow, array('textarea')));
292 $ret .= '</textarea>';
293 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
294 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
295 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
296 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
297 $ret .= $this->selectDate($value, $htmlname, 0, 0, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
298 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
299 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
300 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
301 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
302 $ret .= $this->selectDate($value, $htmlname, 1, 1, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
303 } elseif (preg_match('/^select;/', $typeofdata)) {
304 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
305 $arraylist = array();
306 foreach ($arraydata as $val) {
307 $tmp = explode(':', $val);
308 $tmpkey = str_replace('|', ':', $tmp[0]);
309 $arraylist[$tmpkey] = $tmp[1];
310 }
311 $ret .= $this->selectarray($htmlname, $arraylist, $value);
312 } elseif (preg_match('/^link/', $typeofdata)) {
313 // TODO Not yet implemented. See code for extrafields
314 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
315 $tmp = explode(':', $typeofdata); // Example: ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols:uselocalbrowser
316 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
317 $doleditor = new DolEditor($htmlname, ($editvalue ? $editvalue : $value), (empty($tmp[2]) ? '' : $tmp[2]), (empty($tmp[3]) ? '100' : $tmp[3]), (empty($tmp[1]) ? 'dolibarr_notes' : $tmp[1]), 'In', (empty($tmp[5]) ? 0 : $tmp[5]), (isset($tmp[8]) ? ($tmp[8] ? true : false) : true), true, (empty($tmp[6]) ? '20' : $tmp[6]), (empty($tmp[7]) ? '100' : $tmp[7]));
318 $ret .= $doleditor->Create(1);
319 } elseif ($typeofdata == 'asis') {
320 $ret .= ($editvalue ? $editvalue : $value);
321 }
322 if (empty($notabletag)) {
323 $ret .= '</td>';
324 }
325
326 // Button save-cancel
327 if (empty($notabletag)) {
328 $ret .= '<td>';
329 }
330 //else $ret.='<div class="clearboth"></div>';
331 $ret .= '<input type="submit" class="smallpaddingimp button' . (empty($notabletag) ? '' : ' ') . '" name="modify" value="' . $langs->trans("Modify") . '">';
332 if (preg_match('/ckeditor|textarea/', $typeofdata) && empty($notabletag)) {
333 $ret .= '<br>' . "\n";
334 }
335 $ret .= '<input type="submit" class="smallpaddingimp button button-cancel' . (empty($notabletag) ? '' : ' ') . '" name="cancel" value="' . $langs->trans("Cancel") . '">';
336 if (empty($notabletag)) {
337 $ret .= '</td>';
338 }
339
340 if (empty($notabletag)) {
341 $ret .= '</tr></table>' . "\n";
342 }
343 $ret .= '</form>' . "\n";
344 } else { // view mode
345 if (preg_match('/^email/', $typeofdata)) {
346 $ret .= dol_print_email($value, 0, 0, 0, 0, 1);
347 } elseif (preg_match('/^phone/', $typeofdata)) {
348 $ret .= dol_print_phone($value, '_blank', 32, 1);
349 } elseif (preg_match('/^url/', $typeofdata)) {
350 $ret .= dol_print_url($value, '_blank', 32, 1);
351 } elseif (preg_match('/^(amount|numeric)/', $typeofdata)) {
352 $ret .= ($value != '' ? price($value, '', $langs, 0, -1, -1, $conf->currency) : '');
353 } elseif (preg_match('/^checkbox/', $typeofdata)) {
354 $tmp = explode(':', $typeofdata);
355 $ret .= '<input type="checkbox" disabled id="' . $htmlname . '" name="' . $htmlname . '" value="' . $value . '"' . ($value ? ' checked' : '') . ($tmp[1] ? $tmp[1] : '') . '/>';
356 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) {
358 } elseif (preg_match('/^(safehtmlstring|restricthtml)/', $typeofdata)) { // 'restricthtml' is not an allowed type for editfieldval. Value is 'safehtmlstring'
360 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
361 $ret .= '<span class="valuedate">' . dol_print_date($value, 'day', $gm) . '</span>';
362 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
363 $ret .= '<span class="valuedate">' . dol_print_date($value, 'dayhour', $gm) . '</span>';
364 } elseif (preg_match('/^select;/', $typeofdata)) {
365 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
366 $arraylist = array();
367 foreach ($arraydata as $val) {
368 $tmp = explode(':', $val);
369 $arraylist[$tmp[0]] = $tmp[1];
370 }
371 $ret .= $arraylist[$value];
372 if ($htmlname == 'fk_product_type') {
373 if ($value == 0) {
374 $ret = img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
375 } else {
376 $ret = img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
377 }
378 }
379 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
380 $tmpcontent = dol_htmlentitiesbr($value);
381 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
382 $firstline = preg_replace('/<br>.*/', '', $tmpcontent);
383 $firstline = preg_replace('/[\n\r].*/', '', $firstline);
384 $tmpcontent = $firstline . ((strlen($firstline) != strlen($tmpcontent)) ? '...' : '');
385 }
386 // We dont use dol_escape_htmltag to get the html formating active, but this need we must also
387 // clean data from some dangerous html
389 } else {
390 if (empty($moreoptions['valuealreadyhtmlescaped'])) {
391 $ret .= dol_escape_htmltag($value);
392 } else {
393 $ret .= $value; // $value must be already html escaped.
394 }
395 }
396
397 // Custom format if parameter $formatfunc has been provided
398 if ($formatfunc && method_exists($object, $formatfunc)) {
399 $ret = $object->$formatfunc($ret);
400 }
401 }
402 }
403 return $ret;
404 }
405
417 public function widgetForTranslation($fieldname, $object, $perm, $typeofdata = 'string', $check = '', $morecss = '')
418 {
419 global $conf, $langs, $extralanguages;
420
421 $result = '';
422
423 // List of extra languages
424 $arrayoflangcode = array();
425 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
426 $arrayoflangcode[] = $conf->global->PDF_USE_ALSO_LANGUAGE_CODE;
427 }
428
429 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
430 if (!is_object($extralanguages)) {
431 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
432 $extralanguages = new ExtraLanguages($this->db);
433 }
434 $extralanguages->fetch_name_extralanguages('societe');
435
436 if (!is_array($extralanguages->attributes[$object->element]) || empty($extralanguages->attributes[$object->element][$fieldname])) {
437 return ''; // No extralang field to show
438 }
439
440 $result .= '<!-- Widget for translation -->' . "\n";
441 $result .= '<div class="inline-block paddingleft image-' . $object->element . '-' . $fieldname . '">';
442 $s = img_picto($langs->trans("ShowOtherLanguages"), 'language', '', false, 0, 0, '', 'fa-15 editfieldlang');
443 $result .= $s;
444 $result .= '</div>';
445
446 $result .= '<div class="inline-block hidden field-' . $object->element . '-' . $fieldname . '">';
447
448 $resultforextrlang = '';
449 foreach ($arrayoflangcode as $langcode) {
450 $valuetoshow = GETPOSTISSET('field-' . $object->element . "-" . $fieldname . "-" . $langcode) ? GETPOST('field-' . $object->element . '-' . $fieldname . "-" . $langcode, $check) : '';
451 if (empty($valuetoshow)) {
452 $object->fetchValuesForExtraLanguages();
453 //var_dump($object->array_languages);
454 $valuetoshow = $object->array_languages[$fieldname][$langcode];
455 }
456
457 $s = picto_from_langcode($langcode, 'class="pictoforlang paddingright"');
458 $resultforextrlang .= $s;
459
460 // TODO Use the showInputField() method of ExtraLanguages object
461 if ($typeofdata == 'textarea') {
462 $resultforextrlang .= '<textarea name="field-' . $object->element . "-" . $fieldname . "-" . $langcode . '" id="' . $fieldname . "-" . $langcode . '" class="' . $morecss . '" rows="' . ROWS_2 . '" wrap="soft">';
463 $resultforextrlang .= $valuetoshow;
464 $resultforextrlang .= '</textarea>';
465 } else {
466 $resultforextrlang .= '<input type="text" class="inputfieldforlang ' . ($morecss ? ' ' . $morecss : '') . '" name="field-' . $object->element . '-' . $fieldname . '-' . $langcode . '" value="' . $valuetoshow . '">';
467 }
468 }
469 $result .= $resultforextrlang;
470
471 $result .= '</div>';
472 $result .= '<script nonce="' . getNonce() . '">$(".image-' . $object->element . '-' . $fieldname . '").click(function() { console.log("Toggle lang widget"); jQuery(".field-' . $object->element . '-' . $fieldname . '").toggle(); });</script>';
473 }
474
475 return $result;
476 }
477
491 protected function editInPlace($object, $value, $htmlname, $condition, $inputType = 'textarea', $editvalue = null, $extObject = null, $custommsg = null)
492 {
493 global $conf;
494
495 $out = '';
496
497 // Check parameters
498 if (preg_match('/^text/', $inputType)) {
499 $value = dol_nl2br($value);
500 } elseif (preg_match('/^numeric/', $inputType)) {
501 $value = price($value);
502 } elseif ($inputType == 'day' || $inputType == 'datepicker') {
503 $value = dol_print_date($value, 'day');
504 }
505
506 if ($condition) {
507 $element = false;
508 $table_element = false;
509 $fk_element = false;
510 $loadmethod = false;
511 $savemethod = false;
512 $ext_element = false;
513 $button_only = false;
514 $inputOption = '';
515 $rows = '';
516 $cols = '';
517
518 if (is_object($object)) {
519 $element = $object->element;
520 $table_element = $object->table_element;
521 $fk_element = $object->id;
522 }
523
524 if (is_object($extObject)) {
525 $ext_element = $extObject->element;
526 }
527
528 if (preg_match('/^(string|email|numeric)/', $inputType)) {
529 $tmp = explode(':', $inputType);
530 $inputType = $tmp[0];
531 if (!empty($tmp[1])) {
532 $inputOption = $tmp[1];
533 }
534 if (!empty($tmp[2])) {
535 $savemethod = $tmp[2];
536 }
537 $out .= '<input id="width_' . $htmlname . '" value="' . $inputOption . '" type="hidden"/>' . "\n";
538 } elseif ((preg_match('/^day$/', $inputType)) || (preg_match('/^datepicker/', $inputType)) || (preg_match('/^datehourpicker/', $inputType))) {
539 $tmp = explode(':', $inputType);
540 $inputType = $tmp[0];
541 if (!empty($tmp[1])) {
542 $inputOption = $tmp[1];
543 }
544 if (!empty($tmp[2])) {
545 $savemethod = $tmp[2];
546 }
547
548 $out .= '<input id="timestamp" type="hidden"/>' . "\n"; // Use for timestamp format
549 } elseif (preg_match('/^(select|autocomplete)/', $inputType)) {
550 $tmp = explode(':', $inputType);
551 $inputType = $tmp[0];
552 $loadmethod = $tmp[1];
553 if (!empty($tmp[2])) {
554 $savemethod = $tmp[2];
555 }
556 if (!empty($tmp[3])) {
557 $button_only = true;
558 }
559 } elseif (preg_match('/^textarea/', $inputType)) {
560 $tmp = explode(':', $inputType);
561 $inputType = $tmp[0];
562 $rows = (empty($tmp[1]) ? '8' : $tmp[1]);
563 $cols = (empty($tmp[2]) ? '80' : $tmp[2]);
564 } elseif (preg_match('/^ckeditor/', $inputType)) {
565 $tmp = explode(':', $inputType);
566 $inputType = $tmp[0];
567 $toolbar = $tmp[1];
568 if (!empty($tmp[2])) {
569 $width = $tmp[2];
570 }
571 if (!empty($tmp[3])) {
572 $heigth = $tmp[3];
573 }
574 if (!empty($tmp[4])) {
575 $savemethod = $tmp[4];
576 }
577
578 if (isModEnabled('fckeditor')) {
579 $out .= '<input id="ckeditor_toolbar" value="' . $toolbar . '" type="hidden"/>' . "\n";
580 } else {
581 $inputType = 'textarea';
582 }
583 }
584
585 $out .= '<input id="element_' . $htmlname . '" value="' . $element . '" type="hidden"/>' . "\n";
586 $out .= '<input id="table_element_' . $htmlname . '" value="' . $table_element . '" type="hidden"/>' . "\n";
587 $out .= '<input id="fk_element_' . $htmlname . '" value="' . $fk_element . '" type="hidden"/>' . "\n";
588 $out .= '<input id="loadmethod_' . $htmlname . '" value="' . $loadmethod . '" type="hidden"/>' . "\n";
589 if (!empty($savemethod)) {
590 $out .= '<input id="savemethod_' . $htmlname . '" value="' . $savemethod . '" type="hidden"/>' . "\n";
591 }
592 if (!empty($ext_element)) {
593 $out .= '<input id="ext_element_' . $htmlname . '" value="' . $ext_element . '" type="hidden"/>' . "\n";
594 }
595 if (!empty($custommsg)) {
596 if (is_array($custommsg)) {
597 if (!empty($custommsg['success'])) {
598 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg['success'] . '" type="hidden"/>' . "\n";
599 }
600 if (!empty($custommsg['error'])) {
601 $out .= '<input id="errormsg_' . $htmlname . '" value="' . $custommsg['error'] . '" type="hidden"/>' . "\n";
602 }
603 } else {
604 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg . '" type="hidden"/>' . "\n";
605 }
606 }
607 if ($inputType == 'textarea') {
608 $out .= '<input id="textarea_' . $htmlname . '_rows" value="' . $rows . '" type="hidden"/>' . "\n";
609 $out .= '<input id="textarea_' . $htmlname . '_cols" value="' . $cols . '" type="hidden"/>' . "\n";
610 }
611 $out .= '<span id="viewval_' . $htmlname . '" class="viewval_' . $inputType . ($button_only ? ' inactive' : ' active') . '">' . $value . '</span>' . "\n";
612 $out .= '<span id="editval_' . $htmlname . '" class="editval_' . $inputType . ($button_only ? ' inactive' : ' active') . ' hideobject">' . (!empty($editvalue) ? $editvalue : $value) . '</span>' . "\n";
613 } else {
614 $out = $value;
615 }
616
617 return $out;
618 }
619
638 public function textwithtooltip($text, $htmltext, $tooltipon = 1, $direction = 0, $img = '', $extracss = '', $notabs = 3, $incbefore = '', $noencodehtmltext = 0, $tooltiptrigger = '', $forcenowrap = 0)
639 {
640 if ($incbefore) {
641 $text = $incbefore . $text;
642 }
643 if (!$htmltext) {
644 return $text;
645 }
646 $direction = (int) $direction; // For backward compatibility when $direction was set to '' instead of 0
647
648 $tag = 'td';
649 if ($notabs == 2) {
650 $tag = 'div';
651 }
652 if ($notabs == 3) {
653 $tag = 'span';
654 }
655 // Sanitize tooltip
656 $htmltext = str_replace(array("\r", "\n"), '', $htmltext);
657
658 $extrastyle = '';
659 if ($direction < 0) {
660 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
661 $extrastyle = 'padding: 0px; padding-left: 3px;';
662 }
663 if ($direction > 0) {
664 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
665 $extrastyle = 'padding: 0px; padding-right: 3px;';
666 }
667
668 $classfortooltip = 'classfortooltip';
669
670 $s = '';
671 $textfordialog = '';
672
673 if ($tooltiptrigger == '') {
674 $htmltext = str_replace('"', '&quot;', $htmltext);
675 } else {
676 $classfortooltip = 'classfortooltiponclick';
677 $textfordialog .= '<div style="display: none;" id="idfortooltiponclick_' . $tooltiptrigger . '" class="classfortooltiponclicktext">' . $htmltext . '</div>';
678 }
679 if ($tooltipon == 2 || $tooltipon == 3) {
680 $paramfortooltipimg = ' class="' . $classfortooltip . ($notabs != 3 ? ' inline-block' : '') . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '"';
681 if ($tooltiptrigger == '') {
682 $paramfortooltipimg .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribut to put on img tag to store tooltip
683 } else {
684 $paramfortooltipimg .= ' dolid="' . $tooltiptrigger . '"';
685 }
686 } else {
687 $paramfortooltipimg = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribut to put on td text tag
688 }
689 if ($tooltipon == 1 || $tooltipon == 3) {
690 $paramfortooltiptd = ' class="' . ($tooltipon == 3 ? 'cursorpointer ' : '') . $classfortooltip . ' inline-block' . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '" ';
691 if ($tooltiptrigger == '') {
692 $paramfortooltiptd .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribut to put on td tag to store tooltip
693 } else {
694 $paramfortooltiptd .= ' dolid="' . $tooltiptrigger . '"';
695 }
696 } else {
697 $paramfortooltiptd = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribut to put on td text tag
698 }
699 if (empty($notabs)) {
700 $s .= '<table class="nobordernopadding"><tr style="height: auto;">';
701 } elseif ($notabs == 2) {
702 $s .= '<div class="inline-block' . ($forcenowrap ? ' nowrap' : '') . '">';
703 }
704 // Define value if value is before
705 if ($direction < 0) {
706 $s .= '<' . $tag . $paramfortooltipimg;
707 if ($tag == 'td') {
708 $s .= ' class="valigntop" width="14"';
709 }
710 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
711 }
712 // Use another method to help avoid having a space in value in order to use this value with jquery
713 // Define label
714 if ((string) $text != '') {
715 $s .= '<' . $tag . $paramfortooltiptd . '>' . $text . '</' . $tag . '>';
716 }
717 // Define value if value is after
718 if ($direction > 0) {
719 $s .= '<' . $tag . $paramfortooltipimg;
720 if ($tag == 'td') {
721 $s .= ' class="valignmiddle" width="14"';
722 }
723 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
724 }
725 if (empty($notabs)) {
726 $s .= '</tr></table>';
727 } elseif ($notabs == 2) {
728 $s .= '</div>';
729 }
730
731 return $s;
732 }
733
748 public function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 3, $tooltiptrigger = '', $forcenowrap = 0)
749 {
750 global $conf, $langs;
751
752 //For backwards compatibility
753 if ($type == '0') {
754 $type = 'info';
755 } elseif ($type == '1') {
756 $type = 'help';
757 }
758 // Clean parameters
759 $tooltiptrigger = preg_replace('/[^a-z0-9]/i', '', $tooltiptrigger);
760
761 if (preg_match('/onsmartphone$/', $tooltiptrigger) && empty($conf->dol_no_mouse_hover)) {
762 $tooltiptrigger = preg_replace('/^.*onsmartphone$/', '', $tooltiptrigger);
763 }
764 $alt = '';
765 if ($tooltiptrigger) {
766 $alt = $langs->transnoentitiesnoconv("ClickToShowHelp");
767 }
768
769 // If info or help with no javascript, show only text
770 if (empty($conf->use_javascript_ajax)) {
771 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
772 return $text;
773 } else {
774 $alt = $htmltext;
775 $htmltext = '';
776 }
777 }
778
779 // If info or help with smartphone, show only text (tooltip hover can't works)
780 if (!empty($conf->dol_no_mouse_hover) && empty($tooltiptrigger)) {
781 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
782 return $text;
783 }
784 }
785 // If info or help with smartphone, show only text (tooltip on click does not works with dialog on smaprtphone)
786 //if (!empty($conf->dol_no_mouse_hover) && !empty($tooltiptrigger))
787 //{
788 //if ($type == 'info' || $type == 'help') return '<a href="'..'">'.$text.'</a>';
789 //}
790
791 $img = '';
792 if ($type == 'info') {
793 $img = img_help(0, $alt);
794 } elseif ($type == 'help') {
795 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
796 } elseif ($type == 'helpclickable') {
797 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
798 } elseif ($type == 'superadmin') {
799 $img = img_picto($alt, 'redstar');
800 } elseif ($type == 'admin') {
801 $img = img_picto($alt, 'star');
802 } elseif ($type == 'warning') {
803 $img = img_warning($alt);
804 } elseif ($type != 'none') {
805 $img = img_picto($alt, $type); // $type can be an image path
806 }
807
808 return $this->textwithtooltip($text, $htmltext, ((($tooltiptrigger && !$img) || strpos($type, 'clickable')) ? 3 : 2), $direction, $img, $extracss, $notabs, '', $noencodehtmltext, $tooltiptrigger, $forcenowrap);
809 }
810
821 public function selectMassAction($selected, $arrayofaction, $alwaysvisible = 0, $name = 'massaction', $cssclass = 'checkforselect')
822 {
823 global $conf, $langs, $hookmanager;
824
825 $disabled = 0;
826 $ret = '<div class="centpercent center">';
827 $ret .= '<select class="flat' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'select valignmiddle alignstart" id="' . $name . '" name="' . $name . '"' . ($disabled ? ' disabled="disabled"' : '') . '>';
828
829 // Complete list with data from external modules. THe module can use $_SERVER['PHP_SELF'] to know on which page we are, or use the $parameters['currentcontext'] completed by executeHooks.
830 $parameters = array();
831 $reshook = $hookmanager->executeHooks('addMoreMassActions', $parameters); // Note that $action and $object may have been modified by hook
832 // check if there is a mass action
833
834 if (is_array($arrayofaction) && count($arrayofaction) == 0 && empty($hookmanager->resPrint)) {
835 return;
836 }
837 if (empty($reshook)) {
838 $ret .= '<option value="0"' . ($disabled ? ' disabled="disabled"' : '') . '>-- ' . $langs->trans("SelectAction") . ' --</option>';
839 if (is_array($arrayofaction)) {
840 foreach ($arrayofaction as $code => $label) {
841 $ret .= '<option value="' . $code . '"' . ($disabled ? ' disabled="disabled"' : '') . ' data-html="' . dol_escape_htmltag($label) . '">' . $label . '</option>';
842 }
843 }
844 }
845 $ret .= $hookmanager->resPrint;
846
847 $ret .= '</select>';
848
849 if (empty($conf->dol_optimize_smallscreen)) {
850 $ret .= ajax_combobox('.' . $name . 'select');
851 }
852
853 // Warning: if you set submit button to disabled, post using 'Enter' will no more work if there is no another input submit. So we add a hidden button
854 $ret .= '<input type="submit" name="confirmmassactioninvisible" style="display: none" tabindex="-1">'; // Hidden button BEFORE so it is the one used when we submit with ENTER.
855 $ret .= '<input type="submit" disabled name="confirmmassaction"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display: none"') . ' class="reposition button smallpaddingimp' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'confirmed" value="' . dol_escape_htmltag($langs->trans("Confirm")) . '">';
856 $ret .= '</div>';
857
858 if (!empty($conf->use_javascript_ajax)) {
859 $ret .= '<!-- JS CODE TO ENABLE mass action select -->
860 <script nonce="' . getNonce() . '">
861 function initCheckForSelect(mode, name, cssclass) /* mode is 0 during init of page or click all, 1 when we click on 1 checkboxi, "name" refers to the class of the massaction button, "cssclass" to the class of the checkfor select boxes */
862 {
863 atleastoneselected=0;
864 jQuery("."+cssclass).each(function( index ) {
865 /* console.log( index + ": " + $( this ).text() ); */
866 if ($(this).is(\':checked\')) atleastoneselected++;
867 });
868
869 console.log("initCheckForSelect mode="+mode+" name="+name+" cssclass="+cssclass+" atleastoneselected="+atleastoneselected);
870
871 if (atleastoneselected || ' . $alwaysvisible . ')
872 {
873 jQuery("."+name).show();
874 ' . ($selected ? 'if (atleastoneselected) { jQuery("."+name+"select").val("' . $selected . '").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', false); }' : '') . '
875 ' . ($selected ? 'if (! atleastoneselected) { jQuery("."+name+"select").val("0").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', true); } ' : '') . '
876 }
877 else
878 {
879 jQuery("."+name).hide();
880 jQuery("."+name+"other").hide();
881 }
882 }
883
884 jQuery(document).ready(function () {
885 initCheckForSelect(0, "' . $name . '", "' . $cssclass . '");
886 jQuery(".' . $cssclass . '").click(function() {
887 initCheckForSelect(1, "' . $name . '", "' . $cssclass . '");
888 });
889 jQuery(".' . $name . 'select").change(function() {
890 var massaction = $( this ).val();
891 var urlform = $( this ).closest("form").attr("action").replace("#show_files","");
892 if (massaction == "builddoc")
893 {
894 urlform = urlform + "#show_files";
895 }
896 $( this ).closest("form").attr("action", urlform);
897 console.log("we select a mass action name=' . $name . ' massaction="+massaction+" - "+urlform);
898 /* Warning: if you set submit button to disabled, post using Enter will no more work if there is no other button */
899 if ($(this).val() != \'0\')
900 {
901 jQuery(".' . $name . 'confirmed").prop(\'disabled\', false);
902 jQuery(".' . $name . 'other").hide(); /* To disable if another div was open */
903 jQuery(".' . $name . '"+massaction).show();
904 }
905 else
906 {
907 jQuery(".' . $name . 'confirmed").prop(\'disabled\', true);
908 jQuery(".' . $name . 'other").hide(); /* To disable any div open */
909 }
910 });
911 });
912 </script>
913 ';
914 }
915
916 return $ret;
917 }
918
919 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
920
937 public function select_country($selected = '', $htmlname = 'country_id', $htmloption = '', $maxlength = 0, $morecss = 'minwidth300', $usecodeaskey = '', $showempty = 1, $disablefavorites = 0, $addspecialentries = 0, $exclude_country_code = array(), $hideflags = 0)
938 {
939 // phpcs:enable
940 global $conf, $langs, $mysoc;
941
942 $langs->load("dict");
943
944 $out = '';
945 $countryArray = array();
946 $favorite = array();
947 $label = array();
948 $atleastonefavorite = 0;
949
950 $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite, eec";
951 $sql .= " FROM " . $this->db->prefix() . "c_country";
952 $sql .= " WHERE active > 0";
953 //$sql.= " ORDER BY code ASC";
954
955 dol_syslog(get_class($this) . "::select_country", LOG_DEBUG);
956 $resql = $this->db->query($sql);
957 if ($resql) {
958 $out .= '<select id="select' . $htmlname . '" class="flat maxwidth200onsmartphone selectcountry' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" ' . $htmloption . '>';
959 $num = $this->db->num_rows($resql);
960 $i = 0;
961 if ($num) {
962 while ($i < $num) {
963 $obj = $this->db->fetch_object($resql);
964
965 $countryArray[$i]['rowid'] = $obj->rowid;
966 $countryArray[$i]['code_iso'] = $obj->code_iso;
967 $countryArray[$i]['code_iso3'] = $obj->code_iso3;
968 $countryArray[$i]['label'] = ($obj->code_iso && $langs->transnoentitiesnoconv("Country" . $obj->code_iso) != "Country" . $obj->code_iso ? $langs->transnoentitiesnoconv("Country" . $obj->code_iso) : ($obj->label != '-' ? $obj->label : ''));
969 $countryArray[$i]['favorite'] = $obj->favorite;
970 $countryArray[$i]['eec'] = $obj->eec;
971 $favorite[$i] = $obj->favorite;
972 $label[$i] = dol_string_unaccent($countryArray[$i]['label']);
973 $i++;
974 }
975
976 if (empty($disablefavorites)) {
977 $array1_sort_order = SORT_DESC;
978 $array2_sort_order = SORT_ASC;
979 array_multisort($favorite, $array1_sort_order, $label, $array2_sort_order, $countryArray);
980 } else {
981 $countryArray = dol_sort_array($countryArray, 'label');
982 }
983
984 if ($showempty) {
985 if (is_numeric($showempty)) {
986 $out .= '<option value="">&nbsp;</option>' . "\n";
987 } else {
988 $out .= '<option value="-1">' . $langs->trans($showempty) . '</option>' . "\n";
989 }
990 }
991
992 if ($addspecialentries) { // Add dedicated entries for groups of countries
993 //if ($showempty) $out.= '<option value="" disabled class="selectoptiondisabledwhite">--------------</option>';
994 $out .= '<option value="special_allnotme"' . ($selected == 'special_allnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
995 $out .= '<option value="special_eec"' . ($selected == 'special_eec' ? ' selected' : '') . '>' . $langs->trans("CountriesInEEC") . '</option>';
996 if ($mysoc->isInEEC()) {
997 $out .= '<option value="special_eecnotme"' . ($selected == 'special_eecnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesInEECExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
998 }
999 $out .= '<option value="special_noteec"' . ($selected == 'special_noteec' ? ' selected' : '') . '>' . $langs->trans("CountriesNotInEEC") . '</option>';
1000 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1001 }
1002
1003 foreach ($countryArray as $row) {
1004 //if (empty($showempty) && empty($row['rowid'])) continue;
1005 if (empty($row['rowid'])) {
1006 continue;
1007 }
1008 if (is_array($exclude_country_code) && count($exclude_country_code) && in_array($row['code_iso'], $exclude_country_code)) {
1009 continue; // exclude some countries
1010 }
1011
1012 if (empty($disablefavorites) && $row['favorite'] && $row['code_iso']) {
1013 $atleastonefavorite++;
1014 }
1015 if (empty($row['favorite']) && $atleastonefavorite) {
1016 $atleastonefavorite = 0;
1017 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1018 }
1019
1020 $labeltoshow = '';
1021 if ($row['label']) {
1022 $labeltoshow .= dol_trunc($row['label'], $maxlength, 'middle');
1023 } else {
1024 $labeltoshow .= '&nbsp;';
1025 }
1026 if ($row['code_iso']) {
1027 $labeltoshow .= ' <span class="opacitymedium">(' . $row['code_iso'] . ')</span>';
1028 if (empty($hideflags)) {
1029 $tmpflag = picto_from_langcode($row['code_iso'], 'class="saturatemedium paddingrightonly"', 1);
1030 $labeltoshow = $tmpflag . ' ' . $labeltoshow;
1031 }
1032 }
1033
1034 if ($selected && $selected != '-1' && ($selected == $row['rowid'] || $selected == $row['code_iso'] || $selected == $row['code_iso3'] || $selected == $row['label'])) {
1035 $out .= '<option value="' . ($usecodeaskey ? ($usecodeaskey == 'code2' ? $row['code_iso'] : $row['code_iso3']) : $row['rowid']) . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '" data-eec="' . ((int) $row['eec']) . '">';
1036 } else {
1037 $out .= '<option value="' . ($usecodeaskey ? ($usecodeaskey == 'code2' ? $row['code_iso'] : $row['code_iso3']) : $row['rowid']) . '" data-html="' . dol_escape_htmltag($labeltoshow) . '" data-eec="' . ((int) $row['eec']) . '">';
1038 }
1039 $out .= $labeltoshow;
1040 $out .= '</option>' . "\n";
1041 }
1042 }
1043 $out .= '</select>';
1044 } else {
1045 dol_print_error($this->db);
1046 }
1047
1048 // Make select dynamic
1049 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1050 $out .= ajax_combobox('select' . $htmlname, array(), 0, 0, 'resolve');
1051
1052 return $out;
1053 }
1054
1055 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1056
1070 public function select_incoterms($selected = '', $location_incoterms = '', $page = '', $htmlname = 'incoterm_id', $htmloption = '', $forcecombo = 1, $events = array(), $disableautocomplete = 0)
1071 {
1072 // phpcs:enable
1073 global $conf, $langs;
1074
1075 $langs->load("dict");
1076
1077 $out = '';
1078 $moreattrib = '';
1079 $incotermArray = array();
1080
1081 $sql = "SELECT rowid, code";
1082 $sql .= " FROM " . $this->db->prefix() . "c_incoterms";
1083 $sql .= " WHERE active > 0";
1084 $sql .= " ORDER BY code ASC";
1085
1086 dol_syslog(get_class($this) . "::select_incoterm", LOG_DEBUG);
1087 $resql = $this->db->query($sql);
1088 if ($resql) {
1089 if ($conf->use_javascript_ajax && !$forcecombo) {
1090 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1091 $out .= ajax_combobox($htmlname, $events);
1092 }
1093
1094 if (!empty($page)) {
1095 $out .= '<form method="post" action="' . $page . '">';
1096 $out .= '<input type="hidden" name="action" value="set_incoterms">';
1097 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
1098 }
1099
1100 $out .= '<select id="' . $htmlname . '" class="flat selectincoterm width75" name="' . $htmlname . '" ' . $htmloption . '>';
1101 $out .= '<option value="0">&nbsp;</option>';
1102 $num = $this->db->num_rows($resql);
1103 $i = 0;
1104 if ($num) {
1105 while ($i < $num) {
1106 $obj = $this->db->fetch_object($resql);
1107 $incotermArray[$i]['rowid'] = $obj->rowid;
1108 $incotermArray[$i]['code'] = $obj->code;
1109 $i++;
1110 }
1111
1112 foreach ($incotermArray as $row) {
1113 if ($selected && ($selected == $row['rowid'] || $selected == $row['code'])) {
1114 $out .= '<option value="' . $row['rowid'] . '" selected>';
1115 } else {
1116 $out .= '<option value="' . $row['rowid'] . '">';
1117 }
1118
1119 if ($row['code']) {
1120 $out .= $row['code'];
1121 }
1122
1123 $out .= '</option>';
1124 }
1125 }
1126 $out .= '</select>';
1127
1128 if ($conf->use_javascript_ajax && empty($disableautocomplete)) {
1129 $out .= ajax_multiautocompleter('location_incoterms', array(), DOL_URL_ROOT . '/core/ajax/locationincoterms.php') . "\n";
1130 $moreattrib .= ' autocomplete="off"';
1131 }
1132 $out .= '<input id="location_incoterms" class="maxwidthonsmartphone type="text" name="location_incoterms" value="' . $location_incoterms . '">' . "\n";
1133
1134 if (!empty($page)) {
1135 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp nomargintop nomarginbottom" value="' . $langs->trans("Modify") . '"></form>';
1136 }
1137 } else {
1138 dol_print_error($this->db);
1139 }
1140
1141 return $out;
1142 }
1143
1144 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1145
1157 public function select_type_of_lines($selected = '', $htmlname = 'type', $showempty = 0, $hidetext = 0, $forceall = 0)
1158 {
1159 // phpcs:enable
1160 global $langs;
1161
1162 // If product & services are enabled or both disabled.
1163 if ($forceall == 1 || (empty($forceall) && isModEnabled("product") && isModEnabled("service"))
1164 || (empty($forceall) && !isModEnabled('product') && !isModEnabled('service'))) {
1165 if (empty($hidetext)) {
1166 print $langs->trans("Type") . ': ';
1167 }
1168 print '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
1169 if ($showempty) {
1170 print '<option value="-1"';
1171 if ($selected == -1) {
1172 print ' selected';
1173 }
1174 print '>&nbsp;</option>';
1175 }
1176
1177 print '<option value="0"';
1178 if (0 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'product')) {
1179 print ' selected';
1180 }
1181 print '>' . $langs->trans("Product");
1182
1183 print '<option value="1"';
1184 if (1 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'service')) {
1185 print ' selected';
1186 }
1187 print '>' . $langs->trans("Service");
1188
1189 print '</select>';
1190 print ajax_combobox('select_' . $htmlname);
1191 //if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1192 }
1193 if ((empty($forceall) && !isModEnabled('product') && isModEnabled("service")) || $forceall == 3) {
1194 print $langs->trans("Service");
1195 print '<input type="hidden" name="' . $htmlname . '" value="1">';
1196 }
1197 if ((empty($forceall) && isModEnabled("product") && !isModEnabled('service')) || $forceall == 2) {
1198 print $langs->trans("Product");
1199 print '<input type="hidden" name="' . $htmlname . '" value="0">';
1200 }
1201 if ($forceall < 0) { // This should happened only for contracts when both predefined product and service are disabled.
1202 print '<input type="hidden" name="' . $htmlname . '" value="1">'; // By default we set on service for contract. If CONTRACT_SUPPORT_PRODUCTS is set, forceall should be 1 not -1
1203 }
1204 }
1205
1206 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1207
1213 public function load_cache_types_fees()
1214 {
1215 // phpcs:enable
1216 global $langs;
1217
1218 $num = count($this->cache_types_fees);
1219 if ($num > 0) {
1220 return 0; // Cache already loaded
1221 }
1222
1223 dol_syslog(__METHOD__, LOG_DEBUG);
1224
1225 $langs->load("trips");
1226
1227 $sql = "SELECT c.code, c.label";
1228 $sql .= " FROM " . $this->db->prefix() . "c_type_fees as c";
1229 $sql .= " WHERE active > 0";
1230
1231 $resql = $this->db->query($sql);
1232 if ($resql) {
1233 $num = $this->db->num_rows($resql);
1234 $i = 0;
1235
1236 while ($i < $num) {
1237 $obj = $this->db->fetch_object($resql);
1238
1239 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
1240 $label = ($obj->code != $langs->trans($obj->code) ? $langs->trans($obj->code) : $langs->trans($obj->label));
1241 $this->cache_types_fees[$obj->code] = $label;
1242 $i++;
1243 }
1244
1245 asort($this->cache_types_fees);
1246
1247 return $num;
1248 } else {
1249 dol_print_error($this->db);
1250 return -1;
1251 }
1252 }
1253
1254 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1255
1264 public function select_type_fees($selected = '', $htmlname = 'type', $showempty = 0)
1265 {
1266 // phpcs:enable
1267 global $user, $langs;
1268
1269 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
1270
1271 $this->load_cache_types_fees();
1272
1273 print '<select id="select_' . $htmlname . '" class="flat" name="' . $htmlname . '">';
1274 if ($showempty) {
1275 print '<option value="-1"';
1276 if ($selected == -1) {
1277 print ' selected';
1278 }
1279 print '>&nbsp;</option>';
1280 }
1281
1282 foreach ($this->cache_types_fees as $key => $value) {
1283 print '<option value="' . $key . '"';
1284 if ($key == $selected) {
1285 print ' selected';
1286 }
1287 print '>';
1288 print $value;
1289 print '</option>';
1290 }
1291
1292 print '</select>';
1293 if ($user->admin) {
1294 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1295 }
1296 }
1297
1298
1299 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1300
1322 public function select_company($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $limit = 0, $morecss = 'minwidth100', $moreparam = '', $selected_input_value = '', $hidelabel = 1, $ajaxoptions = array(), $multiple = false, $excludeids = array(), $showcode = 0)
1323 {
1324 // phpcs:enable
1325 global $conf, $user, $langs;
1326
1327 $out = '';
1328
1329 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT') && !$forcecombo) {
1330 if (is_null($ajaxoptions)) {
1331 $ajaxoptions = array();
1332 }
1333
1334 require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1335
1336 // No immediate load of all database
1337 $placeholder = '';
1338 if ($selected && empty($selected_input_value)) {
1339 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1340 $societetmp = new Societe($this->db);
1341 $societetmp->fetch($selected);
1342 $selected_input_value = $societetmp->name;
1343 unset($societetmp);
1344 }
1345
1346 // mode 1
1347 $urloption = 'htmlname=' . urlencode(str_replace('.', '_', $htmlname)) . '&outjson=1&filter=' . urlencode($filter) . (empty($excludeids) ? '' : '&excludeids=' . join(',', $excludeids)) . ($showtype ? '&showtype=' . urlencode($showtype) : '') . ($showcode ? '&showcode=' . urlencode($showcode) : '');
1348
1349 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
1350 if (empty($hidelabel)) {
1351 print $langs->trans("RefOrLabel") . ' : ';
1352 } elseif ($hidelabel > 1) {
1353 $placeholder = $langs->trans("RefOrLabel");
1354 if ($hidelabel == 2) {
1355 $out .= img_picto($langs->trans("Search"), 'search');
1356 }
1357 }
1358 $out .= '<input type="text" class="' . $morecss . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '') . ' ' . (getDolGlobalString('THIRDPARTY_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
1359 if ($hidelabel == 3) {
1360 $out .= img_picto($langs->trans("Search"), 'search');
1361 }
1362
1363 $out .= ajax_event($htmlname, $events);
1364
1365 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/societe/ajax/company.php', $urloption, $conf->global->COMPANY_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
1366 } else {
1367 // Immediate load of all database
1368 $out .= $this->select_thirdparty_list($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, '', 0, $limit, $morecss, $moreparam, $multiple, $excludeids, $showcode);
1369 }
1370
1371 return $out;
1372 }
1373
1374 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1375
1399 public function select_thirdparty_list($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $filterkey = '', $outputmode = 0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $multiple = false, $excludeids = array(), $showcode = 0)
1400 {
1401 // phpcs:enable
1402 global $conf, $user, $langs;
1403 global $hookmanager;
1404
1405 $out = '';
1406 $num = 0;
1407 $outarray = array();
1408
1409 if ($selected === '') {
1410 $selected = array();
1411 } elseif (!is_array($selected)) {
1412 $selected = array($selected);
1413 }
1414
1415 // Clean $filter that may contains sql conditions so sql code
1416 if (function_exists('testSqlAndScriptInject')) {
1417 if (testSqlAndScriptInject($filter, 3) > 0) {
1418 $filter = '';
1419 return 'SQLInjectionTryDetected';
1420 }
1421 }
1422
1423 if ($filter != '') { // If a filter was provided
1424 if (preg_match('/[\‍(\‍)]/', $filter)) {
1425 // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax.
1426 $errormsg = '';
1427 $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1);
1428
1429 // Redo clean $filter that may contains sql conditions so sql code
1430 if (function_exists('testSqlAndScriptInject')) {
1431 if (testSqlAndScriptInject($filter, 3) > 0) {
1432 $filter = '';
1433 return 'SQLInjectionTryDetected';
1434 }
1435 }
1436 } else {
1437 // If not, we do nothing. We already know that there is no parenthesis
1438 // TODO Disallow this case in a future.
1439 dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Syntax.", LOG_WARNING);
1440 }
1441 }
1442
1443 // We search companies
1444 $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.tva_intra, s.client, s.fournisseur, s.code_client, s.code_fournisseur";
1445 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1446 $sql .= ", s.address, s.zip, s.town";
1447 $sql .= ", dictp.code as country_code";
1448 }
1449 $sql .= " FROM " . $this->db->prefix() . "societe as s";
1450 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1451 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_country as dictp ON dictp.rowid = s.fk_pays";
1452 }
1453 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
1454 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
1455 }
1456 $sql .= " WHERE s.entity IN (" . getEntity('societe') . ")";
1457 if (!empty($user->socid)) {
1458 $sql .= " AND s.rowid = " . ((int) $user->socid);
1459 }
1460 if ($filter) {
1461 // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria()
1462 // if not, by testSqlAndScriptInject() only.
1463 $sql .= " AND (" . $filter . ")";
1464 }
1465 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
1466 $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
1467 }
1468 if (getDolGlobalString('COMPANY_HIDE_INACTIVE_IN_COMBOBOX')) {
1469 $sql .= " AND s.status <> 0";
1470 }
1471 if (!empty($excludeids)) {
1472 $sql .= " AND s.rowid NOT IN (" . $this->db->sanitize(join(',', $excludeids)) . ")";
1473 }
1474 // Add where from hooks
1475 $parameters = array();
1476 $reshook = $hookmanager->executeHooks('selectThirdpartyListWhere', $parameters); // Note that $action and $object may have been modified by hook
1477 $sql .= $hookmanager->resPrint;
1478 // Add criteria
1479 if ($filterkey && $filterkey != '') {
1480 $sql .= " AND (";
1481 $prefix = !getDolGlobalString('COMPANY_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if COMPANY_DONOTSEARCH_ANYWHERE is on
1482 // For natural search
1483 $scrit = explode(' ', $filterkey);
1484 $i = 0;
1485 if (count($scrit) > 1) {
1486 $sql .= "(";
1487 }
1488 foreach ($scrit as $crit) {
1489 if ($i > 0) {
1490 $sql .= " AND ";
1491 }
1492 $sql .= "(s.nom LIKE '" . $this->db->escape($prefix . $crit) . "%')";
1493 $i++;
1494 }
1495 if (count($scrit) > 1) {
1496 $sql .= ")";
1497 }
1498 if (isModEnabled('barcode')) {
1499 $sql .= " OR s.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1500 }
1501 $sql .= " OR s.code_client LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.code_fournisseur LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1502 $sql .= " OR s.name_alias LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.tva_intra LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1503 $sql .= ")";
1504 }
1505 $sql .= $this->db->order("nom", "ASC");
1506 $sql .= $this->db->plimit($limit, 0);
1507
1508 // Build output string
1509 dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
1510 $resql = $this->db->query($sql);
1511 if ($resql) {
1512 if (!$forcecombo) {
1513 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1514 $out .= ajax_combobox($htmlname, $events, getDolGlobalString("COMPANY_USE_SEARCH_TO_SELECT"));
1515 }
1516
1517 // Construct $out and $outarray
1518 $out .= '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($moreparam ? ' ' . $moreparam : '') . ' name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . '>' . "\n";
1519
1520 $textifempty = (($showempty && !is_numeric($showempty)) ? $langs->trans($showempty) : '');
1521 if (getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
1522 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
1523 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
1524 if ($showempty && !is_numeric($showempty)) {
1525 $textifempty = $langs->trans($showempty);
1526 } else {
1527 $textifempty .= $langs->trans("All");
1528 }
1529 }
1530 if ($showempty) {
1531 $out .= '<option value="-1" data-html="' . dol_escape_htmltag('<span class="opacitymedium">' . ($textifempty ? $textifempty : '&nbsp;') . '</span>') . '">' . $textifempty . '</option>' . "\n";
1532 }
1533
1534 $companytemp = new Societe($this->db);
1535
1536 $num = $this->db->num_rows($resql);
1537 $i = 0;
1538 if ($num) {
1539 while ($i < $num) {
1540 $obj = $this->db->fetch_object($resql);
1541 $label = '';
1542 if ($showcode || getDolGlobalString('SOCIETE_ADD_REF_IN_LIST')) {
1543 if (($obj->client) && (!empty($obj->code_client))) {
1544 $label = $obj->code_client . ' - ';
1545 }
1546 if (($obj->fournisseur) && (!empty($obj->code_fournisseur))) {
1547 $label .= $obj->code_fournisseur . ' - ';
1548 }
1549 $label .= ' ' . $obj->name;
1550 } else {
1551 $label = $obj->name;
1552 }
1553
1554 if (!empty($obj->name_alias)) {
1555 $label .= ' (' . $obj->name_alias . ')';
1556 }
1557
1558 if (getDolGlobalString('SOCIETE_SHOW_VAT_IN_LIST') && !empty($obj->tva_intra)) {
1559 $label .= ' - '.$obj->tva_intra;
1560 }
1561
1562 $labelhtml = $label;
1563
1564 if ($showtype) {
1565 $companytemp->id = $obj->rowid;
1566 $companytemp->client = $obj->client;
1567 $companytemp->fournisseur = $obj->fournisseur;
1568 $tmptype = $companytemp->getTypeUrl(1, '', 0, 'span');
1569 if ($tmptype) {
1570 $labelhtml .= ' ' . $tmptype;
1571 }
1572
1573 if ($obj->client || $obj->fournisseur) {
1574 $label .= ' (';
1575 }
1576 if ($obj->client == 1 || $obj->client == 3) {
1577 $label .= $langs->trans("Customer");
1578 }
1579 if ($obj->client == 2 || $obj->client == 3) {
1580 $label .= ($obj->client == 3 ? ', ' : '') . $langs->trans("Prospect");
1581 }
1582 if ($obj->fournisseur) {
1583 $label .= ($obj->client ? ', ' : '') . $langs->trans("Supplier");
1584 }
1585 if ($obj->client || $obj->fournisseur) {
1586 $label .= ')';
1587 }
1588 }
1589
1590 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1591 $s = ($obj->address ? ' - ' . $obj->address : '') . ($obj->zip ? ' - ' . $obj->zip : '') . ($obj->town ? ' ' . $obj->town : '');
1592 if (!empty($obj->country_code)) {
1593 $s .= ', ' . $langs->trans('Country' . $obj->country_code);
1594 }
1595 $label .= $s;
1596 $labelhtml .= $s;
1597 }
1598
1599 if (empty($outputmode)) {
1600 if (in_array($obj->rowid, $selected)) {
1601 $out .= '<option value="' . $obj->rowid . '" selected data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1602 } else {
1603 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1604 }
1605 } else {
1606 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label, 'labelhtml' => $labelhtml));
1607 }
1608
1609 $i++;
1610 if (($i % 10) == 0) {
1611 $out .= "\n";
1612 }
1613 }
1614 }
1615 $out .= '</select>' . "\n";
1616 } else {
1617 dol_print_error($this->db);
1618 }
1619
1620 $this->result = array('nbofthirdparties' => $num);
1621
1622 if ($outputmode) {
1623 return $outarray;
1624 }
1625 return $out;
1626 }
1627
1628
1629 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1630
1641 public function select_remises($selected, $htmlname, $filter, $socid, $maxvalue = 0)
1642 {
1643 // phpcs:enable
1644 global $langs, $conf;
1645
1646 // On recherche les remises
1647 $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
1648 $sql .= " re.description, re.fk_facture_source";
1649 $sql .= " FROM " . $this->db->prefix() . "societe_remise_except as re";
1650 $sql .= " WHERE re.fk_soc = " . (int) $socid;
1651 $sql .= " AND re.entity = " . $conf->entity;
1652 if ($filter) {
1653 $sql .= " AND " . $filter;
1654 }
1655 $sql .= " ORDER BY re.description ASC";
1656
1657 dol_syslog(get_class($this) . "::select_remises", LOG_DEBUG);
1658 $resql = $this->db->query($sql);
1659 if ($resql) {
1660 print '<select id="select_' . $htmlname . '" class="flat maxwidthonsmartphone" name="' . $htmlname . '">';
1661 $num = $this->db->num_rows($resql);
1662
1663 $qualifiedlines = $num;
1664
1665 $i = 0;
1666 if ($num) {
1667 print '<option value="0">&nbsp;</option>';
1668 while ($i < $num) {
1669 $obj = $this->db->fetch_object($resql);
1670 $desc = dol_trunc($obj->description, 40);
1671 if (preg_match('/\‍(CREDIT_NOTE\‍)/', $desc)) {
1672 $desc = preg_replace('/\‍(CREDIT_NOTE\‍)/', $langs->trans("CreditNote"), $desc);
1673 }
1674 if (preg_match('/\‍(DEPOSIT\‍)/', $desc)) {
1675 $desc = preg_replace('/\‍(DEPOSIT\‍)/', $langs->trans("Deposit"), $desc);
1676 }
1677 if (preg_match('/\‍(EXCESS RECEIVED\‍)/', $desc)) {
1678 $desc = preg_replace('/\‍(EXCESS RECEIVED\‍)/', $langs->trans("ExcessReceived"), $desc);
1679 }
1680 if (preg_match('/\‍(EXCESS PAID\‍)/', $desc)) {
1681 $desc = preg_replace('/\‍(EXCESS PAID\‍)/', $langs->trans("ExcessPaid"), $desc);
1682 }
1683
1684 $selectstring = '';
1685 if ($selected > 0 && $selected == $obj->rowid) {
1686 $selectstring = ' selected';
1687 }
1688
1689 $disabled = '';
1690 if ($maxvalue > 0 && $obj->amount_ttc > $maxvalue) {
1691 $qualifiedlines--;
1692 $disabled = ' disabled';
1693 }
1694
1695 if (getDolGlobalString('MAIN_SHOW_FACNUMBER_IN_DISCOUNT_LIST') && !empty($obj->fk_facture_source)) {
1696 $tmpfac = new Facture($this->db);
1697 if ($tmpfac->fetch($obj->fk_facture_source) > 0) {
1698 $desc = $desc . ' - ' . $tmpfac->ref;
1699 }
1700 }
1701
1702 print '<option value="' . $obj->rowid . '"' . $selectstring . $disabled . '>' . $desc . ' (' . price($obj->amount_ht) . ' ' . $langs->trans("HT") . ' - ' . price($obj->amount_ttc) . ' ' . $langs->trans("TTC") . ')</option>';
1703 $i++;
1704 }
1705 }
1706 print '</select>';
1707 print ajax_combobox('select_' . $htmlname);
1708
1709 return $qualifiedlines;
1710 } else {
1711 dol_print_error($this->db);
1712 return -1;
1713 }
1714 }
1715
1716 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1717
1738 public function select_contacts($socid, $selected = '', $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $showsoc = 0, $forcecombo = 0, $events = array(), $options_only = false, $moreparam = '', $htmlid = '')
1739 {
1740 // phpcs:enable
1741 print $this->selectcontacts($socid, $selected, $htmlname, $showempty, $exclude, $limitto, $showfunction, $morecss, $options_only, $showsoc, $forcecombo, $events, $moreparam, $htmlid);
1742 return $this->num;
1743 }
1744
1769 public function selectcontacts($socid, $selected = array(), $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $options_only = false, $showsoc = 0, $forcecombo = 0, $events = array(), $moreparam = '', $htmlid = '', $multiple = false, $disableifempty = 0)
1770 {
1771 global $conf, $langs, $hookmanager, $action;
1772
1773 $langs->load('companies');
1774
1775 if (empty($htmlid)) {
1776 $htmlid = $htmlname;
1777 }
1778 $num = 0;
1779
1780 if ($selected === '') {
1781 $selected = array();
1782 } elseif (!is_array($selected)) {
1783 $selected = array($selected);
1784 }
1785 $out = '';
1786
1787 if (!is_object($hookmanager)) {
1788 include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
1789 $hookmanager = new HookManager($this->db);
1790 }
1791
1792 // We search third parties
1793 $sql = "SELECT sp.rowid, sp.lastname, sp.statut, sp.firstname, sp.poste, sp.email, sp.phone, sp.phone_perso, sp.phone_mobile, sp.town AS contact_town";
1794 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1795 $sql .= ", s.nom as company, s.town AS company_town";
1796 }
1797 $sql .= " FROM " . $this->db->prefix() . "socpeople as sp";
1798 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1799 $sql .= " LEFT OUTER JOIN " . $this->db->prefix() . "societe as s ON s.rowid=sp.fk_soc";
1800 }
1801 $sql .= " WHERE sp.entity IN (" . getEntity('contact') . ")";
1802 if ($socid > 0 || $socid == -1) {
1803 $sql .= " AND sp.fk_soc = " . ((int) $socid);
1804 }
1805 if (getDolGlobalString('CONTACT_HIDE_INACTIVE_IN_COMBOBOX')) {
1806 $sql .= " AND sp.statut <> 0";
1807 }
1808 // Add where from hooks
1809 $parameters = array();
1810 $reshook = $hookmanager->executeHooks('selectContactListWhere', $parameters); // Note that $action and $object may have been modified by hook
1811 $sql .= $hookmanager->resPrint;
1812 $sql .= " ORDER BY sp.lastname ASC";
1813
1814 dol_syslog(get_class($this) . "::selectcontacts", LOG_DEBUG);
1815 $resql = $this->db->query($sql);
1816 if ($resql) {
1817 $num = $this->db->num_rows($resql);
1818
1819 if ($htmlname != 'none' && !$options_only) {
1820 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlid . '" name="' . $htmlname . (($num || empty($disableifempty)) ? '' : ' disabled') . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . (!empty($moreparam) ? $moreparam : '') . '>';
1821 }
1822
1823 if ($showempty && !is_numeric($showempty)) {
1824 $textforempty = $showempty;
1825 $out .= '<option class="optiongrey" value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>' . $textforempty . '</option>';
1826 } else {
1827 if (($showempty == 1 || ($showempty == 3 && $num > 1)) && !$multiple) {
1828 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>&nbsp;</option>';
1829 }
1830 if ($showempty == 2) {
1831 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>-- ' . $langs->trans("Internal") . ' --</option>';
1832 }
1833 }
1834
1835 $i = 0;
1836 if ($num) {
1837 include_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1838 $contactstatic = new Contact($this->db);
1839
1840 while ($i < $num) {
1841 $obj = $this->db->fetch_object($resql);
1842
1843 // Set email (or phones) and town extended infos
1844 $extendedInfos = '';
1845 if (getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1846 $extendedInfos = array();
1847 $email = trim($obj->email);
1848 if (!empty($email)) {
1849 $extendedInfos[] = $email;
1850 } else {
1851 $phone = trim($obj->phone);
1852 $phone_perso = trim($obj->phone_perso);
1853 $phone_mobile = trim($obj->phone_mobile);
1854 if (!empty($phone)) {
1855 $extendedInfos[] = $phone;
1856 }
1857 if (!empty($phone_perso)) {
1858 $extendedInfos[] = $phone_perso;
1859 }
1860 if (!empty($phone_mobile)) {
1861 $extendedInfos[] = $phone_mobile;
1862 }
1863 }
1864 $contact_town = trim($obj->contact_town);
1865 $company_town = trim($obj->company_town);
1866 if (!empty($contact_town)) {
1867 $extendedInfos[] = $contact_town;
1868 } elseif (!empty($company_town)) {
1869 $extendedInfos[] = $company_town;
1870 }
1871 $extendedInfos = implode(' - ', $extendedInfos);
1872 if (!empty($extendedInfos)) {
1873 $extendedInfos = ' - ' . $extendedInfos;
1874 }
1875 }
1876
1877 $contactstatic->id = $obj->rowid;
1878 $contactstatic->lastname = $obj->lastname;
1879 $contactstatic->firstname = $obj->firstname;
1880 if ($obj->statut == 1) {
1881 if ($htmlname != 'none') {
1882 $disabled = 0;
1883 if (is_array($exclude) && count($exclude) && in_array($obj->rowid, $exclude)) {
1884 $disabled = 1;
1885 }
1886 if (is_array($limitto) && count($limitto) && !in_array($obj->rowid, $limitto)) {
1887 $disabled = 1;
1888 }
1889 if (!empty($selected) && in_array($obj->rowid, $selected)) {
1890 $out .= '<option value="' . $obj->rowid . '"';
1891 if ($disabled) {
1892 $out .= ' disabled';
1893 }
1894 $out .= ' selected>';
1895 $out .= $contactstatic->getFullName($langs) . $extendedInfos;
1896 if ($showfunction && $obj->poste) {
1897 $out .= ' (' . $obj->poste . ')';
1898 }
1899 if (($showsoc > 0) && $obj->company) {
1900 $out .= ' - (' . $obj->company . ')';
1901 }
1902 $out .= '</option>';
1903 } else {
1904 $out .= '<option value="' . $obj->rowid . '"';
1905 if ($disabled) {
1906 $out .= ' disabled';
1907 }
1908 $out .= '>';
1909 $out .= $contactstatic->getFullName($langs) . $extendedInfos;
1910 if ($showfunction && $obj->poste) {
1911 $out .= ' (' . $obj->poste . ')';
1912 }
1913 if (($showsoc > 0) && $obj->company) {
1914 $out .= ' - (' . $obj->company . ')';
1915 }
1916 $out .= '</option>';
1917 }
1918 } else {
1919 if (in_array($obj->rowid, $selected)) {
1920 $out .= $contactstatic->getFullName($langs) . $extendedInfos;
1921 if ($showfunction && $obj->poste) {
1922 $out .= ' (' . $obj->poste . ')';
1923 }
1924 if (($showsoc > 0) && $obj->company) {
1925 $out .= ' - (' . $obj->company . ')';
1926 }
1927 }
1928 }
1929 }
1930 $i++;
1931 }
1932 } else {
1933 $labeltoshow = ($socid != -1) ? ($langs->trans($socid ? "NoContactDefinedForThirdParty" : "NoContactDefined")) : $langs->trans('SelectAThirdPartyFirst');
1934 $out .= '<option class="disabled" value="-1"' . (($showempty == 2 || $multiple) ? '' : ' selected') . ' disabled="disabled">';
1935 $out .= $labeltoshow;
1936 $out .= '</option>';
1937 }
1938
1939 $parameters = array(
1940 'socid' => $socid,
1941 'htmlname' => $htmlname,
1942 'resql' => $resql,
1943 'out' => &$out,
1944 'showfunction' => $showfunction,
1945 'showsoc' => $showsoc,
1946 );
1947
1948 $reshook = $hookmanager->executeHooks('afterSelectContactOptions', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1949
1950 if ($htmlname != 'none' && !$options_only) {
1951 $out .= '</select>';
1952 }
1953
1954 if ($conf->use_javascript_ajax && !$forcecombo && !$options_only) {
1955 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1956 $out .= ajax_combobox($htmlid, $events, getDolGlobalString("CONTACT_USE_SEARCH_TO_SELECT"));
1957 }
1958
1959 $this->num = $num;
1960 return $out;
1961 } else {
1962 dol_print_error($this->db);
1963 return -1;
1964 }
1965 }
1966
1967 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1968
1984 public function select_users($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0')
1985 {
1986 // phpcs:enable
1987 print $this->select_dolusers($selected, $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity);
1988 }
1989
1990 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1991
2016 public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '', $maxlength = 0, $showstatus = 0, $morefilter = '', $show_every = 0, $enableonlytext = '', $morecss = '', $notdisabled = 0, $outputmode = 0, $multiple = false, $forcecombo = 0)
2017 {
2018 // phpcs:enable
2019 global $conf, $user, $langs, $hookmanager;
2020 global $action;
2021
2022 // If no preselected user defined, we take current user
2023 if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) {
2024 $selected = $user->id;
2025 }
2026
2027 if ($selected === '') {
2028 $selected = array();
2029 } elseif (!is_array($selected)) {
2030 $selected = array($selected);
2031 }
2032
2033 $excludeUsers = null;
2034 $includeUsers = null;
2035
2036 // Exclude some users
2037 if (is_array($exclude)) {
2038 $excludeUsers = implode(",", $exclude);
2039 }
2040 // Include some uses
2041 if (is_array($include)) {
2042 $includeUsers = implode(",", $include);
2043 } elseif ($include == 'hierarchy') {
2044 // Build list includeUsers to have only hierarchy
2045 $includeUsers = implode(",", $user->getAllChildIds(0));
2046 } elseif ($include == 'hierarchyme') {
2047 // Build list includeUsers to have only hierarchy and current user
2048 $includeUsers = implode(",", $user->getAllChildIds(1));
2049 }
2050
2051 $out = '';
2052 $outarray = array();
2053 $outarray2 = array();
2054
2055 // Forge request to select users
2056 $sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut as status, u.login, u.admin, u.entity, u.photo";
2057 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
2058 $sql .= ", e.label";
2059 }
2060 $sql .= " FROM " . $this->db->prefix() . "user as u";
2061 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
2062 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid = u.entity";
2063 if (!empty($force_entity)) {
2064 $sql .= " WHERE u.entity IN (0, " . $this->db->sanitize($force_entity) . ")";
2065 } else {
2066 $sql .= " WHERE u.entity IS NOT NULL";
2067 }
2068 } else {
2069 if (isModEnabled('multicompany') && getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE')) {
2070 $sql .= " WHERE u.rowid IN (SELECT ug.fk_user FROM ".$this->db->prefix()."usergroup_user as ug WHERE ug.entity IN (".getEntity('usergroup')."))";
2071 } else {
2072 $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
2073 }
2074 }
2075 if (!empty($user->socid)) {
2076 $sql .= " AND u.fk_soc = " . ((int) $user->socid);
2077 }
2078 if (is_array($exclude) && $excludeUsers) {
2079 $sql .= " AND u.rowid NOT IN (" . $this->db->sanitize($excludeUsers) . ")";
2080 }
2081 if ($includeUsers) {
2082 $sql .= " AND u.rowid IN (" . $this->db->sanitize($includeUsers) . ")";
2083 }
2084 if (getDolGlobalString('USER_HIDE_INACTIVE_IN_COMBOBOX') || $notdisabled) {
2085 $sql .= " AND u.statut <> 0";
2086 }
2087 if (!empty($morefilter)) {
2088 $sql .= " " . $morefilter;
2089 }
2090
2091 //Add hook to filter on user (for exemple on usergroup define in custom modules)
2092 $reshook = $hookmanager->executeHooks('addSQLWhereFilterOnSelectUsers', array(), $this, $action);
2093 if (!empty($reshook)) {
2094 $sql .= $hookmanager->resPrint;
2095 }
2096
2097 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) { // MAIN_FIRSTNAME_NAME_POSITION is 0 means firstname+lastname
2098 $sql .= " ORDER BY u.statut DESC, u.firstname ASC, u.lastname ASC";
2099 } else {
2100 $sql .= " ORDER BY u.statut DESC, u.lastname ASC, u.firstname ASC";
2101 }
2102
2103 dol_syslog(get_class($this) . "::select_dolusers", LOG_DEBUG);
2104
2105 $resql = $this->db->query($sql);
2106 if ($resql) {
2107 $num = $this->db->num_rows($resql);
2108 $i = 0;
2109 if ($num) {
2110 // do not use maxwidthonsmartphone by default. Set it by caller so auto size to 100% will work when not defined
2111 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : ' minwidth200') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
2112 if ($show_empty && !$multiple) {
2113 $textforempty = ' ';
2114 if (!empty($conf->use_javascript_ajax)) {
2115 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
2116 }
2117 if (!is_numeric($show_empty)) {
2118 $textforempty = $show_empty;
2119 }
2120 $out .= '<option class="optiongrey" value="' . ($show_empty < 0 ? $show_empty : -1) . '"' . ((empty($selected) || in_array(-1, $selected)) ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
2121 }
2122 if ($show_every) {
2123 $out .= '<option value="-2"' . ((in_array(-2, $selected)) ? ' selected' : '') . '>-- ' . $langs->trans("Everybody") . ' --</option>' . "\n";
2124 }
2125
2126 $userstatic = new User($this->db);
2127
2128 while ($i < $num) {
2129 $obj = $this->db->fetch_object($resql);
2130
2131 $userstatic->id = $obj->rowid;
2132 $userstatic->lastname = $obj->lastname;
2133 $userstatic->firstname = $obj->firstname;
2134 $userstatic->photo = $obj->photo;
2135 $userstatic->statut = $obj->status;
2136 $userstatic->entity = $obj->entity;
2137 $userstatic->admin = $obj->admin;
2138
2139 $disableline = '';
2140 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
2141 $disableline = ($enableonlytext ? $enableonlytext : '1');
2142 }
2143
2144 $labeltoshow = '';
2145 $labeltoshowhtml = '';
2146
2147 // $fullNameMode is 0=Lastname+Firstname (MAIN_FIRSTNAME_NAME_POSITION=1), 1=Firstname+Lastname (MAIN_FIRSTNAME_NAME_POSITION=0)
2148 $fullNameMode = 0;
2149 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) {
2150 $fullNameMode = 1; //Firstname+lastname
2151 }
2152 $labeltoshow .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2153 $labeltoshowhtml .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2154 if (empty($obj->firstname) && empty($obj->lastname)) {
2155 $labeltoshow .= $obj->login;
2156 $labeltoshowhtml .= $obj->login;
2157 }
2158
2159 // Complete name with a more info string like: ' (info1 - info2 - ...)'
2160 $moreinfo = '';
2161 $moreinfohtml = '';
2162 if (getDolGlobalString('MAIN_SHOW_LOGIN')) {
2163 $moreinfo .= ($moreinfo ? ' - ' : ' (');
2164 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(');
2165 $moreinfo .= $obj->login;
2166 $moreinfohtml .= $obj->login;
2167 }
2168 if ($showstatus >= 0) {
2169 if ($obj->status == 1 && $showstatus == 1) {
2170 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Enabled');
2171 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Enabled');
2172 }
2173 if ($obj->status == 0 && $showstatus == 1) {
2174 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Disabled');
2175 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Disabled');
2176 }
2177 }
2178 if (isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1 && !empty($user->admin) && empty($user->entity)) {
2179 if (empty($obj->entity)) {
2180 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans("AllEntities");
2181 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans("AllEntities");
2182 } else {
2183 if ($obj->entity != $conf->entity) {
2184 $moreinfo .= ($moreinfo ? ' - ' : ' (') . ($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2185 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . ($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2186 }
2187 }
2188 }
2189 $moreinfo .= (!empty($moreinfo) ? ')' : '');
2190 $moreinfohtml .= (!empty($moreinfohtml) ? ')</span>' : '');
2191 if (!empty($disableline) && $disableline != '1') {
2192 // Add text from $enableonlytext parameter
2193 $moreinfo .= ' - ' . $disableline;
2194 $moreinfohtml .= ' - ' . $disableline;
2195 }
2196 $labeltoshow .= $moreinfo;
2197 $labeltoshowhtml .= $moreinfohtml;
2198
2199 $out .= '<option value="' . $obj->rowid . '"';
2200 if (!empty($disableline)) {
2201 $out .= ' disabled';
2202 }
2203 if ((is_object($selected) && $selected->id == $obj->rowid) || (!is_object($selected) && in_array($obj->rowid, $selected))) {
2204 $out .= ' selected';
2205 }
2206 $out .= ' data-html="';
2207 $outhtml = $userstatic->getNomUrl(-3, '', 0, 1, 24, 1, 'login', '', 1) . ' ';
2208 if ($showstatus >= 0 && $obj->status == 0) {
2209 $outhtml .= '<strike class="opacitymediumxxx">';
2210 }
2211 $outhtml .= $labeltoshowhtml;
2212 if ($showstatus >= 0 && $obj->status == 0) {
2213 $outhtml .= '</strike>';
2214 }
2215 $out .= dol_escape_htmltag($outhtml);
2216 $out .= '">';
2217 $out .= $labeltoshow;
2218 $out .= '</option>';
2219
2220 $outarray[$userstatic->id] = $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength) . $moreinfo;
2221 $outarray2[$userstatic->id] = array(
2222 'id'=>$userstatic->id,
2223 'label'=>$labeltoshow,
2224 'labelhtml'=>$labeltoshowhtml,
2225 'color'=>'',
2226 'picto'=>''
2227 );
2228
2229 $i++;
2230 }
2231 } else {
2232 $out .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '" disabled>';
2233 $out .= '<option value="">' . $langs->trans("None") . '</option>';
2234 }
2235 $out .= '</select>';
2236
2237 if ($num && !$forcecombo) {
2238 // Enhance with select2
2239 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2240 $out .= ajax_combobox($htmlname);
2241 }
2242 } else {
2243 dol_print_error($this->db);
2244 }
2245
2246 if ($outputmode == 2) {
2247 return $outarray2;
2248 } elseif ($outputmode) {
2249 return $outarray;
2250 }
2251
2252 return $out;
2253 }
2254
2255
2256 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2279 public function select_dolusers_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = array(), $enableonly = array(), $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofuserid = array(), $listofcontactid = array(), $listofotherid = array())
2280 {
2281 // phpcs:enable
2282 global $langs;
2283
2284 $userstatic = new User($this->db);
2285 $out = '';
2286
2287 $assignedtouser = array();
2288 if (!empty($_SESSION['assignedtouser'])) {
2289 $assignedtouser = json_decode($_SESSION['assignedtouser'], true);
2290 }
2291 $nbassignetouser = count($assignedtouser);
2292
2293 //if ($nbassignetouser && $action != 'view') $out .= '<br>';
2294 if ($nbassignetouser) {
2295 $out .= '<ul class="attendees">';
2296 }
2297 $i = 0;
2298 $ownerid = 0;
2299 foreach ($assignedtouser as $key => $value) {
2300 if ($value['id'] == $ownerid) {
2301 continue;
2302 }
2303
2304 $out .= '<li>';
2305 $userstatic->fetch($value['id']);
2306 $out .= $userstatic->getNomUrl(-1);
2307 if ($i == 0) {
2308 $ownerid = $value['id'];
2309 $out .= ' (' . $langs->trans("Owner") . ')';
2310 }
2311 if ($nbassignetouser > 1 && $action != 'view') {
2312 $out .= ' <input type="image" style="border: 0px;" src="' . img_picto($langs->trans("Remove"), 'delete', '', 0, 1) . '" value="' . $userstatic->id . '" class="removedassigned reposition" id="removedassigned_' . $userstatic->id . '" name="removedassigned_' . $userstatic->id . '">';
2313 }
2314 // Show my availability
2315 if ($showproperties) {
2316 if ($ownerid == $value['id'] && is_array($listofuserid) && count($listofuserid) && in_array($ownerid, array_keys($listofuserid))) {
2317 $out .= '<div class="myavailability inline-block">';
2318 $out .= '<span class="hideonsmartphone">&nbsp;-&nbsp;<span class="opacitymedium">' . $langs->trans("Availability") . ':</span> </span><input id="transparency" class="paddingrightonly" ' . ($action == 'view' ? 'disabled' : '') . ' type="checkbox" name="transparency"' . ($listofuserid[$ownerid]['transparency'] ? ' checked' : '') . '><label for="transparency">' . $langs->trans("Busy") . '</label>';
2319 $out .= '</div>';
2320 }
2321 }
2322 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2323 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2324
2325 $out .= '</li>';
2326 $i++;
2327 }
2328 if ($nbassignetouser) {
2329 $out .= '</ul>';
2330 }
2331
2332 // Method with no ajax
2333 if ($action != 'view') {
2334 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassigned" value="">';
2335 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2336 $out .= 'jQuery(".removedassigned").click(function() { jQuery(".removedassignedhidden").val(jQuery(this).val()); });';
2337 $out .= 'jQuery(".assignedtouser").change(function() { console.log(jQuery(".assignedtouser option:selected").val());';
2338 $out .= ' if (jQuery(".assignedtouser option:selected").val() > 0) { jQuery("#' . $action . 'assignedtouser").attr("disabled", false); }';
2339 $out .= ' else { jQuery("#' . $action . 'assignedtouser").attr("disabled", true); }';
2340 $out .= '});';
2341 $out .= '})</script>';
2342 $out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2343 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtouser" name="' . $action . 'assignedtouser" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2344 $out .= '<br>';
2345 }
2346
2347 return $out;
2348 }
2349
2350 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2370 public function select_dolresources_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = array(), $enableonly = array(), $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofresourceid = array())
2371 {
2372 // phpcs:enable
2373 global $langs;
2374
2375 require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php';
2376 require_once DOL_DOCUMENT_ROOT.'/resource/class/dolresource.class.php';
2377 $formresources = new FormResource($this->db);
2378 $resourcestatic = new Dolresource($this->db);
2379
2380 $out = '';
2381 $assignedtoresource = array();
2382 if (!empty($_SESSION['assignedtoresource'])) {
2383 $assignedtoresource = json_decode($_SESSION['assignedtoresource'], true);
2384 }
2385 $nbassignetoresource = count($assignedtoresource);
2386
2387 //if ($nbassignetoresource && $action != 'view') $out .= '<br>';
2388 if ($nbassignetoresource) {
2389 $out .= '<ul class="attendees">';
2390 }
2391 $i = 0;
2392
2393 foreach ($assignedtoresource as $key => $value) {
2394 $out .= '<li>';
2395 $resourcestatic->fetch($value['id']);
2396 $out .= $resourcestatic->getNomUrl(-1);
2397 if ($nbassignetoresource > 1 && $action != 'view') {
2398 $out .= ' <input type="image" style="border: 0px;" src="' . img_picto($langs->trans("Remove"), 'delete', '', 0, 1) . '" value="' . $resourcestatic->id . '" class="removedassigned reposition" id="removedassignedresource_' . $resourcestatic->id . '" name="removedassignedresource_' . $resourcestatic->id . '">';
2399 }
2400 // Show my availability
2401 if ($showproperties) {
2402 if (is_array($listofresourceid) && count($listofresourceid)) {
2403 $out .= '<div class="myavailability inline-block">';
2404 $out .= '<span class="hideonsmartphone">&nbsp;-&nbsp;<span class="opacitymedium">' . $langs->trans("Availability") . ':</span> </span><input id="transparencyresource" class="paddingrightonly" ' . ($action == 'view' ? 'disabled' : '') . ' type="checkbox" name="transparency"' . ($listofresourceid[$value['id']]['transparency'] ? ' checked' : '') . '><label for="transparency">' . $langs->trans("Busy") . '</label>';
2405 $out .= '</div>';
2406 }
2407 }
2408 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2409 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2410
2411 $out .= '</li>';
2412 $i++;
2413 }
2414 if ($nbassignetoresource) {
2415 $out .= '</ul>';
2416 }
2417
2418 // Method with no ajax
2419 if ($action != 'view') {
2420 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassignedresource" value="">';
2421 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2422 $out .= 'jQuery(".removedassignedresource").click(function() { jQuery(".removedassignedresourcehidden").val(jQuery(this).val()); });';
2423 $out .= 'jQuery(".assignedtoresource").change(function() { console.log(jQuery(".assignedtoresource option:selected").val());';
2424 $out .= ' if (jQuery(".assignedtoresource option:selected").val() > 0) { jQuery("#' . $action . 'assignedtoresource").attr("disabled", false); }';
2425 $out .= ' else { jQuery("#' . $action . 'assignedtoresource").attr("disabled", true); }';
2426 $out .= '});';
2427 $out .= '})</script>';
2428
2429 $events = array();
2430 $out .= img_picto('', 'resource', 'class="pictofixedwidth"');
2431 $out .= $formresources->select_resource_list('', $htmlname, '', 1, 1, 0, $events, '', 2, null);
2432 //$out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2433 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtoresource" name="' . $action . 'assignedtoresource" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2434 $out .= '<br>';
2435 }
2436
2437 return $out;
2438 }
2439
2440 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2441
2469 public function select_produits($selected = 0, $htmlname = 'productid', $filtertype = '', $limit = 0, $price_level = 0, $status = 1, $finished = 2, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $selected_combinations = null, $nooutput = 0, $status_purchase = -1)
2470 {
2471 // phpcs:enable
2472 global $langs, $conf;
2473
2474 $out = '';
2475
2476 // check parameters
2477 $price_level = (!empty($price_level) ? $price_level : 0);
2478 if (is_null($ajaxoptions)) {
2479 $ajaxoptions = array();
2480 }
2481
2482 if (strval($filtertype) === '' && (isModEnabled("product") || isModEnabled("service"))) {
2483 if (isModEnabled("product") && !isModEnabled('service')) {
2484 $filtertype = '0';
2485 } elseif (!isModEnabled('product') && isModEnabled("service")) {
2486 $filtertype = '1';
2487 }
2488 }
2489
2490 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
2491 $placeholder = '';
2492
2493 if ($selected && empty($selected_input_value)) {
2494 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2495 $producttmpselect = new Product($this->db);
2496 $producttmpselect->fetch($selected);
2497 $selected_input_value = $producttmpselect->ref;
2498 unset($producttmpselect);
2499 }
2500 // handle case where product or service module is disabled + no filter specified
2501 if ($filtertype == '') {
2502 if (!isModEnabled('product')) { // when product module is disabled, show services only
2503 $filtertype = 1;
2504 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
2505 $filtertype = 0;
2506 }
2507 }
2508 // mode=1 means customers products
2509 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=1&status=' . $status . '&status_purchase=' . $status_purchase . '&finished=' . $finished . '&hidepriceinlabel=' . $hidepriceinlabel . '&warehousestatus=' . $warehouseStatus;
2510 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
2511
2512 if (isModEnabled('variants') && is_array($selected_combinations)) {
2513 // Code to automatically insert with javascript the select of attributes under the select of product
2514 // when a parent of variant has been selected.
2515 $out .= '
2516 <!-- script to auto show attributes select tags if a variant was selected -->
2517 <script nonce="' . getNonce() . '">
2518 // auto show attributes fields
2519 selected = ' . json_encode($selected_combinations) . ';
2520 combvalues = {};
2521
2522 jQuery(document).ready(function () {
2523
2524 jQuery("input[name=\'prod_entry_mode\']").change(function () {
2525 if (jQuery(this).val() == \'free\') {
2526 jQuery(\'div#attributes_box\').empty();
2527 }
2528 });
2529
2530 jQuery("input#' . $htmlname . '").change(function () {
2531
2532 if (!jQuery(this).val()) {
2533 jQuery(\'div#attributes_box\').empty();
2534 return;
2535 }
2536
2537 console.log("A change has started. We get variants fields to inject html select");
2538
2539 jQuery.getJSON("' . DOL_URL_ROOT . '/variants/ajax/getCombinations.php", {
2540 id: jQuery(this).val()
2541 }, function (data) {
2542 jQuery(\'div#attributes_box\').empty();
2543
2544 jQuery.each(data, function (key, val) {
2545
2546 combvalues[val.id] = val.values;
2547
2548 var span = jQuery(document.createElement(\'div\')).css({
2549 \'display\': \'table-row\'
2550 });
2551
2552 span.append(
2553 jQuery(document.createElement(\'div\')).text(val.label).css({
2554 \'font-weight\': \'bold\',
2555 \'display\': \'table-cell\'
2556 })
2557 );
2558
2559 var html = jQuery(document.createElement(\'select\')).attr(\'name\', \'combinations[\' + val.id + \']\').css({
2560 \'margin-left\': \'15px\',
2561 \'white-space\': \'pre\'
2562 }).append(
2563 jQuery(document.createElement(\'option\')).val(\'\')
2564 );
2565
2566 jQuery.each(combvalues[val.id], function (key, val) {
2567 var tag = jQuery(document.createElement(\'option\')).val(val.id).html(val.value);
2568
2569 if (selected[val.fk_product_attribute] == val.id) {
2570 tag.attr(\'selected\', \'selected\');
2571 }
2572
2573 html.append(tag);
2574 });
2575
2576 span.append(html);
2577 jQuery(\'div#attributes_box\').append(span);
2578 });
2579 })
2580 });
2581
2582 ' . ($selected ? 'jQuery("input#' . $htmlname . '").change();' : '') . '
2583 });
2584 </script>
2585 ';
2586 }
2587
2588 if (empty($hidelabel)) {
2589 $out .= $langs->trans("RefOrLabel") . ' : ';
2590 } elseif ($hidelabel > 1) {
2591 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
2592 if ($hidelabel == 2) {
2593 $out .= img_picto($langs->trans("Search"), 'search');
2594 }
2595 }
2596 $out .= '<input type="text" class="minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
2597 if ($hidelabel == 3) {
2598 $out .= img_picto($langs->trans("Search"), 'search');
2599 }
2600 } else {
2601 $out .= $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus, $status_purchase);
2602 }
2603
2604 if (empty($nooutput)) {
2605 print $out;
2606 } else {
2607 return $out;
2608 }
2609 }
2610
2611 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2612
2628 public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 0, $showempty = '1', $morecss = '', $nooutput = '', $forcecombo = 0, $TProducts = [])
2629 {
2630 // phpcs:enable
2631 global $conf, $user, $langs, $db;
2632
2633 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2634
2635 $error = 0;
2636 $out = '';
2637
2638 if (!$forcecombo) {
2639 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2640 $events = array();
2641 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
2642 }
2643
2644 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
2645
2646 $sql = 'SELECT b.rowid, b.ref, b.label, b.fk_product';
2647 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'bom_bom as b';
2648 $sql .= ' WHERE b.entity IN (' . getEntity('bom') . ')';
2649 if (!empty($status)) {
2650 $sql .= ' AND status = ' . (int) $status;
2651 }
2652 if (!empty($type)) {
2653 $sql .= ' AND bomtype = ' . (int) $type;
2654 }
2655 if (!empty($TProducts)) {
2656 $sql .= ' AND fk_product IN (' . $this->db->sanitize(implode(',', $TProducts)) . ')';
2657 }
2658 if (!empty($limit)) {
2659 $sql .= ' LIMIT ' . (int) $limit;
2660 }
2661 $resql = $db->query($sql);
2662 if ($resql) {
2663 if ($showempty) {
2664 $out .= '<option value="-1"';
2665 if (empty($selected)) {
2666 $out .= ' selected';
2667 }
2668 $out .= '>&nbsp;</option>';
2669 }
2670 while ($obj = $db->fetch_object($resql)) {
2671 $product = new Product($db);
2672 $res = $product->fetch($obj->fk_product);
2673 $out .= '<option value="' . $obj->rowid . '"';
2674 if ($obj->rowid == $selected) {
2675 $out .= 'selected';
2676 }
2677 $out .= '>' . $obj->ref . ' - ' . $product->label . ' - ' . $obj->label . '</option>';
2678 }
2679 } else {
2680 $error++;
2681 dol_print_error($db);
2682 }
2683 $out .= '</select>';
2684 if (empty($nooutput)) {
2685 print $out;
2686 } else {
2687 return $out;
2688 }
2689 }
2690
2691 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2692
2718 public function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $status_purchase = -1)
2719 {
2720 // phpcs:enable
2721 global $langs, $conf;
2722 global $hookmanager;
2723
2724 $out = '';
2725 $outarray = array();
2726
2727 // Units
2728 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2729 $langs->load('other');
2730 }
2731
2732 $warehouseStatusArray = array();
2733 if (!empty($warehouseStatus)) {
2734 require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
2735 if (preg_match('/warehouseclosed/', $warehouseStatus)) {
2736 $warehouseStatusArray[] = Entrepot::STATUS_CLOSED;
2737 }
2738 if (preg_match('/warehouseopen/', $warehouseStatus)) {
2739 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL;
2740 }
2741 if (preg_match('/warehouseinternal/', $warehouseStatus)) {
2742 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL;
2743 }
2744 }
2745
2746 $selectFields = " p.rowid, p.ref, p.label, p.description, p.barcode, p.fk_country, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.default_vat_code, p.duration, p.fk_price_expression";
2747 if (count($warehouseStatusArray)) {
2748 $selectFieldsGrouped = ", sum(" . $this->db->ifsql("e.statut IS NULL", "0", "ps.reel") . ") as stock"; // e.statut is null if there is no record in stock
2749 } else {
2750 $selectFieldsGrouped = ", " . $this->db->ifsql("p.stock IS NULL", 0, "p.stock") . " AS stock";
2751 }
2752
2753 $sql = "SELECT ";
2754
2755 // Add select from hooks
2756 $parameters = array();
2757 $reshook = $hookmanager->executeHooks('selectProductsListSelect', $parameters); // Note that $action and $object may have been modified by hook
2758 if (empty($reshook)) {
2759 $sql .= $selectFields.$selectFieldsGrouped.$hookmanager->resPrint;
2760 } else {
2761 $sql .= $hookmanager->resPrint;
2762 }
2763
2764 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
2765 //Product category
2766 $sql .= ", (SELECT " . $this->db->prefix() . "categorie_product.fk_categorie
2767 FROM " . $this->db->prefix() . "categorie_product
2768 WHERE " . $this->db->prefix() . "categorie_product.fk_product=p.rowid
2769 LIMIT 1
2770 ) AS categorie_product_id ";
2771 }
2772
2773 //Price by customer
2774 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2775 $sql .= ', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
2776 $sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx, pcp.default_vat_code as custdefault_vat_code, pcp.ref_customer as custref';
2777 $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custdefault_vat_code, custref";
2778 }
2779 // Units
2780 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2781 $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units";
2782 $selectFields .= ', unit_long, unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units';
2783 }
2784
2785 // Multilang : we add translation
2786 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2787 $sql .= ", pl.label as label_translated";
2788 $sql .= ", pl.description as description_translated";
2789 $selectFields .= ", label_translated";
2790 $selectFields .= ", description_translated";
2791 }
2792 // Price by quantity
2793 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2794 $sql .= ", (SELECT pp.rowid FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid";
2795 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2796 $sql .= " AND price_level = " . ((int) $price_level);
2797 }
2798 $sql .= " ORDER BY date_price";
2799 $sql .= " DESC LIMIT 1) as price_rowid";
2800 $sql .= ", (SELECT pp.price_by_qty FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid"; // price_by_qty is 1 if some prices by qty exists in subtable
2801 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2802 $sql .= " AND price_level = " . ((int) $price_level);
2803 }
2804 $sql .= " ORDER BY date_price";
2805 $sql .= " DESC LIMIT 1) as price_by_qty";
2806 $selectFields .= ", price_rowid, price_by_qty";
2807 }
2808
2809 $sql .= " FROM ".$this->db->prefix()."product as p";
2810 // Add from (left join) from hooks
2811 $parameters = array();
2812 $reshook = $hookmanager->executeHooks('selectProductsListFrom', $parameters); // Note that $action and $object may have been modified by hook
2813 $sql .= $hookmanager->resPrint;
2814
2815 if (count($warehouseStatusArray)) {
2816 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_stock as ps on ps.fk_product = p.rowid";
2817 $sql .= " LEFT JOIN " . $this->db->prefix() . "entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (" . getEntity('stock') . ")";
2818 $sql .= ' AND e.statut IN (' . $this->db->sanitize($this->db->escape(implode(',', $warehouseStatusArray))) . ')'; // Return line if product is inside the selected stock. If not, an empty line will be returned so we will count 0.
2819 }
2820
2821 // include search in supplier ref
2822 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
2823 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
2824 }
2825
2826 //Price by customer
2827 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2828 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_customer_price as pcp ON pcp.fk_soc=" . ((int) $socid) . " AND pcp.fk_product=p.rowid";
2829 }
2830 // Units
2831 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2832 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
2833 }
2834 // Multilang : we add translation
2835 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2836 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_lang as pl ON pl.fk_product = p.rowid ";
2837 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE') && !empty($socid)) {
2838 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
2839 $soc = new Societe($this->db);
2840 $result = $soc->fetch($socid);
2841 if ($result > 0 && !empty($soc->default_lang)) {
2842 $sql .= " AND pl.lang = '" . $this->db->escape($soc->default_lang) . "'";
2843 } else {
2844 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
2845 }
2846 } else {
2847 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
2848 }
2849 }
2850
2851 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
2852 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_attribute_combination pac ON pac.fk_product_child = p.rowid";
2853 }
2854
2855 $sql .= ' WHERE p.entity IN (' . getEntity('product') . ')';
2856
2857 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
2858 $sql .= " AND pac.rowid IS NULL";
2859 }
2860
2861 if ($finished == 0) {
2862 $sql .= " AND p.finished = " . ((int) $finished);
2863 } elseif ($finished == 1) {
2864 $sql .= " AND p.finished = ".((int) $finished);
2865 }
2866 if ($status >= 0) {
2867 $sql .= " AND p.tosell = ".((int) $status);
2868 }
2869 if ($status_purchase >= 0) {
2870 $sql .= " AND p.tobuy = " . ((int) $status_purchase);
2871 }
2872 // Filter by product type
2873 if (strval($filtertype) != '') {
2874 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
2875 } elseif (!isModEnabled('product')) { // when product module is disabled, show services only
2876 $sql .= " AND p.fk_product_type = 1";
2877 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
2878 $sql .= " AND p.fk_product_type = 0";
2879 }
2880 // Add where from hooks
2881 $parameters = array();
2882 $reshook = $hookmanager->executeHooks('selectProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
2883 $sql .= $hookmanager->resPrint;
2884 // Add criteria on ref/label
2885 if ($filterkey != '') {
2886 $sql .= ' AND (';
2887 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
2888 // For natural search
2889 $scrit = explode(' ', $filterkey);
2890 $i = 0;
2891 if (count($scrit) > 1) {
2892 $sql .= "(";
2893 }
2894 foreach ($scrit as $crit) {
2895 if ($i > 0) {
2896 $sql .= " AND ";
2897 }
2898 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2899 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2900 $sql .= " OR pl.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2901 }
2902 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2903 $sql .= " OR pcp.ref_customer LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2904 }
2905 if (getDolGlobalString('PRODUCT_AJAX_SEARCH_ON_DESCRIPTION')) {
2906 $sql .= " OR p.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2907 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2908 $sql .= " OR pl.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2909 }
2910 }
2911 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
2912 $sql .= " OR pfp.ref_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2913 }
2914 $sql .= ")";
2915 $i++;
2916 }
2917 if (count($scrit) > 1) {
2918 $sql .= ")";
2919 }
2920 if (isModEnabled('barcode')) {
2921 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
2922 }
2923 $sql .= ')';
2924 }
2925 if (count($warehouseStatusArray)) {
2926 $sql .= " GROUP BY " . $selectFields;
2927 }
2928
2929 //Sort by category
2930 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
2931 $sql .= " ORDER BY categorie_product_id ";
2932 //ASC OR DESC order
2933 (getDolGlobalInt('PRODUCT_SORT_BY_CATEGORY') == 1) ? $sql .= "ASC" : $sql .= "DESC";
2934 } else {
2935 $sql .= $this->db->order("p.ref");
2936 }
2937
2938 $sql .= $this->db->plimit($limit, 0);
2939
2940 // Build output string
2941 dol_syslog(get_class($this) . "::select_produits_list search products", LOG_DEBUG);
2942 $result = $this->db->query($sql);
2943 if ($result) {
2944 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2945 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
2946 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
2947
2948 $num = $this->db->num_rows($result);
2949
2950 $events = null;
2951
2952 if (!$forcecombo) {
2953 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2954 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
2955 }
2956
2957 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
2958
2959 $textifempty = '';
2960 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
2961 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
2962 if (getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
2963 if ($showempty && !is_numeric($showempty)) {
2964 $textifempty = $langs->trans($showempty);
2965 } else {
2966 $textifempty .= $langs->trans("All");
2967 }
2968 } else {
2969 if ($showempty && !is_numeric($showempty)) {
2970 $textifempty = $langs->trans($showempty);
2971 }
2972 }
2973 if ($showempty) {
2974 $out .= '<option value="-1" selected>' . ($textifempty ? $textifempty : '&nbsp;') . '</option>';
2975 }
2976
2977 $i = 0;
2978 while ($num && $i < $num) {
2979 $opt = '';
2980 $optJson = array();
2981 $objp = $this->db->fetch_object($result);
2982
2983 if ((getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) && !empty($objp->price_by_qty) && $objp->price_by_qty == 1) { // Price by quantity will return many prices for the same product
2984 $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type";
2985 $sql .= " FROM " . $this->db->prefix() . "product_price_by_qty";
2986 $sql .= " WHERE fk_product_price = " . ((int) $objp->price_rowid);
2987 $sql .= " ORDER BY quantity ASC";
2988
2989 dol_syslog(get_class($this) . "::select_produits_list search prices by qty", LOG_DEBUG);
2990 $result2 = $this->db->query($sql);
2991 if ($result2) {
2992 $nb_prices = $this->db->num_rows($result2);
2993 $j = 0;
2994 while ($nb_prices && $j < $nb_prices) {
2995 $objp2 = $this->db->fetch_object($result2);
2996
2997 $objp->price_by_qty_rowid = $objp2->rowid;
2998 $objp->price_by_qty_price_base_type = $objp2->price_base_type;
2999 $objp->price_by_qty_quantity = $objp2->quantity;
3000 $objp->price_by_qty_unitprice = $objp2->unitprice;
3001 $objp->price_by_qty_remise_percent = $objp2->remise_percent;
3002 // For backward compatibility
3003 $objp->quantity = $objp2->quantity;
3004 $objp->price = $objp2->price;
3005 $objp->unitprice = $objp2->unitprice;
3006 $objp->remise_percent = $objp2->remise_percent;
3007
3008 //$objp->tva_tx is not overwritten by $objp2 value
3009 //$objp->default_vat_code is not overwritten by $objp2 value
3010
3011 $this->constructProductListOption($objp, $opt, $optJson, 0, $selected, $hidepriceinlabel, $filterkey);
3012
3013 $j++;
3014
3015 // Add new entry
3016 // "key" value of json key array is used by jQuery automatically as selected value
3017 // "label" value of json key array is used by jQuery automatically as text for combo box
3018 $out .= $opt;
3019 array_push($outarray, $optJson);
3020 }
3021 }
3022 } else {
3023 if (isModEnabled('dynamicprices') && !empty($objp->fk_price_expression)) {
3024 $price_product = new Product($this->db);
3025 $price_product->fetch($objp->rowid, '', '', 1);
3026
3027 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3028 $priceparser = new PriceParser($this->db);
3029 $price_result = $priceparser->parseProduct($price_product);
3030 if ($price_result >= 0) {
3031 $objp->price = $price_result;
3032 $objp->unitprice = $price_result;
3033 //Calculate the VAT
3034 $objp->price_ttc = price2num($objp->price) * (1 + ($objp->tva_tx / 100));
3035 $objp->price_ttc = price2num($objp->price_ttc, 'MU');
3036 }
3037 }
3038
3039 $this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected, $hidepriceinlabel, $filterkey);
3040 // Add new entry
3041 // "key" value of json key array is used by jQuery automatically as selected value
3042 // "label" value of json key array is used by jQuery automatically as text for combo box
3043 $out .= $opt;
3044 array_push($outarray, $optJson);
3045 }
3046
3047 $i++;
3048 }
3049
3050 $out .= '</select>';
3051
3052 $this->db->free($result);
3053
3054 if (empty($outputmode)) {
3055 return $out;
3056 }
3057
3058 return $outarray;
3059 } else {
3060 dol_print_error($this->db);
3061 }
3062
3063 return '';
3064 }
3065
3081 protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0)
3082 {
3083 global $langs, $conf, $user;
3084 global $hookmanager;
3085
3086 $outkey = '';
3087 $outval = '';
3088 $outref = '';
3089 $outlabel = '';
3090 $outlabel_translated = '';
3091 $outdesc = '';
3092 $outdesc_translated = '';
3093 $outbarcode = '';
3094 $outorigin = '';
3095 $outtype = '';
3096 $outprice_ht = '';
3097 $outprice_ttc = '';
3098 $outpricebasetype = '';
3099 $outtva_tx = '';
3100 $outdefault_vat_code = '';
3101 $outqty = 1;
3102 $outdiscount = 0;
3103
3104 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3105
3106 $label = $objp->label;
3107 if (!empty($objp->label_translated)) {
3108 $label = $objp->label_translated;
3109 }
3110 if (!empty($filterkey) && $filterkey != '') {
3111 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3112 }
3113
3114 $outkey = $objp->rowid;
3115 $outref = $objp->ref;
3116 $outrefcust = empty($objp->custref) ? '' : $objp->custref;
3117 $outlabel = $objp->label;
3118 $outdesc = $objp->description;
3119 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3120 $outlabel_translated = $objp->label_translated;
3121 $outdesc_translated = $objp->description_translated;
3122 }
3123 $outbarcode = $objp->barcode;
3124 $outorigin = $objp->fk_country;
3125 $outpbq = empty($objp->price_by_qty_rowid) ? '' : $objp->price_by_qty_rowid;
3126
3127 $outtype = $objp->fk_product_type;
3128 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3129 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3130
3131 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3132 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
3133 }
3134
3135 // Units
3136 $outvalUnits = '';
3137 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3138 if (!empty($objp->unit_short)) {
3139 $outvalUnits .= ' - ' . $objp->unit_short;
3140 }
3141 }
3142 if (getDolGlobalString('PRODUCT_SHOW_DIMENSIONS_IN_COMBO')) {
3143 if (!empty($objp->weight) && $objp->weight_units !== null) {
3144 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3145 $outvalUnits .= ' - ' . $unitToShow;
3146 }
3147 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3148 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3149 $outvalUnits .= ' - ' . $unitToShow;
3150 }
3151 if (!empty($objp->surface) && $objp->surface_units !== null) {
3152 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3153 $outvalUnits .= ' - ' . $unitToShow;
3154 }
3155 if (!empty($objp->volume) && $objp->volume_units !== null) {
3156 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3157 $outvalUnits .= ' - ' . $unitToShow;
3158 }
3159 }
3160 if ($outdurationvalue && $outdurationunit) {
3161 $da = array(
3162 'h' => $langs->trans('Hour'),
3163 'd' => $langs->trans('Day'),
3164 'w' => $langs->trans('Week'),
3165 'm' => $langs->trans('Month'),
3166 'y' => $langs->trans('Year')
3167 );
3168 if (isset($da[$outdurationunit])) {
3169 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3170 }
3171 }
3172
3173 $opt = '<option value="' . $objp->rowid . '"';
3174 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
3175 if (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0) {
3176 $opt .= ' pbq="' . $objp->price_by_qty_rowid . '" data-pbq="' . $objp->price_by_qty_rowid . '" data-pbqup="' . $objp->price_by_qty_unitprice . '" data-pbqbase="' . $objp->price_by_qty_price_base_type . '" data-pbqqty="' . $objp->price_by_qty_quantity . '" data-pbqpercent="' . $objp->price_by_qty_remise_percent . '"';
3177 }
3178 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3179 if ($user->hasRight('stock', 'lire')) {
3180 if ($objp->stock > 0) {
3181 $opt .= ' class="product_line_stock_ok"';
3182 } elseif ($objp->stock <= 0) {
3183 $opt .= ' class="product_line_stock_too_low"';
3184 }
3185 }
3186 }
3187 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
3188 $opt .= ' data-labeltrans="' . $outlabel_translated . '"';
3189 $opt .= ' data-desctrans="' . dol_escape_htmltag($outdesc_translated) . '"';
3190 }
3191 $opt .= '>';
3192 $opt .= $objp->ref;
3193 if (!empty($objp->custref)) {
3194 $opt .= ' (' . $objp->custref . ')';
3195 }
3196 if ($outbarcode) {
3197 $opt .= ' (' . $outbarcode . ')';
3198 }
3199 $opt .= ' - ' . dol_trunc($label, $maxlengtharticle);
3200 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3201 $opt .= ' (' . getCountry($outorigin, 1) . ')';
3202 }
3203
3204 $objRef = $objp->ref;
3205 if (!empty($objp->custref)) {
3206 $objRef .= ' (' . $objp->custref . ')';
3207 }
3208 if (!empty($filterkey) && $filterkey != '') {
3209 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3210 }
3211 $outval .= $objRef;
3212 if ($outbarcode) {
3213 $outval .= ' (' . $outbarcode . ')';
3214 }
3215 $outval .= ' - ' . dol_trunc($label, $maxlengtharticle);
3216 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3217 $outval .= ' (' . getCountry($outorigin, 1) . ')';
3218 }
3219
3220 // Units
3221 $opt .= $outvalUnits;
3222 $outval .= $outvalUnits;
3223
3224 $found = 0;
3225
3226 // Multiprice
3227 // If we need a particular price level (from 1 to n)
3228 if (empty($hidepriceinlabel) && $price_level >= 1 && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3229 $sql = "SELECT price, price_ttc, price_base_type, tva_tx, default_vat_code";
3230 $sql .= " FROM " . $this->db->prefix() . "product_price";
3231 $sql .= " WHERE fk_product = " . ((int) $objp->rowid);
3232 $sql .= " AND entity IN (" . getEntity('productprice') . ")";
3233 $sql .= " AND price_level = " . ((int) $price_level);
3234 $sql .= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid.
3235 $sql .= " LIMIT 1";
3236
3237 dol_syslog(get_class($this) . '::constructProductListOption search price for product ' . $objp->rowid . ' AND level ' . $price_level, LOG_DEBUG);
3238 $result2 = $this->db->query($sql);
3239 if ($result2) {
3240 $objp2 = $this->db->fetch_object($result2);
3241 if ($objp2) {
3242 $found = 1;
3243 if ($objp2->price_base_type == 'HT') {
3244 $opt .= ' - ' . price($objp2->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3245 $outval .= ' - ' . price($objp2->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3246 } else {
3247 $opt .= ' - ' . price($objp2->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3248 $outval .= ' - ' . price($objp2->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3249 }
3250 $outprice_ht = price($objp2->price);
3251 $outprice_ttc = price($objp2->price_ttc);
3252 $outpricebasetype = $objp2->price_base_type;
3253 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
3254 $outtva_tx = $objp2->tva_tx; // We use the vat rate on line of multiprice
3255 $outdefault_vat_code = $objp2->default_vat_code; // We use the vat code on line of multiprice
3256 } else {
3257 $outtva_tx = $objp->tva_tx; // We use the vat rate of product, not the one on line of multiprice
3258 $outdefault_vat_code = $objp->default_vat_code; // We use the vat code or product, not the one on line of multiprice
3259 }
3260 }
3261 } else {
3262 dol_print_error($this->db);
3263 }
3264 }
3265
3266 // Price by quantity
3267 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1 && (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3268 $found = 1;
3269 $outqty = $objp->quantity;
3270 $outdiscount = $objp->remise_percent;
3271 if ($objp->quantity == 1) {
3272 $opt .= ' - ' . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/";
3273 $outval .= ' - ' . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/";
3274 $opt .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3275 $outval .= $langs->transnoentities("Unit");
3276 } else {
3277 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3278 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3279 $opt .= $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3280 $outval .= $langs->transnoentities("Units");
3281 }
3282
3283 $outprice_ht = price($objp->unitprice);
3284 $outprice_ttc = price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
3285 $outpricebasetype = $objp->price_base_type;
3286 $outtva_tx = $objp->tva_tx; // This value is the value on product when constructProductListOption is called by select_produits_list even if other field $objp-> are from table price_by_qty
3287 $outdefault_vat_code = $objp->default_vat_code; // This value is the value on product when constructProductListOption is called by select_produits_list even if other field $objp-> are from table price_by_qty
3288 }
3289 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1) {
3290 $opt .= " (" . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3291 $outval .= " (" . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3292 }
3293 if (empty($hidepriceinlabel) && !empty($objp->remise_percent) && $objp->remise_percent >= 1) {
3294 $opt .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3295 $outval .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3296 }
3297
3298 // Price by customer
3299 if (empty($hidepriceinlabel) && getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
3300 if (!empty($objp->idprodcustprice)) {
3301 $found = 1;
3302
3303 if ($objp->custprice_base_type == 'HT') {
3304 $opt .= ' - ' . price($objp->custprice, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3305 $outval .= ' - ' . price($objp->custprice, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3306 } else {
3307 $opt .= ' - ' . price($objp->custprice_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3308 $outval .= ' - ' . price($objp->custprice_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3309 }
3310
3311 $outprice_ht = price($objp->custprice);
3312 $outprice_ttc = price($objp->custprice_ttc);
3313 $outpricebasetype = $objp->custprice_base_type;
3314 $outtva_tx = $objp->custtva_tx;
3315 $outdefault_vat_code = $objp->custdefault_vat_code;
3316 }
3317 }
3318
3319 // If level no defined or multiprice not found, we used the default price
3320 if (empty($hidepriceinlabel) && !$found) {
3321 if ($objp->price_base_type == 'HT') {
3322 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3323 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3324 } else {
3325 $opt .= ' - ' . price($objp->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3326 $outval .= ' - ' . price($objp->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3327 }
3328 $outprice_ht = price($objp->price);
3329 $outprice_ttc = price($objp->price_ttc);
3330 $outpricebasetype = $objp->price_base_type;
3331 $outtva_tx = $objp->tva_tx;
3332 $outdefault_vat_code = $objp->default_vat_code;
3333 }
3334
3335 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3336 if ($user->hasRight('stock', 'lire')) {
3337 $opt .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3338
3339 if ($objp->stock > 0) {
3340 $outval .= ' - <span class="product_line_stock_ok">';
3341 } elseif ($objp->stock <= 0) {
3342 $outval .= ' - <span class="product_line_stock_too_low">';
3343 }
3344 $outval .= $langs->transnoentities("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3345 $outval .= '</span>';
3346 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3347 $langs->load("stocks");
3348
3349 $tmpproduct = new Product($this->db);
3350 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3351 $tmpproduct->load_virtual_stock();
3352 $virtualstock = $tmpproduct->stock_theorique;
3353
3354 $opt .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3355
3356 $outval .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3357 if ($virtualstock > 0) {
3358 $outval .= '<span class="product_line_stock_ok">';
3359 } elseif ($virtualstock <= 0) {
3360 $outval .= '<span class="product_line_stock_too_low">';
3361 }
3362 $outval .= $virtualstock;
3363 $outval .= '</span>';
3364
3365 unset($tmpproduct);
3366 }
3367 }
3368 }
3369
3370 $parameters = array('objp'=>$objp);
3371 $reshook = $hookmanager->executeHooks('constructProductListOption', $parameters); // Note that $action and $object may have been modified by hook
3372 if (empty($reshook)) {
3373 $opt .= $hookmanager->resPrint;
3374 } else {
3375 $opt = $hookmanager->resPrint;
3376 }
3377
3378 $opt .= "</option>\n";
3379 $optJson = array(
3380 'key' => $outkey,
3381 'value' => $outref,
3382 'label' => $outval,
3383 'label2' => $outlabel,
3384 'desc' => $outdesc,
3385 'type' => $outtype,
3386 'price_ht' => price2num($outprice_ht),
3387 'price_ttc' => price2num($outprice_ttc),
3388 'price_ht_locale' => price(price2num($outprice_ht)),
3389 'price_ttc_locale' => price(price2num($outprice_ttc)),
3390 'pricebasetype' => $outpricebasetype,
3391 'tva_tx' => $outtva_tx,
3392 'default_vat_code' => $outdefault_vat_code,
3393 'qty' => $outqty,
3394 'discount' => $outdiscount,
3395 'duration_value' => $outdurationvalue,
3396 'duration_unit' => $outdurationunit,
3397 'pbq' => $outpbq,
3398 'labeltrans' => $outlabel_translated,
3399 'desctrans' => $outdesc_translated,
3400 'ref_customer' => $outrefcust
3401 );
3402 }
3403
3404 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3405
3421 public function select_produits_fournisseurs($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $ajaxoptions = array(), $hidelabel = 0, $alsoproductwithnosupplierprice = 0, $morecss = '', $placeholder = '')
3422 {
3423 // phpcs:enable
3424 global $langs, $conf;
3425 global $price_level, $status, $finished;
3426
3427 if (!isset($status)) {
3428 $status = 1;
3429 }
3430
3431 $selected_input_value = '';
3432 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3433 if ($selected > 0) {
3434 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3435 $producttmpselect = new Product($this->db);
3436 $producttmpselect->fetch($selected);
3437 $selected_input_value = $producttmpselect->ref;
3438 unset($producttmpselect);
3439 }
3440
3441 // mode=2 means suppliers products
3442 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=2&status=' . $status . '&finished=' . $finished . '&alsoproductwithnosupplierprice=' . $alsoproductwithnosupplierprice;
3443 print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
3444
3445 print($hidelabel ? '' : $langs->trans("RefOrLabel") . ' : ') . '<input type="text" class="minwidth300" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . $placeholder . '"' : '') . '>';
3446 } else {
3447 print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', $status, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder);
3448 }
3449 }
3450
3451 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3452
3471 public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '', $showstockinlist = 0, $placeholder = '')
3472 {
3473 // phpcs:enable
3474 global $langs, $conf, $user;
3475 global $hookmanager;
3476
3477 $out = '';
3478 $outarray = array();
3479
3480 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3481
3482 $langs->load('stocks');
3483 // Units
3484 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3485 $langs->load('other');
3486 }
3487
3488 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, p.fk_product_type, p.stock, p.tva_tx as tva_tx_sale, p.default_vat_code as default_vat_code_sale,";
3489 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice,";
3490 $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.default_vat_code, pfp.fk_soc, s.nom as name,";
3491 $sql .= " pfp.supplier_reputation";
3492 // if we use supplier description of the products
3493 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3494 $sql .= ", pfp.desc_fourn as description";
3495 } else {
3496 $sql .= ", p.description";
3497 }
3498 // Units
3499 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3500 $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";
3501 }
3502 if (isModEnabled('barcode')) {
3503 $sql .= ", pfp.barcode";
3504 }
3505 $sql .= " FROM " . $this->db->prefix() . "product as p";
3506 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (" . getEntity('product') . ") )";
3507 if ($socid > 0) {
3508 $sql .= " AND pfp.fk_soc = " . ((int) $socid);
3509 }
3510 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3511 // Units
3512 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3513 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3514 }
3515 $sql .= " WHERE p.entity IN (" . getEntity('product') . ")";
3516 if ($statut != -1) {
3517 $sql .= " AND p.tobuy = " . ((int) $statut);
3518 }
3519 if (strval($filtertype) != '') {
3520 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3521 }
3522 if (!empty($filtre)) {
3523 $sql .= " " . $filtre;
3524 }
3525 // Add where from hooks
3526 $parameters = array();
3527 $reshook = $hookmanager->executeHooks('selectSuppliersProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3528 $sql .= $hookmanager->resPrint;
3529 // Add criteria on ref/label
3530 if ($filterkey != '') {
3531 $sql .= ' AND (';
3532 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3533 // For natural search
3534 $scrit = explode(' ', $filterkey);
3535 $i = 0;
3536 if (count($scrit) > 1) {
3537 $sql .= "(";
3538 }
3539 foreach ($scrit as $crit) {
3540 if ($i > 0) {
3541 $sql .= " AND ";
3542 }
3543 $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) . "%'";
3544 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3545 $sql .= " OR pfp.desc_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3546 }
3547 $sql .= ")";
3548 $i++;
3549 }
3550 if (count($scrit) > 1) {
3551 $sql .= ")";
3552 }
3553 if (isModEnabled('barcode')) {
3554 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3555 $sql .= " OR pfp.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3556 }
3557 $sql .= ')';
3558 }
3559 $sql .= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC";
3560 $sql .= $this->db->plimit($limit, 0);
3561
3562 // Build output string
3563
3564 dol_syslog(get_class($this) . "::select_produits_fournisseurs_list", LOG_DEBUG);
3565 $result = $this->db->query($sql);
3566 if ($result) {
3567 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3568 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3569
3570 $num = $this->db->num_rows($result);
3571
3572 //$out.='<select class="flat" id="select'.$htmlname.'" name="'.$htmlname.'">'; // remove select to have id same with combo and ajax
3573 $out .= '<select class="flat ' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '">';
3574 if (!$selected) {
3575 $out .= '<option value="-1" selected>' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3576 } else {
3577 $out .= '<option value="-1">' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3578 }
3579
3580 $i = 0;
3581 while ($i < $num) {
3582 $objp = $this->db->fetch_object($result);
3583
3584 if (is_null($objp->idprodfournprice)) {
3585 // There is no supplier price found, we will use the vat rate for sale
3586 $objp->tva_tx = $objp->tva_tx_sale;
3587 $objp->default_vat_code = $objp->default_vat_code_sale;
3588 }
3589
3590 $outkey = $objp->idprodfournprice; // id in table of price
3591 if (!$outkey && $alsoproductwithnosupplierprice) {
3592 $outkey = 'idprod_' . $objp->rowid; // id of product
3593 }
3594
3595 $outref = $objp->ref;
3596 $outbarcode = $objp->barcode;
3597 $outqty = 1;
3598 $outdiscount = 0;
3599 $outtype = $objp->fk_product_type;
3600 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3601 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3602
3603 // Units
3604 $outvalUnits = '';
3605 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3606 if (!empty($objp->unit_short)) {
3607 $outvalUnits .= ' - ' . $objp->unit_short;
3608 }
3609 if (!empty($objp->weight) && $objp->weight_units !== null) {
3610 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3611 $outvalUnits .= ' - ' . $unitToShow;
3612 }
3613 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3614 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3615 $outvalUnits .= ' - ' . $unitToShow;
3616 }
3617 if (!empty($objp->surface) && $objp->surface_units !== null) {
3618 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3619 $outvalUnits .= ' - ' . $unitToShow;
3620 }
3621 if (!empty($objp->volume) && $objp->volume_units !== null) {
3622 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3623 $outvalUnits .= ' - ' . $unitToShow;
3624 }
3625 if ($outdurationvalue && $outdurationunit) {
3626 $da = array(
3627 'h' => $langs->trans('Hour'),
3628 'd' => $langs->trans('Day'),
3629 'w' => $langs->trans('Week'),
3630 'm' => $langs->trans('Month'),
3631 'y' => $langs->trans('Year')
3632 );
3633 if (isset($da[$outdurationunit])) {
3634 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3635 }
3636 }
3637 }
3638
3639 $objRef = $objp->ref;
3640 if ($filterkey && $filterkey != '') {
3641 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3642 }
3643 $objRefFourn = $objp->ref_fourn;
3644 if ($filterkey && $filterkey != '') {
3645 $objRefFourn = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRefFourn, 1);
3646 }
3647 $label = $objp->label;
3648 if ($filterkey && $filterkey != '') {
3649 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3650 }
3651
3652 switch ($objp->fk_product_type) {
3654 $picto = 'product';
3655 break;
3657 $picto = 'service';
3658 break;
3659 default:
3660 $picto = '';
3661 break;
3662 }
3663
3664 if (empty($picto)) {
3665 $optlabel = '';
3666 } else {
3667 $optlabel = img_object('', $picto, 'class="paddingright classfortooltip"', 0, 0, 1);
3668 }
3669
3670 $optlabel .= $objp->ref;
3671 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3672 $optlabel .= ' <span class="opacitymedium">(' . $objp->ref_fourn . ')</span>';
3673 }
3674 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3675 $optlabel .= ' (' . $outbarcode . ')';
3676 }
3677 $optlabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3678
3679 $outvallabel = $objRef;
3680 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3681 $outvallabel .= ' (' . $objRefFourn . ')';
3682 }
3683 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3684 $outvallabel .= ' (' . $outbarcode . ')';
3685 }
3686 $outvallabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3687
3688 // Units
3689 $optlabel .= $outvalUnits;
3690 $outvallabel .= $outvalUnits;
3691
3692 if (!empty($objp->idprodfournprice)) {
3693 $outqty = $objp->quantity;
3694 $outdiscount = $objp->remise_percent;
3695 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3696 $prod_supplier = new ProductFournisseur($this->db);
3697 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3698 $prod_supplier->id = $objp->fk_product;
3699 $prod_supplier->fourn_qty = $objp->quantity;
3700 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3701 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3702
3703 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3704 $priceparser = new PriceParser($this->db);
3705 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3706 if ($price_result >= 0) {
3707 $objp->fprice = $price_result;
3708 if ($objp->quantity >= 1) {
3709 $objp->unitprice = $objp->fprice / $objp->quantity; // Replace dynamically unitprice
3710 }
3711 }
3712 }
3713 if ($objp->quantity == 1) {
3714 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3715 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/";
3716 $optlabel .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3717 $outvallabel .= $langs->transnoentities("Unit");
3718 } else {
3719 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3720 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3721 $optlabel .= ' ' . $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3722 $outvallabel .= ' ' . $langs->transnoentities("Units");
3723 }
3724
3725 if ($objp->quantity > 1) {
3726 $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
3727 $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
3728 }
3729 if ($objp->remise_percent >= 1) {
3730 $optlabel .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3731 $outvallabel .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3732 }
3733 if ($objp->duration) {
3734 $optlabel .= " - " . $objp->duration;
3735 $outvallabel .= " - " . $objp->duration;
3736 }
3737 if (!$socid) {
3738 $optlabel .= " - " . dol_trunc($objp->name, 8);
3739 $outvallabel .= " - " . dol_trunc($objp->name, 8);
3740 }
3741 if ($objp->supplier_reputation) {
3742 //TODO dictionary
3743 $reputations = array('' => $langs->trans('Standard'), 'FAVORITE' => $langs->trans('Favorite'), 'NOTTHGOOD' => $langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER' => $langs->trans('DoNotOrderThisProductToThisSupplier'));
3744
3745 $optlabel .= " - " . $reputations[$objp->supplier_reputation];
3746 $outvallabel .= " - " . $reputations[$objp->supplier_reputation];
3747 }
3748 } else {
3749 if (empty($alsoproductwithnosupplierprice)) { // No supplier price defined for couple product/supplier
3750 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3751 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3752 } else { // No supplier price defined for product, even on other suppliers
3753 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3754 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3755 }
3756 }
3757
3758 if (isModEnabled('stock') && $showstockinlist && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3759 $novirtualstock = ($showstockinlist == 2);
3760
3761 if ($user->hasRight('stock', 'lire')) {
3762 $outvallabel .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3763
3764 if ($objp->stock > 0) {
3765 $optlabel .= ' - <span class="product_line_stock_ok">';
3766 } elseif ($objp->stock <= 0) {
3767 $optlabel .= ' - <span class="product_line_stock_too_low">';
3768 }
3769 $optlabel .= $langs->transnoentities("Stock") . ':' . price(price2num($objp->stock, 'MS'));
3770 $optlabel .= '</span>';
3771 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3772 $langs->load("stocks");
3773
3774 $tmpproduct = new Product($this->db);
3775 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3776 $tmpproduct->load_virtual_stock();
3777 $virtualstock = $tmpproduct->stock_theorique;
3778
3779 $outvallabel .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3780
3781 $optlabel .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3782 if ($virtualstock > 0) {
3783 $optlabel .= '<span class="product_line_stock_ok">';
3784 } elseif ($virtualstock <= 0) {
3785 $optlabel .= '<span class="product_line_stock_too_low">';
3786 }
3787 $optlabel .= $virtualstock;
3788 $optlabel .= '</span>';
3789
3790 unset($tmpproduct);
3791 }
3792 }
3793 }
3794
3795 $optstart = '<option value="' . $outkey . '"';
3796 if ($selected && $selected == $objp->idprodfournprice) {
3797 $optstart .= ' selected';
3798 }
3799 if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) {
3800 $optstart .= ' disabled';
3801 }
3802
3803 if (!empty($objp->idprodfournprice) && $objp->idprodfournprice > 0) {
3804 $optstart .= ' data-product-id="' . dol_escape_htmltag($objp->rowid) . '"';
3805 $optstart .= ' data-price-id="' . dol_escape_htmltag($objp->idprodfournprice) . '"';
3806 $optstart .= ' data-qty="' . dol_escape_htmltag($objp->quantity) . '"';
3807 $optstart .= ' data-up="' . dol_escape_htmltag(price2num($objp->unitprice)) . '"';
3808 $optstart .= ' data-up-locale="' . dol_escape_htmltag(price($objp->unitprice)) . '"';
3809 $optstart .= ' data-discount="' . dol_escape_htmltag($outdiscount) . '"';
3810 $optstart .= ' data-tvatx="' . dol_escape_htmltag(price2num($objp->tva_tx)) . '"';
3811 $optstart .= ' data-tvatx-formated="' . dol_escape_htmltag(price($objp->tva_tx, 0, $langs, 1, -1, 2)) . '"';
3812 $optstart .= ' data-default-vat-code="' . dol_escape_htmltag($objp->default_vat_code) . '"';
3813 $optstart .= ' data-supplier-ref="' . dol_escape_htmltag($objp->ref_fourn) . '"';
3814 }
3815 $optstart .= ' data-description="' . dol_escape_htmltag($objp->description, 0, 1) . '"';
3816
3817 $outarrayentry = array(
3818 'key' => $outkey,
3819 'value' => $outref,
3820 'label' => $outvallabel,
3821 'qty' => $outqty,
3822 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
3823 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
3824 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
3825 'tva_tx_formated' => price($objp->tva_tx, 0, $langs, 1, -1, 2),
3826 'tva_tx' => price2num($objp->tva_tx),
3827 'default_vat_code' => $objp->default_vat_code,
3828 'discount' => $outdiscount,
3829 'type' => $outtype,
3830 'duration_value' => $outdurationvalue,
3831 'duration_unit' => $outdurationunit,
3832 'disabled' => (empty($objp->idprodfournprice) ? true : false),
3833 'description' => $objp->description
3834 );
3835
3836 $parameters = array(
3837 'objp' => &$objp,
3838 'optstart' => &$optstart,
3839 'optlabel' => &$optlabel,
3840 'outvallabel' => &$outvallabel,
3841 'outarrayentry' => &$outarrayentry
3842 );
3843 $reshook = $hookmanager->executeHooks('selectProduitsFournisseurListOption', $parameters, $this);
3844
3845
3846 // Add new entry
3847 // "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
3848 // "label" value of json key array is used by jQuery automatically as text for combo box
3849 $out .= $optstart . ' data-html="' . dol_escape_htmltag($optlabel) . '">' . $optlabel . "</option>\n";
3850 array_push(
3851 $outarray,
3852 array('key' => $outkey,
3853 'value' => $outref,
3854 'label' => $outvallabel,
3855 'qty' => $outqty,
3856 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
3857 'price_qty_ht_locale' => price($objp->fprice),
3858 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
3859 'price_unit_ht_locale' => price($objp->unitprice),
3860 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
3861 'tva_tx_formated' => price($objp->tva_tx),
3862 'tva_tx' => price2num($objp->tva_tx),
3863 'default_vat_code' => $objp->default_vat_code,
3864 'discount' => $outdiscount,
3865 'type' => $outtype,
3866 'duration_value' => $outdurationvalue,
3867 'duration_unit' => $outdurationunit,
3868 'disabled' => (empty($objp->idprodfournprice) ? true : false),
3869 'description' => $objp->description
3870 )
3871 );
3872 // Exemple of var_dump $outarray
3873 // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
3874 // ["label"]=>string(76) "ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
3875 // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false)
3876 //}
3877 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
3878 //$outval=array('label'=>'ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)');
3879 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
3880
3881 $i++;
3882 }
3883 $out .= '</select>';
3884
3885 $this->db->free($result);
3886
3887 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
3888 $out .= ajax_combobox($htmlname);
3889 } else {
3890 dol_print_error($this->db);
3891 }
3892
3893 if (empty($outputmode)) {
3894 return $out;
3895 }
3896 return $outarray;
3897 }
3898
3899 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3900
3909 public function select_product_fourn_price($productid, $htmlname = 'productfournpriceid', $selected_supplier = 0)
3910 {
3911 // phpcs:enable
3912 global $langs, $conf;
3913
3914 $langs->load('stocks');
3915
3916 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, pfp.fk_soc,";
3917 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,";
3918 $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name";
3919 $sql .= " FROM " . $this->db->prefix() . "product as p";
3920 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
3921 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3922 $sql .= " WHERE pfp.entity IN (" . getEntity('productsupplierprice') . ")";
3923 $sql .= " AND p.tobuy = 1";
3924 $sql .= " AND s.fournisseur = 1";
3925 $sql .= " AND p.rowid = " . ((int) $productid);
3926 if (!getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED')) {
3927 $sql .= " ORDER BY s.nom, pfp.ref_fourn DESC";
3928 } else {
3929 $sql .= " ORDER BY pfp.unitprice ASC";
3930 }
3931
3932 dol_syslog(get_class($this) . "::select_product_fourn_price", LOG_DEBUG);
3933 $result = $this->db->query($sql);
3934
3935 if ($result) {
3936 $num = $this->db->num_rows($result);
3937
3938 $form = '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
3939
3940 if (!$num) {
3941 $form .= '<option value="0">-- ' . $langs->trans("NoSupplierPriceDefinedForThisProduct") . ' --</option>';
3942 } else {
3943 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3944 $form .= '<option value="0">&nbsp;</option>';
3945
3946 $i = 0;
3947 while ($i < $num) {
3948 $objp = $this->db->fetch_object($result);
3949
3950 $opt = '<option value="' . $objp->idprodfournprice . '"';
3951 //if there is only one supplier, preselect it
3952 if ($num == 1 || ($selected_supplier > 0 && $objp->fk_soc == $selected_supplier) || ($i == 0 && getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED'))) {
3953 $opt .= ' selected';
3954 }
3955 $opt .= '>' . $objp->name . ' - ' . $objp->ref_fourn . ' - ';
3956
3957 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3958 $prod_supplier = new ProductFournisseur($this->db);
3959 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3960 $prod_supplier->id = $productid;
3961 $prod_supplier->fourn_qty = $objp->quantity;
3962 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3963 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3964
3965 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3966 $priceparser = new PriceParser($this->db);
3967 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3968 if ($price_result >= 0) {
3969 $objp->fprice = $price_result;
3970 if ($objp->quantity >= 1) {
3971 $objp->unitprice = $objp->fprice / $objp->quantity;
3972 }
3973 }
3974 }
3975 if ($objp->quantity == 1) {
3976 $opt .= price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3977 }
3978
3979 $opt .= $objp->quantity . ' ';
3980
3981 if ($objp->quantity == 1) {
3982 $opt .= $langs->trans("Unit");
3983 } else {
3984 $opt .= $langs->trans("Units");
3985 }
3986 if ($objp->quantity > 1) {
3987 $opt .= " - ";
3988 $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");
3989 }
3990 if ($objp->duration) {
3991 $opt .= " - " . $objp->duration;
3992 }
3993 $opt .= "</option>\n";
3994
3995 $form .= $opt;
3996 $i++;
3997 }
3998 }
3999
4000 $form .= '</select>';
4001 $this->db->free($result);
4002 return $form;
4003 } else {
4004 dol_print_error($this->db);
4005 return '';
4006 }
4007 }
4008
4009
4010 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4017 {
4018 // phpcs:enable
4019 global $langs;
4020
4021 $num = count($this->cache_conditions_paiements);
4022 if ($num > 0) {
4023 return 0; // Cache already loaded
4024 }
4025
4026 dol_syslog(__METHOD__, LOG_DEBUG);
4027
4028 $sql = "SELECT rowid, code, libelle as label, deposit_percent";
4029 $sql .= " FROM " . $this->db->prefix() . 'c_payment_term';
4030 $sql .= " WHERE entity IN (" . getEntity('c_payment_term') . ")";
4031 $sql .= " AND active > 0";
4032 $sql .= " ORDER BY sortorder";
4033
4034 $resql = $this->db->query($sql);
4035 if ($resql) {
4036 $num = $this->db->num_rows($resql);
4037 $i = 0;
4038 while ($i < $num) {
4039 $obj = $this->db->fetch_object($resql);
4040
4041 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4042 $label = ($langs->trans("PaymentConditionShort" . $obj->code) != "PaymentConditionShort" . $obj->code ? $langs->trans("PaymentConditionShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4043 $this->cache_conditions_paiements[$obj->rowid]['code'] = $obj->code;
4044 $this->cache_conditions_paiements[$obj->rowid]['label'] = $label;
4045 $this->cache_conditions_paiements[$obj->rowid]['deposit_percent'] = $obj->deposit_percent;
4046 $i++;
4047 }
4048
4049 //$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1); // We use the field sortorder of table
4050
4051 return $num;
4052 } else {
4053 dol_print_error($this->db);
4054 return -1;
4055 }
4056 }
4057
4058 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4059
4065 public function load_cache_availability()
4066 {
4067 // phpcs:enable
4068 global $langs;
4069
4070 $num = count($this->cache_availability); // TODO Use $conf->cache['availability'] instead of $this->cache_availability
4071 if ($num > 0) {
4072 return 0; // Cache already loaded
4073 }
4074
4075 dol_syslog(__METHOD__, LOG_DEBUG);
4076
4077 $langs->load('propal');
4078
4079 $sql = "SELECT rowid, code, label, position";
4080 $sql .= " FROM " . $this->db->prefix() . 'c_availability';
4081 $sql .= " WHERE active > 0";
4082
4083 $resql = $this->db->query($sql);
4084 if ($resql) {
4085 $num = $this->db->num_rows($resql);
4086 $i = 0;
4087 while ($i < $num) {
4088 $obj = $this->db->fetch_object($resql);
4089
4090 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4091 $label = ($langs->trans("AvailabilityType" . $obj->code) != "AvailabilityType" . $obj->code ? $langs->trans("AvailabilityType" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4092 $this->cache_availability[$obj->rowid]['code'] = $obj->code;
4093 $this->cache_availability[$obj->rowid]['label'] = $label;
4094 $this->cache_availability[$obj->rowid]['position'] = $obj->position;
4095 $i++;
4096 }
4097
4098 $this->cache_availability = dol_sort_array($this->cache_availability, 'position', 'asc', 0, 0, 1);
4099
4100 return $num;
4101 } else {
4102 dol_print_error($this->db);
4103 return -1;
4104 }
4105 }
4106
4117 public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0, $morecss = '')
4118 {
4119 global $langs, $user;
4120
4121 $this->load_cache_availability();
4122
4123 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4124
4125 print '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4126 if ($addempty) {
4127 print '<option value="0">&nbsp;</option>';
4128 }
4129 foreach ($this->cache_availability as $id => $arrayavailability) {
4130 if ($selected == $id) {
4131 print '<option value="' . $id . '" selected>';
4132 } else {
4133 print '<option value="' . $id . '">';
4134 }
4135 print dol_escape_htmltag($arrayavailability['label']);
4136 print '</option>';
4137 }
4138 print '</select>';
4139 if ($user->admin) {
4140 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4141 }
4142 print ajax_combobox($htmlname);
4143 }
4144
4150 public function loadCacheInputReason()
4151 {
4152 global $langs;
4153
4154 $num = count($this->cache_demand_reason); // TODO Use $conf->cache['input_reason'] instead of $this->cache_demand_reason
4155 if ($num > 0) {
4156 return 0; // Cache already loaded
4157 }
4158
4159 $sql = "SELECT rowid, code, label";
4160 $sql .= " FROM " . $this->db->prefix() . 'c_input_reason';
4161 $sql .= " WHERE active > 0";
4162
4163 $resql = $this->db->query($sql);
4164 if ($resql) {
4165 $num = $this->db->num_rows($resql);
4166 $i = 0;
4167 $tmparray = array();
4168 while ($i < $num) {
4169 $obj = $this->db->fetch_object($resql);
4170
4171 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4172 $label = ($obj->label != '-' ? $obj->label : '');
4173 if ($langs->trans("DemandReasonType" . $obj->code) != "DemandReasonType" . $obj->code) {
4174 $label = $langs->trans("DemandReasonType" . $obj->code); // So translation key DemandReasonTypeSRC_XXX will work
4175 }
4176 if ($langs->trans($obj->code) != $obj->code) {
4177 $label = $langs->trans($obj->code); // So translation key SRC_XXX will work
4178 }
4179
4180 $tmparray[$obj->rowid]['id'] = $obj->rowid;
4181 $tmparray[$obj->rowid]['code'] = $obj->code;
4182 $tmparray[$obj->rowid]['label'] = $label;
4183 $i++;
4184 }
4185
4186 $this->cache_demand_reason = dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1);
4187
4188 unset($tmparray);
4189 return $num;
4190 } else {
4191 dol_print_error($this->db);
4192 return -1;
4193 }
4194 }
4195
4208 public function selectInputReason($selected = '', $htmlname = 'demandreasonid', $exclude = '', $addempty = 0, $morecss = '', $notooltip = 0)
4209 {
4210 global $langs, $user;
4211
4212 $this->loadCacheInputReason();
4213
4214 print '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4215 if ($addempty) {
4216 print '<option value="0"' . (empty($selected) ? ' selected' : '') . '>&nbsp;</option>';
4217 }
4218 foreach ($this->cache_demand_reason as $id => $arraydemandreason) {
4219 if ($arraydemandreason['code'] == $exclude) {
4220 continue;
4221 }
4222
4223 if ($selected && ($selected == $arraydemandreason['id'] || $selected == $arraydemandreason['code'])) {
4224 print '<option value="' . $arraydemandreason['id'] . '" selected>';
4225 } else {
4226 print '<option value="' . $arraydemandreason['id'] . '">';
4227 }
4228 $label = $arraydemandreason['label']; // Translation of label was already done into the ->loadCacheInputReason
4229 print $langs->trans($label);
4230 print '</option>';
4231 }
4232 print '</select>';
4233 if ($user->admin && empty($notooltip)) {
4234 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4235 }
4236 print ajax_combobox('select_' . $htmlname);
4237 }
4238
4239 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4240
4247 {
4248 // phpcs:enable
4249 global $langs;
4250
4251 $num = count($this->cache_types_paiements); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_types_paiements
4252 if ($num > 0) {
4253 return $num; // Cache already loaded
4254 }
4255
4256 dol_syslog(__METHOD__, LOG_DEBUG);
4257
4258 $this->cache_types_paiements = array();
4259
4260 $sql = "SELECT id, code, libelle as label, type, active";
4261 $sql .= " FROM " . $this->db->prefix() . "c_paiement";
4262 $sql .= " WHERE entity IN (" . getEntity('c_paiement') . ")";
4263
4264 $resql = $this->db->query($sql);
4265 if ($resql) {
4266 $num = $this->db->num_rows($resql);
4267 $i = 0;
4268 while ($i < $num) {
4269 $obj = $this->db->fetch_object($resql);
4270
4271 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4272 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4273 $this->cache_types_paiements[$obj->id]['id'] = $obj->id;
4274 $this->cache_types_paiements[$obj->id]['code'] = $obj->code;
4275 $this->cache_types_paiements[$obj->id]['label'] = $label;
4276 $this->cache_types_paiements[$obj->id]['type'] = $obj->type;
4277 $this->cache_types_paiements[$obj->id]['active'] = $obj->active;
4278 $i++;
4279 }
4280
4281 $this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1);
4282
4283 return $num;
4284 } else {
4285 dol_print_error($this->db);
4286 return -1;
4287 }
4288 }
4289
4290
4291 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4292
4310 public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4311 {
4312 // phpcs:enable
4313 print $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, $noinfoadmin, $morecss, $deposit_percent);
4314 }
4315
4316
4333 public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4334 {
4335 global $langs, $user, $conf;
4336
4337 $out = '';
4338 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4339
4341
4342 // Set default value if not already set by caller
4343 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID')) {
4344 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TERM_ID", LOG_NOTICE);
4345 $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID;
4346 }
4347
4348 $out .= '<select id="' . $htmlname . '" class="flat selectpaymentterms' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4349 if ($addempty) {
4350 $out .= '<option value="0">&nbsp;</option>';
4351 }
4352
4353 $selectedDepositPercent = null;
4354
4355 foreach ($this->cache_conditions_paiements as $id => $arrayconditions) {
4356 if ($filtertype <= 0 && !empty($arrayconditions['deposit_percent'])) {
4357 continue;
4358 }
4359
4360 if ($selected == $id) {
4361 $selectedDepositPercent = $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'];
4362 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '" selected>';
4363 } else {
4364 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '">';
4365 }
4366 $label = $arrayconditions['label'];
4367
4368 if (!empty($arrayconditions['deposit_percent'])) {
4369 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'], $label);
4370 }
4371
4372 $out .= $label;
4373 $out .= '</option>';
4374 }
4375 $out .= '</select>';
4376 if ($user->admin && empty($noinfoadmin)) {
4377 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4378 }
4379 $out .= ajax_combobox($htmlname);
4380
4381 if ($deposit_percent >= 0) {
4382 $out .= ' <span id="' . $htmlname . '_deposit_percent_container"' . (empty($selectedDepositPercent) ? ' style="display: none"' : '') . '>';
4383 $out .= $langs->trans('DepositPercent') . ' : ';
4384 $out .= '<input id="' . $htmlname . '_deposit_percent" name="' . $htmlname . '_deposit_percent" class="maxwidth50" value="' . $deposit_percent . '" />';
4385 $out .= '</span>';
4386 $out .= '
4387 <script nonce="' . getNonce() . '">
4388 $(document).ready(function () {
4389 $("#' . $htmlname . '").change(function () {
4390 let $selected = $(this).find("option:selected");
4391 let depositPercent = $selected.attr("data-deposit_percent");
4392
4393 if (depositPercent.length > 0) {
4394 $("#' . $htmlname . '_deposit_percent_container").show().find("#' . $htmlname . '_deposit_percent").val(depositPercent);
4395 } else {
4396 $("#' . $htmlname . '_deposit_percent_container").hide();
4397 }
4398
4399 return true;
4400 });
4401 });
4402 </script>';
4403 }
4404
4405 return $out;
4406 }
4407
4408
4409 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4410
4427 public function select_types_paiements($selected = '', $htmlname = 'paiementtype', $filtertype = '', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '', $nooutput = 0)
4428 {
4429 // phpcs:enable
4430 global $langs, $user, $conf;
4431
4432 $out = '';
4433
4434 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
4435
4436 $filterarray = array();
4437 if ($filtertype == 'CRDT') {
4438 $filterarray = array(0, 2, 3);
4439 } elseif ($filtertype == 'DBIT') {
4440 $filterarray = array(1, 2, 3);
4441 } elseif ($filtertype != '' && $filtertype != '-1') {
4442 $filterarray = explode(',', $filtertype);
4443 }
4444
4446
4447 // Set default value if not already set by caller
4448 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID')) {
4449 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TYPE_ID", LOG_NOTICE);
4450 $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TYPE_ID;
4451 }
4452
4453 $out .= '<select id="select' . $htmlname . '" class="flat selectpaymenttypes' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4454 if ($empty) {
4455 $out .= '<option value="">&nbsp;</option>';
4456 }
4457 foreach ($this->cache_types_paiements as $id => $arraytypes) {
4458 // If not good status
4459 if ($active >= 0 && $arraytypes['active'] != $active) {
4460 continue;
4461 }
4462
4463 // On passe si on a demande de filtrer sur des modes de paiments particuliers
4464 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
4465 continue;
4466 }
4467
4468 // We discard empty line if showempty is on because an empty line has already been output.
4469 if ($empty && empty($arraytypes['code'])) {
4470 continue;
4471 }
4472
4473 if ($format == 0) {
4474 $out .= '<option value="' . $id . '"';
4475 } elseif ($format == 1) {
4476 $out .= '<option value="' . $arraytypes['code'] . '"';
4477 } elseif ($format == 2) {
4478 $out .= '<option value="' . $arraytypes['code'] . '"';
4479 } elseif ($format == 3) {
4480 $out .= '<option value="' . $id . '"';
4481 }
4482 // Print attribute selected or not
4483 if ($format == 1 || $format == 2) {
4484 if ($selected == $arraytypes['code']) {
4485 $out .= ' selected';
4486 }
4487 } else {
4488 if ($selected == $id) {
4489 $out .= ' selected';
4490 }
4491 }
4492 $out .= '>';
4493 $value = '';
4494 if ($format == 0) {
4495 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4496 } elseif ($format == 1) {
4497 $value = $arraytypes['code'];
4498 } elseif ($format == 2) {
4499 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4500 } elseif ($format == 3) {
4501 $value = $arraytypes['code'];
4502 }
4503 $out .= $value ? $value : '&nbsp;';
4504 $out .= '</option>';
4505 }
4506 $out .= '</select>';
4507 if ($user->admin && !$noadmininfo) {
4508 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4509 }
4510 $out .= ajax_combobox('select' . $htmlname);
4511
4512 if (empty($nooutput)) {
4513 print $out;
4514 } else {
4515 return $out;
4516 }
4517 }
4518
4519
4528 public function selectPriceBaseType($selected = '', $htmlname = 'price_base_type', $addjscombo = 0)
4529 {
4530 global $langs;
4531
4532 $return = '<select class="flat maxwidth100" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4533 $options = array(
4534 'HT' => $langs->trans("HT"),
4535 'TTC' => $langs->trans("TTC")
4536 );
4537 foreach ($options as $id => $value) {
4538 if ($selected == $id) {
4539 $return .= '<option value="' . $id . '" selected>' . $value;
4540 } else {
4541 $return .= '<option value="' . $id . '">' . $value;
4542 }
4543 $return .= '</option>';
4544 }
4545 $return .= '</select>';
4546 if ($addjscombo) {
4547 $return .= ajax_combobox('select_' . $htmlname);
4548 }
4549
4550 return $return;
4551 }
4552
4553 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4554
4561 {
4562 // phpcs:enable
4563 global $langs;
4564
4565 $num = count($this->cache_transport_mode); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_transport_mode
4566 if ($num > 0) {
4567 return $num; // Cache already loaded
4568 }
4569
4570 dol_syslog(__METHOD__, LOG_DEBUG);
4571
4572 $this->cache_transport_mode = array();
4573
4574 $sql = "SELECT rowid, code, label, active";
4575 $sql .= " FROM " . $this->db->prefix() . "c_transport_mode";
4576 $sql .= " WHERE entity IN (" . getEntity('c_transport_mode') . ")";
4577
4578 $resql = $this->db->query($sql);
4579 if ($resql) {
4580 $num = $this->db->num_rows($resql);
4581 $i = 0;
4582 while ($i < $num) {
4583 $obj = $this->db->fetch_object($resql);
4584
4585 // If traduction exist, we use it else we take the default label
4586 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4587 $this->cache_transport_mode[$obj->rowid]['rowid'] = $obj->rowid;
4588 $this->cache_transport_mode[$obj->rowid]['code'] = $obj->code;
4589 $this->cache_transport_mode[$obj->rowid]['label'] = $label;
4590 $this->cache_transport_mode[$obj->rowid]['active'] = $obj->active;
4591 $i++;
4592 }
4593
4594 $this->cache_transport_mode = dol_sort_array($this->cache_transport_mode, 'label', 'asc', 0, 0, 1);
4595
4596 return $num;
4597 } else {
4598 dol_print_error($this->db);
4599 return -1;
4600 }
4601 }
4602
4616 public function selectTransportMode($selected = '', $htmlname = 'transportmode', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '')
4617 {
4618 global $langs, $user;
4619
4620 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $format, LOG_DEBUG);
4621
4623
4624 print '<select id="select' . $htmlname . '" class="flat selectmodetransport' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4625 if ($empty) {
4626 print '<option value="">&nbsp;</option>';
4627 }
4628 foreach ($this->cache_transport_mode as $id => $arraytypes) {
4629 // If not good status
4630 if ($active >= 0 && $arraytypes['active'] != $active) {
4631 continue;
4632 }
4633
4634 // We discard empty line if showempty is on because an empty line has already been output.
4635 if ($empty && empty($arraytypes['code'])) {
4636 continue;
4637 }
4638
4639 if ($format == 0) {
4640 print '<option value="' . $id . '"';
4641 } elseif ($format == 1) {
4642 print '<option value="' . $arraytypes['code'] . '"';
4643 } elseif ($format == 2) {
4644 print '<option value="' . $arraytypes['code'] . '"';
4645 } elseif ($format == 3) {
4646 print '<option value="' . $id . '"';
4647 }
4648 // If text is selected, we compare with code, else with id
4649 if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) {
4650 print ' selected';
4651 } elseif ($selected == $id) {
4652 print ' selected';
4653 }
4654 print '>';
4655 $value = '';
4656 if ($format == 0) {
4657 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4658 } elseif ($format == 1) {
4659 $value = $arraytypes['code'];
4660 } elseif ($format == 2) {
4661 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4662 } elseif ($format == 3) {
4663 $value = $arraytypes['code'];
4664 }
4665 print $value ? $value : '&nbsp;';
4666 print '</option>';
4667 }
4668 print '</select>';
4669 if ($user->admin && !$noadmininfo) {
4670 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4671 }
4672 }
4673
4686 public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '', $noinfoadmin = 0, $morecss = '')
4687 {
4688 global $langs, $user;
4689
4690 $langs->load("admin");
4691 $langs->load("deliveries");
4692
4693 $sql = "SELECT rowid, code, libelle as label";
4694 $sql .= " FROM " . $this->db->prefix() . "c_shipment_mode";
4695 $sql .= " WHERE active > 0";
4696 if ($filtre) {
4697 $sql .= " AND " . $filtre;
4698 }
4699 $sql .= " ORDER BY libelle ASC";
4700
4701 dol_syslog(get_class($this) . "::selectShippingMode", LOG_DEBUG);
4702 $result = $this->db->query($sql);
4703 if ($result) {
4704 $num = $this->db->num_rows($result);
4705 $i = 0;
4706 if ($num) {
4707 print '<select id="select' . $htmlname . '" class="flat selectshippingmethod' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4708 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4709 print '<option value="-1">&nbsp;</option>';
4710 }
4711 while ($i < $num) {
4712 $obj = $this->db->fetch_object($result);
4713 if ($selected == $obj->rowid) {
4714 print '<option value="' . $obj->rowid . '" selected>';
4715 } else {
4716 print '<option value="' . $obj->rowid . '">';
4717 }
4718 print ($langs->trans("SendingMethod" . strtoupper($obj->code)) != "SendingMethod" . strtoupper($obj->code)) ? $langs->trans("SendingMethod" . strtoupper($obj->code)) : $obj->label;
4719 print '</option>';
4720 $i++;
4721 }
4722 print "</select>";
4723 if ($user->admin && empty($noinfoadmin)) {
4724 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4725 }
4726
4727 print ajax_combobox('select' . $htmlname);
4728 } else {
4729 print $langs->trans("NoShippingMethodDefined");
4730 }
4731 } else {
4732 dol_print_error($this->db);
4733 }
4734 }
4735
4745 public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0)
4746 {
4747 global $langs;
4748
4749 $langs->load("deliveries");
4750
4751 if ($htmlname != "none") {
4752 print '<form method="POST" action="' . $page . '">';
4753 print '<input type="hidden" name="action" value="setshippingmethod">';
4754 print '<input type="hidden" name="token" value="' . newToken() . '">';
4755 $this->selectShippingMethod($selected, $htmlname, '', $addempty);
4756 print '<input type="submit" class="button valignmiddle" value="' . $langs->trans("Modify") . '">';
4757 print '</form>';
4758 } else {
4759 if ($selected) {
4760 $code = $langs->getLabelFromKey($this->db, $selected, 'c_shipment_mode', 'rowid', 'code');
4761 print $langs->trans("SendingMethod" . strtoupper($code));
4762 } else {
4763 print "&nbsp;";
4764 }
4765 }
4766 }
4767
4776 public function selectSituationInvoices($selected = '', $socid = 0)
4777 {
4778 global $langs;
4779
4780 $langs->load('bills');
4781
4782 $opt = '<option value="" selected></option>';
4783 $sql = "SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc";
4784 $sql .= ' FROM ' . $this->db->prefix() . 'facture';
4785 $sql .= ' WHERE entity IN (' . getEntity('invoice') . ')';
4786 $sql .= ' AND situation_counter >= 1';
4787 $sql .= ' AND fk_soc = ' . (int) $socid;
4788 $sql .= ' AND type <> 2';
4789 $sql .= ' ORDER by situation_cycle_ref, situation_counter desc';
4790 $resql = $this->db->query($sql);
4791
4792 if ($resql && $this->db->num_rows($resql) > 0) {
4793 // Last seen cycle
4794 $ref = 0;
4795 while ($obj = $this->db->fetch_object($resql)) {
4796 //Same cycle ?
4797 if ($obj->situation_cycle_ref != $ref) {
4798 // Just seen this cycle
4799 $ref = $obj->situation_cycle_ref;
4800 //not final ?
4801 if ($obj->situation_final != 1) {
4802 //Not prov?
4803 if (substr($obj->ref, 1, 4) != 'PROV') {
4804 if ($selected == $obj->rowid) {
4805 $opt .= '<option value="' . $obj->rowid . '" selected>' . $obj->ref . '</option>';
4806 } else {
4807 $opt .= '<option value="' . $obj->rowid . '">' . $obj->ref . '</option>';
4808 }
4809 }
4810 }
4811 }
4812 }
4813 } else {
4814 dol_syslog("Error sql=" . $sql . ", error=" . $this->error, LOG_ERR);
4815 }
4816 if ($opt == '<option value ="" selected></option>') {
4817 $opt = '<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>';
4818 }
4819 return $opt;
4820 }
4821
4831 public function selectUnits($selected = '', $htmlname = 'units', $showempty = 0, $unit_type = '')
4832 {
4833 global $langs;
4834
4835 $langs->load('products');
4836
4837 $return = '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
4838
4839 $sql = "SELECT rowid, label, code FROM " . $this->db->prefix() . "c_units";
4840 $sql .= ' WHERE active > 0';
4841 if (!empty($unit_type)) {
4842 $sql .= " AND unit_type = '" . $this->db->escape($unit_type) . "'";
4843 }
4844 $sql .= " ORDER BY sortorder";
4845
4846 $resql = $this->db->query($sql);
4847 if ($resql && $this->db->num_rows($resql) > 0) {
4848 if ($showempty) {
4849 $return .= '<option value="none"></option>';
4850 }
4851
4852 while ($res = $this->db->fetch_object($resql)) {
4853 $unitLabel = $res->label;
4854 if (!empty($langs->tab_translate['unit' . $res->code])) { // check if Translation is available before
4855 $unitLabel = $langs->trans('unit' . $res->code) != $res->label ? $langs->trans('unit' . $res->code) : $res->label;
4856 }
4857
4858 if ($selected == $res->rowid) {
4859 $return .= '<option value="' . $res->rowid . '" selected>' . $unitLabel . '</option>';
4860 } else {
4861 $return .= '<option value="' . $res->rowid . '">' . $unitLabel . '</option>';
4862 }
4863 }
4864 $return .= '</select>';
4865 }
4866 return $return;
4867 }
4868
4869 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4870
4885 public function select_comptes($selected = '', $htmlname = 'accountid', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '', $showcurrency = 0, $morecss = '', $nooutput = 0)
4886 {
4887 // phpcs:enable
4888 global $langs, $conf;
4889
4890 $out = '';
4891
4892 $langs->load("admin");
4893 $num = 0;
4894
4895 $sql = "SELECT rowid, label, bank, clos as status, currency_code";
4896 $sql .= " FROM " . $this->db->prefix() . "bank_account";
4897 $sql .= " WHERE entity IN (" . getEntity('bank_account') . ")";
4898 if ($status != 2) {
4899 $sql .= " AND clos = " . (int) $status;
4900 }
4901 if ($filtre) {
4902 $sql .= " AND " . $filtre;
4903 }
4904 $sql .= " ORDER BY label";
4905
4906 dol_syslog(get_class($this) . "::select_comptes", LOG_DEBUG);
4907 $result = $this->db->query($sql);
4908 if ($result) {
4909 $num = $this->db->num_rows($result);
4910 $i = 0;
4911 if ($num) {
4912 $out .= '<select id="select' . $htmlname . '" class="flat selectbankaccount' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4913 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4914 $out .= '<option value="-1">&nbsp;</option>';
4915 }
4916
4917 while ($i < $num) {
4918 $obj = $this->db->fetch_object($result);
4919 if ($selected == $obj->rowid || ($useempty == 2 && $num == 1 && empty($selected))) {
4920 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '" selected>';
4921 } else {
4922 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '">';
4923 }
4924 $out .= trim($obj->label);
4925 if ($showcurrency) {
4926 $out .= ' (' . $obj->currency_code . ')';
4927 }
4928 if ($status == 2 && $obj->status == 1) {
4929 $out .= ' (' . $langs->trans("Closed") . ')';
4930 }
4931 $out .= '</option>';
4932 $i++;
4933 }
4934 $out .= "</select>";
4935 $out .= ajax_combobox('select' . $htmlname);
4936 } else {
4937 if ($status == 0) {
4938 $out .= '<span class="opacitymedium">' . $langs->trans("NoActiveBankAccountDefined") . '</span>';
4939 } else {
4940 $out .= '<span class="opacitymedium">' . $langs->trans("NoBankAccountFound") . '</span>';
4941 }
4942 }
4943 } else {
4944 dol_print_error($this->db);
4945 }
4946
4947 // Output or return
4948 if (empty($nooutput)) {
4949 print $out;
4950 } else {
4951 return $out;
4952 }
4953
4954 return $num;
4955 }
4956
4968 public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '')
4969 {
4970 global $langs, $conf;
4971
4972 $langs->load("admin");
4973 $num = 0;
4974
4975 $sql = "SELECT rowid, name, fk_country, status, entity";
4976 $sql .= " FROM " . $this->db->prefix() . "establishment";
4977 $sql .= " WHERE 1=1";
4978 if ($status != 2) {
4979 $sql .= " AND status = " . (int) $status;
4980 }
4981 if ($filtre) {
4982 $sql .= " AND " . $filtre;
4983 }
4984 $sql .= " ORDER BY name";
4985
4986 dol_syslog(get_class($this) . "::select_establishment", LOG_DEBUG);
4987 $result = $this->db->query($sql);
4988 if ($result) {
4989 $num = $this->db->num_rows($result);
4990 $i = 0;
4991 if ($num) {
4992 print '<select id="select' . $htmlname . '" class="flat selectestablishment" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4993 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4994 print '<option value="-1">&nbsp;</option>';
4995 }
4996
4997 while ($i < $num) {
4998 $obj = $this->db->fetch_object($result);
4999 if ($selected == $obj->rowid) {
5000 print '<option value="' . $obj->rowid . '" selected>';
5001 } else {
5002 print '<option value="' . $obj->rowid . '">';
5003 }
5004 print trim($obj->name);
5005 if ($status == 2 && $obj->status == 1) {
5006 print ' (' . $langs->trans("Closed") . ')';
5007 }
5008 print '</option>';
5009 $i++;
5010 }
5011 print "</select>";
5012 } else {
5013 if ($status == 0) {
5014 print '<span class="opacitymedium">' . $langs->trans("NoActiveEstablishmentDefined") . '</span>';
5015 } else {
5016 print '<span class="opacitymedium">' . $langs->trans("NoEstablishmentFound") . '</span>';
5017 }
5018 }
5019
5020 return $num;
5021 } else {
5022 dol_print_error($this->db);
5023 return -1;
5024 }
5025 }
5026
5036 public function formSelectAccount($page, $selected = '', $htmlname = 'fk_account', $addempty = 0)
5037 {
5038 global $langs;
5039 if ($htmlname != "none") {
5040 print '<form method="POST" action="' . $page . '">';
5041 print '<input type="hidden" name="action" value="setbankaccount">';
5042 print '<input type="hidden" name="token" value="' . newToken() . '">';
5043 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
5044 $nbaccountfound = $this->select_comptes($selected, $htmlname, 0, '', $addempty);
5045 if ($nbaccountfound > 0) {
5046 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5047 }
5048 print '</form>';
5049 } else {
5050 $langs->load('banks');
5051
5052 if ($selected) {
5053 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
5054 $bankstatic = new Account($this->db);
5055 $result = $bankstatic->fetch($selected);
5056 if ($result) {
5057 print $bankstatic->getNomUrl(1);
5058 }
5059 } else {
5060 print "&nbsp;";
5061 }
5062 }
5063 }
5064
5065 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5066
5085 public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $markafterid = 0, $outputmode = 0, $include = 0, $morecss = '')
5086 {
5087 // phpcs:enable
5088 global $conf, $langs;
5089 $langs->load("categories");
5090
5091 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
5092
5093 // For backward compatibility
5094 if (is_numeric($type)) {
5095 dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING);
5096 }
5097
5098 if ($type === Categorie::TYPE_BANK_LINE) {
5099 // TODO Move this into common category feature
5100 $cate_arbo = array();
5101 $sql = "SELECT c.label, c.rowid";
5102 $sql .= " FROM " . $this->db->prefix() . "bank_categ as c";
5103 $sql .= " WHERE entity = " . $conf->entity;
5104 $sql .= " ORDER BY c.label";
5105 $result = $this->db->query($sql);
5106 if ($result) {
5107 $num = $this->db->num_rows($result);
5108 $i = 0;
5109 while ($i < $num) {
5110 $objp = $this->db->fetch_object($result);
5111 if ($objp) {
5112 $cate_arbo[$objp->rowid] = array('id' => $objp->rowid, 'fulllabel' => $objp->label, 'color' => '', 'picto' => 'category');
5113 }
5114 $i++;
5115 }
5116 $this->db->free($result);
5117 } else {
5118 dol_print_error($this->db);
5119 }
5120 } else {
5121 $cat = new Categorie($this->db);
5122 $cate_arbo = $cat->get_full_arbo($type, $markafterid, $include);
5123 }
5124
5125 $outarray = array();
5126 $outarrayrichhtml = array();
5127
5128 $output = '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
5129 if (is_array($cate_arbo)) {
5130 if (!count($cate_arbo)) {
5131 $output .= '<option value="-1" disabled>' . $langs->trans("NoCategoriesDefined") . '</option>';
5132 } else {
5133 $output .= '<option value="-1">&nbsp;</option>';
5134 foreach ($cate_arbo as $key => $value) {
5135 if ($cate_arbo[$key]['id'] == $selected || ($selected === 'auto' && count($cate_arbo) == 1)) {
5136 $add = 'selected ';
5137 } else {
5138 $add = '';
5139 }
5140
5141 $labeltoshow = img_picto('', 'category', 'class="pictofixedwidth" style="color: #' . $cate_arbo[$key]['color'] . '"');
5142 $labeltoshow .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5143
5144 $outarray[$cate_arbo[$key]['id']] = $cate_arbo[$key]['fulllabel'];
5145
5146 $outarrayrichhtml[$cate_arbo[$key]['id']] = $labeltoshow;
5147
5148 $output .= '<option ' . $add . 'value="' . $cate_arbo[$key]['id'] . '"';
5149 $output .= ' data-html="' . dol_escape_htmltag($labeltoshow) . '"';
5150 $output .= '>';
5151 $output .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5152 $output .= '</option>';
5153 }
5154 }
5155 }
5156 $output .= '</select>';
5157 $output .= "\n";
5158
5159 if ($outputmode == 2) {
5160 return $cate_arbo;
5161 } elseif ($outputmode == 1) {
5162 return $outarray;
5163 } elseif ($outputmode == 3) {
5164 return $outarrayrichhtml;
5165 }
5166 return $output;
5167 }
5168
5169 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5170
5187 public function form_confirm($page, $title, $question, $action, $formquestion = array(), $selectedchoice = "", $useajax = 0, $height = 170, $width = 500)
5188 {
5189 // phpcs:enable
5190 dol_syslog(__METHOD__ . ': using form_confirm is deprecated. Use formconfim instead.', LOG_WARNING);
5191 print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width);
5192 }
5193
5221 public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No')
5222 {
5223 global $langs, $conf;
5224
5225 $more = '<!-- formconfirm - before call, page=' . dol_escape_htmltag($page) . ' -->';
5226 $formconfirm = '';
5227 $inputok = array();
5228 $inputko = array();
5229
5230 // Clean parameters
5231 $newselectedchoice = empty($selectedchoice) ? "no" : $selectedchoice;
5232 if ($conf->browser->layout == 'phone') {
5233 $width = '95%';
5234 }
5235
5236 // Set height automatically if not defined
5237 if (empty($height)) {
5238 $height = 220;
5239 if (is_array($formquestion) && count($formquestion) > 2) {
5240 $height += ((count($formquestion) - 2) * 24);
5241 }
5242 }
5243
5244 if (is_array($formquestion) && !empty($formquestion)) {
5245 // First add hidden fields and value
5246 foreach ($formquestion as $key => $input) {
5247 if (is_array($input) && !empty($input)) {
5248 if ($input['type'] == 'hidden') {
5249 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5250 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5251
5252 $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";
5253 }
5254 }
5255 }
5256
5257 // Now add questions
5258 $moreonecolumn = '';
5259 $more .= '<div class="tagtable paddingtopbottomonly centpercent noborderspacing">' . "\n";
5260 foreach ($formquestion as $key => $input) {
5261 if (is_array($input) && !empty($input)) {
5262 $size = (!empty($input['size']) ? ' size="' . $input['size'] . '"' : ''); // deprecated. Use morecss instead.
5263 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5264 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5265
5266 if ($input['type'] == 'text') {
5267 $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";
5268 } elseif ($input['type'] == 'password') {
5269 $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";
5270 } elseif ($input['type'] == 'textarea') {
5271 /*$more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">'.$input['label'].'</div><div class="tagtd">';
5272 $more .= '<textarea name="'.$input['name'].'" class="'.$morecss.'"'.$moreattr.'>';
5273 $more .= $input['value'];
5274 $more .= '</textarea>';
5275 $more .= '</div></div>'."\n";*/
5276 $moreonecolumn .= '<div class="margintoponly">';
5277 $moreonecolumn .= $input['label'] . '<br>';
5278 $moreonecolumn .= '<textarea name="' . dol_escape_htmltag($input['name']) . '" id="' . dol_escape_htmltag($input['name']) . '" class="' . $morecss . '"' . $moreattr . '>';
5279 $moreonecolumn .= $input['value'];
5280 $moreonecolumn .= '</textarea>';
5281 $moreonecolumn .= '</div>';
5282 } elseif (in_array($input['type'], ['select', 'multiselect'])) {
5283 if (empty($morecss)) {
5284 $morecss = 'minwidth100';
5285 }
5286
5287 $show_empty = isset($input['select_show_empty']) ? $input['select_show_empty'] : 1;
5288 $key_in_label = isset($input['select_key_in_label']) ? $input['select_key_in_label'] : 0;
5289 $value_as_key = isset($input['select_value_as_key']) ? $input['select_value_as_key'] : 0;
5290 $translate = isset($input['select_translate']) ? $input['select_translate'] : 0;
5291 $maxlen = isset($input['select_maxlen']) ? $input['select_maxlen'] : 0;
5292 $disabled = isset($input['select_disabled']) ? $input['select_disabled'] : 0;
5293 $sort = isset($input['select_sort']) ? $input['select_sort'] : '';
5294
5295 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">';
5296 if (!empty($input['label'])) {
5297 $more .= $input['label'] . '</div><div class="tagtd left">';
5298 }
5299 if ($input['type'] == 'select') {
5300 $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);
5301 } else {
5302 $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);
5303 }
5304 $more .= '</div></div>' . "\n";
5305 } elseif ($input['type'] == 'checkbox') {
5306 $more .= '<div class="tagtr">';
5307 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '"><label for="' . dol_escape_htmltag($input['name']) . '">' . $input['label'] . '</label></div><div class="tagtd">';
5308 $more .= '<input type="checkbox" class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $moreattr;
5309 if (!is_bool($input['value']) && $input['value'] != 'false' && $input['value'] != '0' && $input['value'] != '') {
5310 $more .= ' checked';
5311 }
5312 if (is_bool($input['value']) && $input['value']) {
5313 $more .= ' checked';
5314 }
5315 if (isset($input['disabled'])) {
5316 $more .= ' disabled';
5317 }
5318 $more .= ' /></div>';
5319 $more .= '</div>' . "\n";
5320 } elseif ($input['type'] == 'radio') {
5321 $i = 0;
5322 foreach ($input['values'] as $selkey => $selval) {
5323 $more .= '<div class="tagtr">';
5324 if (isset($input['label'])) {
5325 if ($i == 0) {
5326 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? ' tdtop' : (' tdtop ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5327 } else {
5328 $more .= '<div clas="tagtd' . (empty($input['tdclass']) ? '' : (' "' . $input['tdclass'])) . '">&nbsp;</div>';
5329 }
5330 }
5331 $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;
5332 if (!empty($input['disabled'])) {
5333 $more .= ' disabled';
5334 }
5335 if (isset($input['default']) && $input['default'] === $selkey) {
5336 $more .= ' checked="checked"';
5337 }
5338 $more .= ' /> ';
5339 $more .= '<label for="' . dol_escape_htmltag($input['name'] . $selkey) . '" class="valignmiddle">' . $selval . '</label>';
5340 $more .= '</div></div>' . "\n";
5341 $i++;
5342 }
5343 } elseif ($input['type'] == 'date' || $input['type'] == 'datetime') {
5344 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5345 $more .= '<div class="tagtd">';
5346 $addnowlink = (empty($input['datenow']) ? 0 : 1);
5347 $h = $m = 0;
5348 if ($input['type'] == 'datetime') {
5349 $h = isset($input['hours']) ? $input['hours'] : 1;
5350 $m = isset($input['minutes']) ? $input['minutes'] : 1;
5351 }
5352 $more .= $this->selectDate($input['value'], $input['name'], $h, $m, 0, '', 1, $addnowlink);
5353 $more .= '</div></div>'."\n";
5354 $formquestion[] = array('name'=>$input['name'].'day');
5355 $formquestion[] = array('name'=>$input['name'].'month');
5356 $formquestion[] = array('name'=>$input['name'].'year');
5357 $formquestion[] = array('name'=>$input['name'].'hour');
5358 $formquestion[] = array('name'=>$input['name'].'min');
5359 } elseif ($input['type'] == 'other') { // can be 1 column or 2 depending if label is set or not
5360 $more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">';
5361 if (!empty($input['label'])) {
5362 $more .= $input['label'] . '</div><div class="tagtd">';
5363 }
5364 $more .= $input['value'];
5365 $more .= '</div></div>' . "\n";
5366 } elseif ($input['type'] == 'onecolumn') {
5367 $moreonecolumn .= '<div class="margintoponly">';
5368 $moreonecolumn .= $input['value'];
5369 $moreonecolumn .= '</div>' . "\n";
5370 } elseif ($input['type'] == 'hidden') {
5371 // Do nothing more, already added by a previous loop
5372 } elseif ($input['type'] == 'separator') {
5373 $more .= '<br>';
5374 } else {
5375 $more .= 'Error type ' . $input['type'] . ' for the confirm box is not a supported type';
5376 }
5377 }
5378 }
5379 $more .= '</div>' . "\n";
5380 $more .= $moreonecolumn;
5381 }
5382
5383 // JQUERY method dialog is broken with smartphone, we use standard HTML.
5384 // 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
5385 // See page product/card.php for example
5386 if (!empty($conf->dol_use_jmobile)) {
5387 $useajax = 0;
5388 }
5389 if (empty($conf->use_javascript_ajax)) {
5390 $useajax = 0;
5391 }
5392
5393 if ($useajax) {
5394 $autoOpen = true;
5395 $dialogconfirm = 'dialog-confirm';
5396 $button = '';
5397 if (!is_numeric($useajax)) {
5398 $button = $useajax;
5399 $useajax = 1;
5400 $autoOpen = false;
5401 $dialogconfirm .= '-' . $button;
5402 }
5403 $pageyes = $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=yes';
5404 $pageno = ($useajax == 2 ? $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=no' : '');
5405
5406 // Add input fields into list of fields to read during submit (inputok and inputko)
5407 if (is_array($formquestion)) {
5408 foreach ($formquestion as $key => $input) {
5409 //print "xx ".$key." rr ".is_array($input)."<br>\n";
5410 // Add name of fields to propagate with the GET when submitting the form with button OK.
5411 if (is_array($input) && isset($input['name'])) {
5412 if (strpos($input['name'], ',') > 0) {
5413 $inputok = array_merge($inputok, explode(',', $input['name']));
5414 } else {
5415 array_push($inputok, $input['name']);
5416 }
5417 }
5418 // Add name of fields to propagate with the GET when submitting the form with button KO.
5419 if (isset($input['inputko']) && $input['inputko'] == 1) {
5420 array_push($inputko, $input['name']);
5421 }
5422 }
5423 }
5424
5425 // Show JQuery confirm box.
5426 $formconfirm .= '<div id="' . $dialogconfirm . '" title="' . dol_escape_htmltag($title) . '" style="display: none;">';
5427 if (is_array($formquestion) && !empty($formquestion['text'])) {
5428 $formconfirm .= '<div class="confirmtext">' . $formquestion['text'] . '</div>' . "\n";
5429 }
5430 if (!empty($more)) {
5431 $formconfirm .= '<div class="confirmquestions">' . $more . '</div>' . "\n";
5432 }
5433 $formconfirm .= ($question ? '<div class="confirmmessage">' . img_help('', '') . ' ' . $question . '</div>' : '');
5434 $formconfirm .= '</div>' . "\n";
5435
5436 $formconfirm .= "\n<!-- begin code of popup for formconfirm page=" . $page . " -->\n";
5437 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5438 $formconfirm .= "/* Code for the jQuery('#dialogforpopup').dialog() */\n";
5439 $formconfirm .= 'jQuery(document).ready(function() {
5440 $(function() {
5441 $( "#' . $dialogconfirm . '" ).dialog(
5442 {
5443 autoOpen: ' . ($autoOpen ? "true" : "false") . ',';
5444 if ($newselectedchoice == 'no') {
5445 $formconfirm .= '
5446 open: function() {
5447 $(this).parent().find("button.ui-button:eq(2)").focus();
5448 },';
5449 }
5450
5451 $jsforcursor = '';
5452 if ($useajax == 1) {
5453 $jsforcursor = '// The call to urljump can be slow, so we set the wait cursor' . "\n";
5454 $jsforcursor .= 'jQuery("html,body,#id-container").addClass("cursorwait");' . "\n";
5455 }
5456
5457 $postconfirmas = 'GET';
5458
5459 $formconfirm .= '
5460 resizable: false,
5461 height: "' . $height . '",
5462 width: "' . $width . '",
5463 modal: true,
5464 closeOnEscape: false,
5465 buttons: {
5466 "' . dol_escape_js($langs->transnoentities($labelbuttonyes)) . '": function() {
5467 var options = "token=' . urlencode(newToken()) . '";
5468 var inputok = ' . json_encode($inputok) . '; /* List of fields into form */
5469 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5470 var pageyes = "' . dol_escape_js(!empty($pageyes) ? $pageyes : '') . '";
5471
5472 if (inputok.length > 0) {
5473 $.each(inputok, function(i, inputname) {
5474 var more = "";
5475 var inputvalue;
5476 if ($("input[name=\'" + inputname + "\']").attr("type") == "radio") {
5477 inputvalue = $("input[name=\'" + inputname + "\']:checked").val();
5478 } else {
5479 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5480 inputvalue = $("#" + inputname + more).val();
5481 }
5482 if (typeof inputvalue == "undefined") { inputvalue=""; }
5483 console.log("formconfirm check inputname="+inputname+" inputvalue="+inputvalue);
5484 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5485 });
5486 }
5487 var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "&") + options;
5488 if (pageyes.length > 0) {';
5489 if ($postconfirmas == 'GET') {
5490 $formconfirm .= 'location.href = urljump;';
5491 } else {
5492 $formconfirm .= $jsforcursor;
5493 $formconfirm .= 'var post = $.post(
5494 pageyes,
5495 options,
5496 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5497 );';
5498 }
5499 $formconfirm .= '
5500 console.log("after post ok");
5501 }
5502 $(this).dialog("close");
5503 },
5504 "' . dol_escape_js($langs->transnoentities($labelbuttonno)) . '": function() {
5505 var options = "token=' . urlencode(newToken()) . '";
5506 var inputko = ' . json_encode($inputko) . '; /* List of fields into form */
5507 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5508 var pageno="' . dol_escape_js(!empty($pageno) ? $pageno : '') . '";
5509 if (inputko.length > 0) {
5510 $.each(inputko, function(i, inputname) {
5511 var more = "";
5512 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5513 var inputvalue = $("#" + inputname + more).val();
5514 if (typeof inputvalue == "undefined") { inputvalue=""; }
5515 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5516 });
5517 }
5518 var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "&") + options;
5519 //alert(urljump);
5520 if (pageno.length > 0) {';
5521 if ($postconfirmas == 'GET') {
5522 $formconfirm .= 'location.href = urljump;';
5523 } else {
5524 $formconfirm .= $jsforcursor;
5525 $formconfirm .= 'var post = $.post(
5526 pageno,
5527 options,
5528 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5529 );';
5530 }
5531 $formconfirm .= '
5532 console.log("after post ko");
5533 }
5534 $(this).dialog("close");
5535 }
5536 }
5537 }
5538 );
5539
5540 var button = "' . $button . '";
5541 if (button.length > 0) {
5542 $( "#" + button ).click(function() {
5543 $("#' . $dialogconfirm . '").dialog("open");
5544 });
5545 }
5546 });
5547 });
5548 </script>';
5549 $formconfirm .= "<!-- end ajax formconfirm -->\n";
5550 } else {
5551 $formconfirm .= "\n<!-- begin formconfirm page=" . dol_escape_htmltag($page) . " -->\n";
5552
5553 if (empty($disableformtag)) {
5554 $formconfirm .= '<form method="POST" action="' . $page . '" class="notoptoleftroright">' . "\n";
5555 }
5556
5557 $formconfirm .= '<input type="hidden" name="action" value="' . $action . '">' . "\n";
5558 $formconfirm .= '<input type="hidden" name="token" value="' . newToken() . '">' . "\n";
5559
5560 $formconfirm .= '<table class="valid centpercent">' . "\n";
5561
5562 // Line title
5563 $formconfirm .= '<tr class="validtitre"><td class="validtitre" colspan="2">';
5564 $formconfirm .= img_picto('', 'pictoconfirm') . ' ' . $title;
5565 $formconfirm .= '</td></tr>' . "\n";
5566
5567 // Line text
5568 if (is_array($formquestion) && !empty($formquestion['text'])) {
5569 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . $formquestion['text'] . '</td></tr>' . "\n";
5570 }
5571
5572 // Line form fields
5573 if ($more) {
5574 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . "\n";
5575 $formconfirm .= $more;
5576 $formconfirm .= '</td></tr>' . "\n";
5577 }
5578
5579 // Line with question
5580 $formconfirm .= '<tr class="valid">';
5581 $formconfirm .= '<td class="valid">' . $question . '</td>';
5582 $formconfirm .= '<td class="valid center">';
5583 $formconfirm .= $this->selectyesno("confirm", $newselectedchoice, 0, false, 0, 0, 'marginleftonly marginrightonly', $labelbuttonyes, $labelbuttonno);
5584 $formconfirm .= '<input class="button valignmiddle confirmvalidatebutton small" type="submit" value="' . $langs->trans("Validate") . '">';
5585 $formconfirm .= '</td>';
5586 $formconfirm .= '</tr>' . "\n";
5587
5588 $formconfirm .= '</table>' . "\n";
5589
5590 if (empty($disableformtag)) {
5591 $formconfirm .= "</form>\n";
5592 }
5593 $formconfirm .= '<br>';
5594
5595 if (!empty($conf->use_javascript_ajax)) {
5596 $formconfirm .= '<!-- code to disable button to avoid double clic -->';
5597 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5598 $formconfirm .= '
5599 $(document).ready(function () {
5600 $(".confirmvalidatebutton").on("click", function() {
5601 console.log("We click on button confirmvalidatebutton");
5602 $(this).attr("disabled", "disabled");
5603 setTimeout(\'$(".confirmvalidatebutton").removeAttr("disabled")\', 3000);
5604 //console.log($(this).closest("form"));
5605 $(this).closest("form").submit();
5606 });
5607 });
5608 ';
5609 $formconfirm .= '</script>' . "\n";
5610 }
5611
5612 $formconfirm .= "<!-- end formconfirm -->\n";
5613 }
5614
5615 return $formconfirm;
5616 }
5617
5618
5619 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5620
5636 public function form_project($page, $socid, $selected = '', $htmlname = 'projectid', $discard_closed = 0, $maxlength = 20, $forcefocus = 0, $nooutput = 0, $textifnoproject = '', $morecss = '')
5637 {
5638 // phpcs:enable
5639 global $langs;
5640
5641 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
5642 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
5643
5644 $out = '';
5645
5646 $formproject = new FormProjets($this->db);
5647
5648 $langs->load("project");
5649 if ($htmlname != "none") {
5650 $out .= '<form method="post" action="' . $page . '">';
5651 $out .= '<input type="hidden" name="action" value="classin">';
5652 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5653 $out .= $formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1, 0, $morecss);
5654 $out .= '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5655 $out .= '</form>';
5656 } else {
5657 $out .= '<span class="project_head_block">';
5658 if ($selected) {
5659 $projet = new Project($this->db);
5660 $projet->fetch($selected);
5661 $out .= $projet->getNomUrl(0, '', 1);
5662 } else {
5663 $out .= '<span class="opacitymedium">' . $textifnoproject . '</span>';
5664 }
5665 $out .= '</span>';
5666 }
5667
5668 if (empty($nooutput)) {
5669 print $out;
5670 return '';
5671 }
5672 return $out;
5673 }
5674
5675 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5676
5692 public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0, $type = '', $filtertype = -1, $deposit_percent = -1, $nooutput = 0)
5693 {
5694 // phpcs:enable
5695 global $langs;
5696
5697 $out = '';
5698
5699 if ($htmlname != "none") {
5700 $out .= '<form method="POST" action="' . $page . '">';
5701 $out .= '<input type="hidden" name="action" value="setconditions">';
5702 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5703 if ($type) {
5704 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5705 }
5706 $out .= $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, 0, '', $deposit_percent);
5707 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5708 $out .= '</form>';
5709 } else {
5710 if ($selected) {
5712 if (isset($this->cache_conditions_paiements[$selected])) {
5713 $label = $this->cache_conditions_paiements[$selected]['label'];
5714
5715 if (!empty($this->cache_conditions_paiements[$selected]['deposit_percent'])) {
5716 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $this->cache_conditions_paiements[$selected]['deposit_percent'], $label);
5717 }
5718
5719 $out .= $label;
5720 } else {
5721 $langs->load('errors');
5722 $out .= $langs->trans('ErrorNotInDictionaryPaymentConditions');
5723 }
5724 } else {
5725 $out .= '&nbsp;';
5726 }
5727 }
5728
5729 if (empty($nooutput)) {
5730 print $out;
5731 return '';
5732 }
5733 return $out;
5734 }
5735
5736 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5737
5747 public function form_availability($page, $selected = '', $htmlname = 'availability', $addempty = 0)
5748 {
5749 // phpcs:enable
5750 global $langs;
5751 if ($htmlname != "none") {
5752 print '<form method="post" action="' . $page . '">';
5753 print '<input type="hidden" name="action" value="setavailability">';
5754 print '<input type="hidden" name="token" value="' . newToken() . '">';
5755 $this->selectAvailabilityDelay($selected, $htmlname, -1, $addempty);
5756 print '<input type="submit" name="modify" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5757 print '<input type="submit" name="cancel" class="button smallpaddingimp" value="' . $langs->trans("Cancel") . '">';
5758 print '</form>';
5759 } else {
5760 if ($selected) {
5761 $this->load_cache_availability();
5762 print $this->cache_availability[$selected]['label'];
5763 } else {
5764 print "&nbsp;";
5765 }
5766 }
5767 }
5768
5779 public function formInputReason($page, $selected = '', $htmlname = 'demandreason', $addempty = 0)
5780 {
5781 global $langs;
5782 if ($htmlname != "none") {
5783 print '<form method="post" action="' . $page . '">';
5784 print '<input type="hidden" name="action" value="setdemandreason">';
5785 print '<input type="hidden" name="token" value="' . newToken() . '">';
5786 $this->selectInputReason($selected, $htmlname, -1, $addempty);
5787 print '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5788 print '</form>';
5789 } else {
5790 if ($selected) {
5791 $this->loadCacheInputReason();
5792 foreach ($this->cache_demand_reason as $key => $val) {
5793 if ($val['id'] == $selected) {
5794 print $val['label'];
5795 break;
5796 }
5797 }
5798 } else {
5799 print "&nbsp;";
5800 }
5801 }
5802 }
5803
5804 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5805
5819 public function form_date($page, $selected, $htmlname, $displayhour = 0, $displaymin = 0, $nooutput = 0, $type = '')
5820 {
5821 // phpcs:enable
5822 global $langs;
5823
5824 $ret = '';
5825
5826 if ($htmlname != "none") {
5827 $ret .= '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
5828 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
5829 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
5830 if ($type) {
5831 $ret .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5832 }
5833 $ret .= '<table class="nobordernopadding">';
5834 $ret .= '<tr><td>';
5835 $ret .= $this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form' . $htmlname, 1, 0);
5836 $ret .= '</td>';
5837 $ret .= '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
5838 $ret .= '</tr></table></form>';
5839 } else {
5840 if ($displayhour) {
5841 $ret .= dol_print_date($selected, 'dayhour');
5842 } else {
5843 $ret .= dol_print_date($selected, 'day');
5844 }
5845 }
5846
5847 if (empty($nooutput)) {
5848 print $ret;
5849 }
5850 return $ret;
5851 }
5852
5853
5854 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5855
5866 public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = array(), $include = array())
5867 {
5868 // phpcs:enable
5869 global $langs;
5870
5871 if ($htmlname != "none") {
5872 print '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
5873 print '<input type="hidden" name="action" value="set' . $htmlname . '">';
5874 print '<input type="hidden" name="token" value="' . newToken() . '">';
5875 print $this->select_dolusers($selected, $htmlname, 1, $exclude, 0, $include);
5876 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5877 print '</form>';
5878 } else {
5879 if ($selected) {
5880 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
5881 $theuser = new User($this->db);
5882 $theuser->fetch($selected);
5883 print $theuser->getNomUrl(1);
5884 } else {
5885 print "&nbsp;";
5886 }
5887 }
5888 }
5889
5890
5891 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5892
5906 public function form_modes_reglement($page, $selected = '', $htmlname = 'mode_reglement_id', $filtertype = '', $active = 1, $addempty = 0, $type = '', $nooutput = 0)
5907 {
5908 // phpcs:enable
5909 global $langs;
5910
5911 $out = '';
5912 if ($htmlname != "none") {
5913 $out .= '<form method="POST" action="' . $page . '">';
5914 $out .= '<input type="hidden" name="action" value="setmode">';
5915 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5916 if ($type) {
5917 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5918 }
5919 $out .= $this->select_types_paiements($selected, $htmlname, $filtertype, 0, $addempty, 0, 0, $active, '', 1);
5920 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5921 $out .= '</form>';
5922 } else {
5923 if ($selected) {
5925 $out .= $this->cache_types_paiements[$selected]['label'];
5926 } else {
5927 $out .= "&nbsp;";
5928 }
5929 }
5930
5931 if ($nooutput) {
5932 return $out;
5933 } else {
5934 print $out;
5935 }
5936 return '';
5937 }
5938
5949 public function formSelectTransportMode($page, $selected = '', $htmlname = 'transport_mode_id', $active = 1, $addempty = 0)
5950 {
5951 global $langs;
5952 if ($htmlname != "none") {
5953 print '<form method="POST" action="' . $page . '">';
5954 print '<input type="hidden" name="action" value="settransportmode">';
5955 print '<input type="hidden" name="token" value="' . newToken() . '">';
5956 $this->selectTransportMode($selected, $htmlname, 0, $addempty, 0, 0, $active);
5957 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5958 print '</form>';
5959 } else {
5960 if ($selected) {
5962 print $this->cache_transport_mode[$selected]['label'];
5963 } else {
5964 print "&nbsp;";
5965 }
5966 }
5967 }
5968
5969 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5970
5979 public function form_multicurrency_code($page, $selected = '', $htmlname = 'multicurrency_code')
5980 {
5981 // phpcs:enable
5982 global $langs;
5983 if ($htmlname != "none") {
5984 print '<form method="POST" action="' . $page . '">';
5985 print '<input type="hidden" name="action" value="setmulticurrencycode">';
5986 print '<input type="hidden" name="token" value="' . newToken() . '">';
5987 print $this->selectMultiCurrency($selected, $htmlname, 0);
5988 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5989 print '</form>';
5990 } else {
5991 dol_include_once('/core/lib/company.lib.php');
5992 print !empty($selected) ? currency_name($selected, 1) : '&nbsp;';
5993 }
5994 }
5995
5996 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5997
6007 public function form_multicurrency_rate($page, $rate = 0.0, $htmlname = 'multicurrency_tx', $currency = '')
6008 {
6009 // phpcs:enable
6010 global $langs, $mysoc, $conf;
6011
6012 if ($htmlname != "none") {
6013 print '<form method="POST" action="' . $page . '">';
6014 print '<input type="hidden" name="action" value="setmulticurrencyrate">';
6015 print '<input type="hidden" name="token" value="' . newToken() . '">';
6016 print '<input type="text" class="maxwidth100" name="' . $htmlname . '" value="' . (!empty($rate) ? price(price2num($rate, 'CU')) : 1) . '" /> ';
6017 print '<select name="calculation_mode">';
6018 print '<option value="1">Change ' . $langs->trans("PriceUHT") . ' of lines</option>';
6019 print '<option value="2">Change ' . $langs->trans("PriceUHTCurrency") . ' of lines</option>';
6020 print '</select> ';
6021 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6022 print '</form>';
6023 } else {
6024 if (!empty($rate)) {
6025 print price($rate, 1, $langs, 0, 0);
6026 if ($currency && $rate != 1) {
6027 print ' &nbsp; (' . price($rate, 1, $langs, 0, 0) . ' ' . $currency . ' = 1 ' . $conf->currency . ')';
6028 }
6029 } else {
6030 print 1;
6031 }
6032 }
6033 }
6034
6035
6036 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6037
6053 public function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter = '', $maxvalue = 0, $more = '', $hidelist = 0, $discount_type = 0)
6054 {
6055 // phpcs:enable
6056 global $conf, $langs;
6057 if ($htmlname != "none") {
6058 print '<form method="post" action="' . $page . '">';
6059 print '<input type="hidden" name="action" value="setabsolutediscount">';
6060 print '<input type="hidden" name="token" value="' . newToken() . '">';
6061 print '<div class="inline-block">';
6062 if (!empty($discount_type)) {
6063 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
6064 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL") {
6065 $translationKey = 'HasAbsoluteDiscountFromSupplier'; // If we want deposit to be substracted to payments only and not to total of final invoice
6066 } else {
6067 $translationKey = 'HasCreditNoteFromSupplier';
6068 }
6069 } else {
6070 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6071 $translationKey = 'HasAbsoluteDiscountFromSupplier';
6072 } else {
6073 $translationKey = 'HasCreditNoteFromSupplier';
6074 }
6075 }
6076 } else {
6077 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
6078 if (!$filter || $filter == "fk_facture_source IS NULL") {
6079 $translationKey = 'CompanyHasAbsoluteDiscount'; // If we want deposit to be substracted to payments only and not to total of final invoice
6080 } else {
6081 $translationKey = 'CompanyHasCreditNote';
6082 }
6083 } else {
6084 if (!$filter || $filter == "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6085 $translationKey = 'CompanyHasAbsoluteDiscount';
6086 } else {
6087 $translationKey = 'CompanyHasCreditNote';
6088 }
6089 }
6090 }
6091 print $langs->trans($translationKey, price($amount, 0, $langs, 0, 0, -1, $conf->currency));
6092 if (empty($hidelist)) {
6093 print ' ';
6094 }
6095 print '</div>';
6096 if (empty($hidelist)) {
6097 print '<div class="inline-block" style="padding-right: 10px">';
6098 $newfilter = 'discount_type=' . intval($discount_type);
6099 if (!empty($discount_type)) {
6100 $newfilter .= ' AND fk_invoice_supplier IS NULL AND fk_invoice_supplier_line IS NULL'; // Supplier discounts available
6101 } else {
6102 $newfilter .= ' AND fk_facture IS NULL AND fk_facture_line IS NULL'; // Customer discounts available
6103 }
6104 if ($filter) {
6105 $newfilter .= ' AND (' . $filter . ')';
6106 }
6107 // output the combo of discounts
6108 $nbqualifiedlines = $this->select_remises($selected, $htmlname, $newfilter, $socid, $maxvalue);
6109 if ($nbqualifiedlines > 0) {
6110 print ' &nbsp; <input type="submit" class="button smallpaddingimp" value="' . dol_escape_htmltag($langs->trans("UseLine")) . '"';
6111 if (!empty($discount_type) && $filter && $filter != "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6112 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6113 }
6114 if (empty($discount_type) && $filter && $filter != "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6115 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6116 }
6117
6118 print '>';
6119 }
6120 print '</div>';
6121 }
6122 if ($more) {
6123 print '<div class="inline-block">';
6124 print $more;
6125 print '</div>';
6126 }
6127 print '</form>';
6128 } else {
6129 if ($selected) {
6130 print $selected;
6131 } else {
6132 print "0";
6133 }
6134 }
6135 }
6136
6137
6138 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6139
6149 public function form_contacts($page, $societe, $selected = '', $htmlname = 'contactid')
6150 {
6151 // phpcs:enable
6152 global $langs, $conf;
6153
6154 if ($htmlname != "none") {
6155 print '<form method="post" action="' . $page . '">';
6156 print '<input type="hidden" name="action" value="set_contact">';
6157 print '<input type="hidden" name="token" value="' . newToken() . '">';
6158 print '<table class="nobordernopadding">';
6159 print '<tr><td>';
6160 print $this->selectcontacts($societe->id, $selected, $htmlname);
6161 $num = $this->num;
6162 if ($num == 0) {
6163 $addcontact = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("AddContact") : $langs->trans("AddContactAddress"));
6164 print '<a href="' . DOL_URL_ROOT . '/contact/card.php?socid=' . $societe->id . '&amp;action=create&amp;backtoreferer=1">' . $addcontact . '</a>';
6165 }
6166 print '</td>';
6167 print '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6168 print '</tr></table></form>';
6169 } else {
6170 if ($selected) {
6171 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
6172 $contact = new Contact($this->db);
6173 $contact->fetch($selected);
6174 print $contact->getFullName($langs);
6175 } else {
6176 print "&nbsp;";
6177 }
6178 }
6179 }
6180
6181 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6182
6199 public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0, $excludeids = array(), $textifnothirdparty = '')
6200 {
6201 // phpcs:enable
6202 global $langs;
6203
6204 $out = '';
6205 if ($htmlname != "none") {
6206 $out .= '<form method="post" action="' . $page . '">';
6207 $out .= '<input type="hidden" name="action" value="set_thirdparty">';
6208 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6209 $out .= $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, 0, 'minwidth100', '', '', 1, array(), false, $excludeids);
6210 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6211 $out .= '</form>';
6212 } else {
6213 if ($selected) {
6214 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
6215 $soc = new Societe($this->db);
6216 $soc->fetch($selected);
6217 $out .= $soc->getNomUrl(0, '');
6218 } else {
6219 $out .= '<span class="opacitymedium">' . $textifnothirdparty . '</span>';
6220 }
6221 }
6222
6223 if ($nooutput) {
6224 return $out;
6225 } else {
6226 print $out;
6227 }
6228
6229 return '';
6230 }
6231
6232 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6233
6242 public function select_currency($selected = '', $htmlname = 'currency_id')
6243 {
6244 // phpcs:enable
6245 print $this->selectCurrency($selected, $htmlname);
6246 }
6247
6257 public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0, $useempty = '')
6258 {
6259 global $conf, $langs, $user;
6260
6261 $langs->loadCacheCurrencies('');
6262
6263 $out = '';
6264
6265 if ($selected == 'euro' || $selected == 'euros') {
6266 $selected = 'EUR'; // Pour compatibilite
6267 }
6268
6269 $out .= '<select class="flat maxwidth200onsmartphone minwidth300" name="' . $htmlname . '" id="' . $htmlname . '">';
6270 if ($useempty) {
6271 $out .= '<option value="-1" selected></option>';
6272 }
6273 foreach ($langs->cache_currencies as $code_iso => $currency) {
6274 $labeltoshow = $currency['label'];
6275 if ($mode == 1) {
6276 $labeltoshow .= ' <span class="opacitymedium">(' . $code_iso . ')</span>';
6277 } else {
6278 $labeltoshow .= ' <span class="opacitymedium">(' . $langs->getCurrencySymbol($code_iso) . ')</span>';
6279 }
6280
6281 if ($selected && $selected == $code_iso) {
6282 $out .= '<option value="' . $code_iso . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6283 } else {
6284 $out .= '<option value="' . $code_iso . '" data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6285 }
6286 $out .= $labeltoshow;
6287 $out .= '</option>';
6288 }
6289 $out .= '</select>';
6290 if ($user->admin) {
6291 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
6292 }
6293
6294 // Make select dynamic
6295 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6296 $out .= ajax_combobox($htmlname);
6297
6298 return $out;
6299 }
6300
6313 public function selectMultiCurrency($selected = '', $htmlname = 'multicurrency_code', $useempty = 0, $filter = '', $excludeConfCurrency = false, $morecss = '')
6314 {
6315 global $conf, $langs;
6316
6317 $langs->loadCacheCurrencies(''); // Load ->cache_currencies
6318
6319 $TCurrency = array();
6320
6321 $sql = "SELECT code FROM " . $this->db->prefix() . "multicurrency";
6322 $sql .= " WHERE entity IN ('" . getEntity('mutlicurrency') . "')";
6323 if ($filter) {
6324 $sql .= " AND " . $filter;
6325 }
6326 $resql = $this->db->query($sql);
6327 if ($resql) {
6328 while ($obj = $this->db->fetch_object($resql)) {
6329 $TCurrency[$obj->code] = $obj->code;
6330 }
6331 }
6332
6333 $out = '';
6334 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
6335 if ($useempty) {
6336 $out .= '<option value="">&nbsp;</option>';
6337 }
6338 // If company current currency not in table, we add it into list. Should always be available.
6339 if (!in_array($conf->currency, $TCurrency) && !$excludeConfCurrency) {
6340 $TCurrency[$conf->currency] = $conf->currency;
6341 }
6342 if (count($TCurrency) > 0) {
6343 foreach ($langs->cache_currencies as $code_iso => $currency) {
6344 if (isset($TCurrency[$code_iso])) {
6345 if (!empty($selected) && $selected == $code_iso) {
6346 $out .= '<option value="' . $code_iso . '" selected="selected">';
6347 } else {
6348 $out .= '<option value="' . $code_iso . '">';
6349 }
6350
6351 $out .= $currency['label'];
6352 $out .= ' (' . $langs->getCurrencySymbol($code_iso) . ')';
6353 $out .= '</option>';
6354 }
6355 }
6356 }
6357
6358 $out .= '</select>';
6359
6360 // Make select dynamic
6361 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6362 $out .= ajax_combobox($htmlname);
6363
6364 return $out;
6365 }
6366
6367 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6368
6375 public function load_cache_vatrates($country_code)
6376 {
6377 // phpcs:enable
6378 global $langs, $user;
6379
6380 $num = count($this->cache_vatrates);
6381 if ($num > 0) {
6382 return $num; // Cache already loaded
6383 }
6384
6385 dol_syslog(__METHOD__, LOG_DEBUG);
6386
6387 $sql = "SELECT DISTINCT t.rowid, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
6388 $sql .= " FROM " . $this->db->prefix() . "c_tva as t, " . $this->db->prefix() . "c_country as c";
6389 $sql .= " WHERE t.fk_pays = c.rowid";
6390 $sql .= " AND t.active > 0";
6391 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
6392 $sql .= " AND c.code IN (" . $this->db->sanitize($country_code, 1) . ")";
6393 $sql .= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC";
6394
6395 $resql = $this->db->query($sql);
6396 if ($resql) {
6397 $num = $this->db->num_rows($resql);
6398 if ($num) {
6399 for ($i = 0; $i < $num; $i++) {
6400 $obj = $this->db->fetch_object($resql);
6401 $this->cache_vatrates[$i]['rowid'] = $obj->rowid;
6402 $this->cache_vatrates[$i]['code'] = $obj->code;
6403 $this->cache_vatrates[$i]['txtva'] = $obj->taux;
6404 $this->cache_vatrates[$i]['nprtva'] = $obj->recuperableonly;
6405 $this->cache_vatrates[$i]['localtax1'] = $obj->localtax1;
6406 $this->cache_vatrates[$i]['localtax1_type'] = $obj->localtax1_type;
6407 $this->cache_vatrates[$i]['localtax2'] = $obj->localtax2;
6408 $this->cache_vatrates[$i]['localtax2_type'] = $obj->localtax1_type;
6409
6410 $this->cache_vatrates[$i]['label'] = $obj->taux . '%' . ($obj->code ? ' (' . $obj->code . ')' : ''); // Label must contains only 0-9 , . % or *
6411 $this->cache_vatrates[$i]['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
6412 $positiverates = '';
6413 if ($obj->taux) {
6414 $positiverates .= ($positiverates ? '/' : '') . $obj->taux;
6415 }
6416 if ($obj->localtax1) {
6417 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax1;
6418 }
6419 if ($obj->localtax2) {
6420 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax2;
6421 }
6422 if (empty($positiverates)) {
6423 $positiverates = '0';
6424 }
6425 $this->cache_vatrates[$i]['labelpositiverates'] = $positiverates . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
6426 }
6427
6428 return $num;
6429 } else {
6430 $this->error = '<span class="error">';
6431 $this->error .= $langs->trans("ErrorNoVATRateDefinedForSellerCountry", $country_code);
6432 $reg = array();
6433 if (!empty($user) && $user->admin && preg_match('/\'(..)\'/', $country_code, $reg)) {
6434 $langs->load("errors");
6435 $new_country_code = $reg[1];
6436 $country_id = dol_getIdFromCode($this->db, $new_country_code, 'c_pays', 'code', 'rowid');
6437 $this->error .= '<br>'.$langs->trans("ErrorFixThisHere", DOL_URL_ROOT.'/admin/dict.php?id=10'.($country_id > 0 ? '&countryidforinsert='.$country_id : ''));
6438 }
6439 $this->error .= '</span>';
6440 return -1;
6441 }
6442 } else {
6443 $this->error = '<span class="error">' . $this->db->error() . '</span>';
6444 return -2;
6445 }
6446 }
6447
6448 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6449
6471 public function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = null, $societe_acheteuse = null, $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0)
6472 {
6473 // phpcs:enable
6474 global $langs, $conf, $mysoc;
6475
6476 $langs->load('errors');
6477
6478 $return = '';
6479
6480 // Define defaultnpr, defaultttx and defaultcode
6481 $defaultnpr = ($info_bits & 0x01);
6482 $defaultnpr = (preg_match('/\*/', $selectedrate) ? 1 : $defaultnpr);
6483 $defaulttx = str_replace('*', '', $selectedrate);
6484 $defaultcode = '';
6485 $reg = array();
6486 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6487 $defaultcode = $reg[1];
6488 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6489 }
6490 //var_dump($selectedrate.'-'.$defaulttx.'-'.$defaultnpr.'-'.$defaultcode);
6491
6492 // Check parameters
6493 if (is_object($societe_vendeuse) && !$societe_vendeuse->country_code) {
6494 if ($societe_vendeuse->id == $mysoc->id) {
6495 $return .= '<span class="error">' . $langs->trans("ErrorYourCountryIsNotDefined") . '</span>';
6496 } else {
6497 $return .= '<span class="error">' . $langs->trans("ErrorSupplierCountryIsNotDefined") . '</span>';
6498 }
6499 return $return;
6500 }
6501
6502 //var_dump($societe_acheteuse);
6503 //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";
6504 //exit;
6505
6506 // Define list of countries to use to search VAT rates to show
6507 // First we defined code_country to use to find list
6508 if (is_object($societe_vendeuse)) {
6509 $code_country = "'" . $societe_vendeuse->country_code . "'";
6510 } else {
6511 $code_country = "'" . $mysoc->country_code . "'"; // Pour compatibilite ascendente
6512 }
6513 if (getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC')) { // If option to have vat for end customer for services is on
6514 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6515 // If SERVICE_ARE_ECOMMERCE_200238EC=1 combo list vat rate of purchaser and seller countries
6516 // If SERVICE_ARE_ECOMMERCE_200238EC=2 combo list only the vat rate of the purchaser country
6517 $selectVatComboMode = getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC');
6518 if (isInEEC($societe_vendeuse) && isInEEC($societe_acheteuse) && !$societe_acheteuse->isACompany()) {
6519 // We also add the buyer country code
6520 if (is_numeric($type)) {
6521 if ($type == 1) { // We know product is a service
6522 switch ($selectVatComboMode) {
6523 case '1':
6524 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6525 break;
6526 case '2':
6527 $code_country = "'" . $societe_acheteuse->country_code . "'";
6528 break;
6529 }
6530 }
6531 } elseif (!$idprod) { // We don't know type of product
6532 switch ($selectVatComboMode) {
6533 case '1':
6534 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6535 break;
6536 case '2':
6537 $code_country = "'" . $societe_acheteuse->country_code . "'";
6538 break;
6539 }
6540 } else {
6541 $prodstatic = new Product($this->db);
6542 $prodstatic->fetch($idprod);
6543 if ($prodstatic->type == Product::TYPE_SERVICE) { // We know product is a service
6544 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6545 }
6546 }
6547 }
6548 }
6549
6550 // Now we get list
6551 $num = $this->load_cache_vatrates($code_country); // If no vat at all defined for this country, return -1 with message into this->error
6552
6553 if ($num > 0) {
6554 // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '')
6555 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6556 $tmpthirdparty = new Societe($this->db);
6557
6558 $defaulttx = get_default_tva($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6559 $defaultnpr = get_default_npr($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6560
6561 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6562 $defaultcode = $reg[1];
6563 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6564 }
6565 if (empty($defaulttx)) {
6566 $defaultnpr = 0;
6567 }
6568 }
6569
6570 // If we fails to find a default vat rate, we take the last one in list
6571 // Because they are sorted in ascending order, the last one will be the higher one (we suppose the higher one is the current rate)
6572 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6573 if (!getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS')) {
6574 // We take the last one found in list
6575 $defaulttx = $this->cache_vatrates[$num - 1]['txtva'];
6576 } else {
6577 // We will use the rate defined into MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS
6578 $defaulttx = '';
6579 if (getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS') != 'none') {
6580 $defaulttx = $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS;
6581 }
6582 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6583 $defaultcode = $reg[1];
6584 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6585 }
6586 }
6587 }
6588
6589 // Disabled if seller is not subject to VAT
6590 $disabled = false;
6591 $title = '';
6592 if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0") {
6593 // Override/enable VAT for expense report regardless of global setting - needed if expense report used for business expenses instead
6594 // of using supplier invoices (this is a very bad idea !)
6595 if (!getDolGlobalString('EXPENSEREPORT_OVERRIDE_VAT')) {
6596 $title = ' title="' . dol_escape_htmltag($langs->trans('VATIsNotUsed')) . '"';
6597 $disabled = true;
6598 }
6599 }
6600
6601 if (!$options_only) {
6602 $return .= '<select class="flat minwidth50imp maxwidth100" id="' . $htmlname . '" name="' . $htmlname . '"' . ($disabled ? ' disabled' : '') . $title . '>';
6603 }
6604
6605 $selectedfound = false;
6606 foreach ($this->cache_vatrates as $rate) {
6607 // Keep only 0 if seller is not subject to VAT
6608 if ($disabled && $rate['txtva'] != 0) {
6609 continue;
6610 }
6611
6612 // Define key to use into select list
6613 $key = $rate['txtva'];
6614 $key .= $rate['nprtva'] ? '*' : '';
6615 if ($mode > 0 && $rate['code']) {
6616 $key .= ' (' . $rate['code'] . ')';
6617 }
6618 if ($mode < 0) {
6619 $key = $rate['rowid'];
6620 }
6621
6622 $return .= '<option value="' . $key . '"';
6623 if (!$selectedfound) {
6624 if ($defaultcode) { // If defaultcode is defined, we used it in priority to select combo option instead of using rate+npr flag
6625 if ($defaultcode == $rate['code']) {
6626 $return .= ' selected';
6627 $selectedfound = true;
6628 }
6629 } elseif ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr) {
6630 $return .= ' selected';
6631 $selectedfound = true;
6632 }
6633 }
6634 $return .= '>';
6635
6636 // Show label of VAT
6637 if ($mysoc->country_code == 'IN' || getDolGlobalString('MAIN_VAT_LABEL_IS_POSITIVE_RATES')) {
6638 // Label with all localtax and code. For example: x.y / a.b / c.d (CODE)'
6639 $return .= $rate['labelpositiverates'];
6640 } else {
6641 // Simple label
6642 $return .= vatrate($rate['label']);
6643 }
6644
6645 //$return.=($rate['code']?' '.$rate['code']:'');
6646 $return .= (empty($rate['code']) && $rate['nprtva']) ? ' *' : ''; // We show the * (old behaviour only if new vat code is not used)
6647
6648 $return .= '</option>';
6649 }
6650
6651 if (!$options_only) {
6652 $return .= '</select>';
6653 //$return .= ajax_combobox($htmlname); // This break for the moment the dynamic autoselection of a value when selecting a product in object lines
6654 }
6655 } else {
6656 $return .= $this->error;
6657 }
6658
6659 $this->num = $num;
6660 return $return;
6661 }
6662
6663
6664 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6665
6690 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 = '')
6691 {
6692 // phpcs:enable
6693 dol_syslog(__METHOD__ . ': using select_date is deprecated. Use selectDate instead.', LOG_WARNING);
6694 $retstring = $this->selectDate($set_time, $prefix, $h, $m, $empty, $form_name, $d, $addnowlink, $disabled, $fullday, $addplusone, $adddateof);
6695 if (!empty($nooutput)) {
6696 return $retstring;
6697 }
6698 print $retstring;
6699
6700 return '';
6701 }
6702
6718 public function selectDateToDate($set_time = '', $set_time_end = '', $prefix = 're', $empty = 0, $forcenewline = 0)
6719 {
6720 global $langs;
6721
6722 $ret = $this->selectDate($set_time, $prefix . '_start', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("from"), 'tzuserrel');
6723 if ($forcenewline) {
6724 $ret .= '<br>';
6725 }
6726 $ret .= $this->selectDate($set_time_end, $prefix . '_end', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"), 'tzuserrel');
6727 return $ret;
6728 }
6729
6757 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')
6758 {
6759 global $conf, $langs;
6760
6761 if ($gm === 'auto') {
6762 $gm = (empty($conf) ? 'tzserver' : $conf->tzuserinputkey);
6763 }
6764
6765 $retstring = '';
6766
6767 if ($prefix == '') {
6768 $prefix = 're';
6769 }
6770 if ($h == '') {
6771 $h = 0;
6772 }
6773 if ($m == '') {
6774 $m = 0;
6775 }
6776 $emptydate = 0;
6777 $emptyhours = 0;
6778 if ($stepminutes <= 0 || $stepminutes > 30) {
6779 $stepminutes = 1;
6780 }
6781 if ($empty == 1) {
6782 $emptydate = 1;
6783 $emptyhours = 1;
6784 }
6785 if ($empty == 2) {
6786 $emptydate = 0;
6787 $emptyhours = 1;
6788 }
6789 $orig_set_time = $set_time;
6790
6791 if ($set_time === '' && $emptydate == 0) {
6792 include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
6793 if ($gm == 'tzuser' || $gm == 'tzuserrel') {
6794 $set_time = dol_now($gm);
6795 } else {
6796 $set_time = dol_now('tzuser') - (getServerTimeZoneInt('now') * 3600); // set_time must be relative to PHP server timezone
6797 }
6798 }
6799
6800 // Analysis of the pre-selection date
6801 $reg = array();
6802 $shour = '';
6803 $smin = '';
6804 $ssec = '';
6805 if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', $set_time, $reg)) { // deprecated usage
6806 // Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'
6807 $syear = (!empty($reg[1]) ? $reg[1] : '');
6808 $smonth = (!empty($reg[2]) ? $reg[2] : '');
6809 $sday = (!empty($reg[3]) ? $reg[3] : '');
6810 $shour = (!empty($reg[4]) ? $reg[4] : '');
6811 $smin = (!empty($reg[5]) ? $reg[5] : '');
6812 } elseif (strval($set_time) != '' && $set_time != -1) {
6813 // set_time est un timestamps (0 possible)
6814 $syear = dol_print_date($set_time, "%Y", $gm);
6815 $smonth = dol_print_date($set_time, "%m", $gm);
6816 $sday = dol_print_date($set_time, "%d", $gm);
6817 if ($orig_set_time != '') {
6818 $shour = dol_print_date($set_time, "%H", $gm);
6819 $smin = dol_print_date($set_time, "%M", $gm);
6820 $ssec = dol_print_date($set_time, "%S", $gm);
6821 }
6822 } else {
6823 // Date est '' ou vaut -1
6824 $syear = '';
6825 $smonth = '';
6826 $sday = '';
6827 $shour = !isset($conf->global->MAIN_DEFAULT_DATE_HOUR) ? ($h == -1 ? '23' : '') : $conf->global->MAIN_DEFAULT_DATE_HOUR;
6828 $smin = !isset($conf->global->MAIN_DEFAULT_DATE_MIN) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_MIN;
6829 $ssec = !isset($conf->global->MAIN_DEFAULT_DATE_SEC) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_SEC;
6830 }
6831 if ($h == 3) {
6832 $shour = '';
6833 }
6834 if ($m == 3) {
6835 $smin = '';
6836 }
6837
6838 $nowgmt = dol_now('gmt');
6839 //var_dump(dol_print_date($nowgmt, 'dayhourinputnoreduce', 'tzuserrel'));
6840
6841 // You can set MAIN_POPUP_CALENDAR to 'eldy' or 'jquery'
6842 $usecalendar = 'combo';
6843 if (!empty($conf->use_javascript_ajax) && (!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') != "none")) {
6844 $usecalendar = ((!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') == 'eldy') ? 'jquery' : $conf->global->MAIN_POPUP_CALENDAR);
6845 }
6846
6847 if ($d) {
6848 // Show date with popup
6849 if ($usecalendar != 'combo') {
6850 $formated_date = '';
6851 //print "e".$set_time." t ".$conf->format_date_short;
6852 if (strval($set_time) != '' && $set_time != -1) {
6853 //$formated_date=dol_print_date($set_time,$conf->format_date_short);
6854 $formated_date = dol_print_date($set_time, $langs->trans("FormatDateShortInput"), $gm); // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
6855 }
6856
6857 // Calendrier popup version eldy
6858 if ($usecalendar == "eldy") {
6859 // Input area to enter date manually
6860 $retstring .= '<input id="' . $prefix . '" name="' . $prefix . '" type="text" class="maxwidthdate" maxlength="11" value="' . $formated_date . '"';
6861 $retstring .= ($disabled ? ' disabled' : '');
6862 $retstring .= ' onChange="dpChangeDay(\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
6863 $retstring .= '>';
6864
6865 // Icon calendar
6866 $retstringbuttom = '';
6867 if (!$disabled) {
6868 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons"';
6869 $base = DOL_URL_ROOT . '/core/';
6870 $retstringbuttom .= ' onClick="showDP(\'' . $base . '\',\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\',\'' . $langs->defaultlang . '\');"';
6871 $retstringbuttom .= '>' . img_object($langs->trans("SelectDate"), 'calendarday', 'class="datecallink"') . '</button>';
6872 } else {
6873 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
6874 }
6875 $retstring = $retstringbuttom . $retstring;
6876
6877 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
6878 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
6879 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
6880 } elseif ($usecalendar == 'jquery') {
6881 if (!$disabled) {
6882 // Output javascript for datepicker
6883 $minYear = getDolGlobalInt('MIN_YEAR_SELECT_DATE', (date('Y') - 100));
6884 $maxYear = getDolGlobalInt('MAX_YEAR_SELECT_DATE', (date('Y') + 100));
6885
6886 $retstring .= '<script nonce="' . getNonce() . '" type="text/javascript">';
6887 $retstring .= "$(function(){ $('#" . $prefix . "').datepicker({
6888 dateFormat: '" . $langs->trans("FormatDateShortJQueryInput") . "',
6889 autoclose: true,
6890 todayHighlight: true,
6891 yearRange: '" . $minYear . ":" . $maxYear . "',";
6892 if (!empty($conf->dol_use_jmobile)) {
6893 $retstring .= "
6894 beforeShow: function (input, datePicker) {
6895 input.disabled = true;
6896 },
6897 onClose: function (dateText, datePicker) {
6898 this.disabled = false;
6899 },
6900 ";
6901 }
6902 // Note: We don't need monthNames, monthNamesShort, dayNames, dayNamesShort, dayNamesMin, they are set globally on datepicker component in lib_head.js.php
6903 if (!getDolGlobalString('MAIN_POPUP_CALENDAR_ON_FOCUS')) {
6904 $retstring .= "
6905 showOn: 'button', /* both has problem with autocompletion */
6906 buttonImage: '" . DOL_URL_ROOT . "/theme/" . dol_escape_js($conf->theme) . "/img/object_calendarday.png',
6907 buttonImageOnly: true";
6908 }
6909 $retstring .= "
6910 }) });";
6911 $retstring .= "</script>";
6912 }
6913
6914 // Zone de saisie manuelle de la date
6915 $retstring .= '<div class="nowraponall inline-block divfordateinput">';
6916 $retstring .= '<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidthdate" maxlength="11" value="'.$formated_date.'"';
6917 $retstring .= ($disabled ? ' disabled' : '');
6918 $retstring .= ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '');
6919 $retstring .= ' onChange="dpChangeDay(\'' . dol_escape_js($prefix) . '\',\'' . dol_escape_js($langs->trans("FormatDateShortJavaInput")) . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
6920 $retstring .= '>';
6921
6922 // Icone calendrier
6923 if (!$disabled) {
6924 /* Not required. Managed by option buttonImage of jquery
6925 $retstring.=img_object($langs->trans("SelectDate"),'calendarday','id="'.$prefix.'id" class="datecallink"');
6926 $retstring.='<script nonce="'.getNonce().'" type="text/javascript">';
6927 $retstring.="jQuery(document).ready(function() {";
6928 $retstring.=' jQuery("#'.$prefix.'id").click(function() {';
6929 $retstring.=" jQuery('#".$prefix."').focus();";
6930 $retstring.=' });';
6931 $retstring.='});';
6932 $retstring.="</script>";*/
6933 } else {
6934 $retstringbutton = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
6935 $retsring = $retstringbutton . $retstring;
6936 }
6937
6938 $retstring .= '</div>';
6939 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
6940 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
6941 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
6942 } else {
6943 $retstring .= "Bad value of MAIN_POPUP_CALENDAR";
6944 }
6945 } else {
6946 // Show date with combo selects
6947 // Day
6948 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50imp" id="' . $prefix . 'day" name="' . $prefix . 'day">';
6949
6950 if ($emptydate || $set_time == -1) {
6951 $retstring .= '<option value="0" selected>&nbsp;</option>';
6952 }
6953
6954 for ($day = 1; $day <= 31; $day++) {
6955 $retstring .= '<option value="' . $day . '"' . ($day == $sday ? ' selected' : '') . '>' . $day . '</option>';
6956 }
6957
6958 $retstring .= "</select>";
6959
6960 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'month" name="' . $prefix . 'month">';
6961 if ($emptydate || $set_time == -1) {
6962 $retstring .= '<option value="0" selected>&nbsp;</option>';
6963 }
6964
6965 // Month
6966 for ($month = 1; $month <= 12; $month++) {
6967 $retstring .= '<option value="' . $month . '"' . ($month == $smonth ? ' selected' : '') . '>';
6968 $retstring .= dol_print_date(mktime(12, 0, 0, $month, 1, 2000), "%b");
6969 $retstring .= "</option>";
6970 }
6971 $retstring .= "</select>";
6972
6973 // Year
6974 if ($emptydate || $set_time == -1) {
6975 $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 . '">';
6976 } else {
6977 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'year" name="' . $prefix . 'year">';
6978
6979 for ($year = $syear - 10; $year < $syear + 10; $year++) {
6980 $retstring .= '<option value="' . $year . '"' . ($year == $syear ? ' selected' : '') . '>' . $year . '</option>';
6981 }
6982 $retstring .= "</select>\n";
6983 }
6984 }
6985 }
6986
6987 if ($d && $h) {
6988 $retstring .= ($h == 2 ? '<br>' : ' ');
6989 $retstring .= '<span class="nowraponall">';
6990 }
6991
6992 if ($h) {
6993 $hourstart = 0;
6994 $hourend = 24;
6995 if ($openinghours != '') {
6996 $openinghours = explode(',', $openinghours);
6997 $hourstart = $openinghours[0];
6998 $hourend = $openinghours[1];
6999 if ($hourend < $hourstart) {
7000 $hourend = $hourstart;
7001 }
7002 }
7003 // Show hour
7004 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'hour' : '') . '" id="' . $prefix . 'hour" name="' . $prefix . 'hour">';
7005 if ($emptyhours) {
7006 $retstring .= '<option value="-1">&nbsp;</option>';
7007 }
7008 for ($hour = $hourstart; $hour < $hourend; $hour++) {
7009 if (strlen($hour) < 2) {
7010 $hour = "0" . $hour;
7011 }
7012 $retstring .= '<option value="' . $hour . '"' . (($hour == $shour) ? ' selected' : '') . '>' . $hour;
7013 //$retstring .= (empty($conf->dol_optimize_smallscreen) ? '' : 'H');
7014 $retstring .= '</option>';
7015 }
7016 $retstring .= '</select>';
7017 //if ($m && empty($conf->dol_optimize_smallscreen)) $retstring .= ":";
7018 if ($m) {
7019 $retstring .= ":";
7020 }
7021 }
7022
7023 if ($m) {
7024 // Show minutes
7025 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'min' : '') . '" id="' . $prefix . 'min" name="' . $prefix . 'min">';
7026 if ($emptyhours) {
7027 $retstring .= '<option value="-1">&nbsp;</option>';
7028 }
7029 for ($min = 0; $min < 60; $min += $stepminutes) {
7030 if (strlen($min) < 2) {
7031 $min = "0" . $min;
7032 }
7033 $retstring .= '<option value="' . $min . '"' . (($min == $smin) ? ' selected' : '') . '>' . $min . (empty($conf->dol_optimize_smallscreen) ? '' : '') . '</option>';
7034 }
7035 $retstring .= '</select>';
7036
7037 $retstring .= '<input type="hidden" name="' . $prefix . 'sec" value="' . $ssec . '">';
7038 }
7039
7040 if ($d && $h) {
7041 $retstring .= '</span>';
7042 }
7043
7044 // Add a "Now" link
7045 if (!empty($conf->use_javascript_ajax) && $addnowlink) {
7046 // Script which will be inserted in the onClick of the "Now" link
7047 $reset_scripts = "";
7048 if ($addnowlink == 2) { // local computer time
7049 // pad add leading 0 on numbers
7050 $reset_scripts .= "Number.prototype.pad = function(size) {
7051 var s = String(this);
7052 while (s.length < (size || 2)) {s = '0' + s;}
7053 return s;
7054 };
7055 var d = new Date();";
7056 }
7057
7058 // Generate the date part, depending on the use or not of the javascript calendar
7059 if ($addnowlink == 1) { // server time expressed in user time setup
7060 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7061 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7062 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7063 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7064 } elseif ($addnowlink == 2) {
7065 /* Disabled because the output does not use the string format defined by FormatDateShort key to forge the value into #prefix.
7066 * This break application for foreign languages.
7067 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(d.toLocaleDateString(\''.str_replace('_', '-', $langs->defaultlang).'\'));';
7068 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(d.getDate().pad());';
7069 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(parseInt(d.getMonth().pad()) + 1);';
7070 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(d.getFullYear());';
7071 */
7072 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7073 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7074 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7075 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7076 }
7077 /*if ($usecalendar == "eldy")
7078 {
7079 $base=DOL_URL_ROOT.'/core/';
7080 $reset_scripts .= 'resetDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');';
7081 }
7082 else
7083 {
7084 $reset_scripts .= 'this.form.elements[\''.$prefix.'day\'].value=formatDate(new Date(), \'d\'); ';
7085 $reset_scripts .= 'this.form.elements[\''.$prefix.'month\'].value=formatDate(new Date(), \'M\'); ';
7086 $reset_scripts .= 'this.form.elements[\''.$prefix.'year\'].value=formatDate(new Date(), \'yyyy\'); ';
7087 }*/
7088 // Update the hour part
7089 if ($h) {
7090 if ($fullday) {
7091 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7092 }
7093 //$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); ';
7094 if ($addnowlink == 1) {
7095 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7096 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7097 } elseif ($addnowlink == 2) {
7098 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(d.getHours().pad());';
7099 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7100 }
7101
7102 if ($fullday) {
7103 $reset_scripts .= ' } ';
7104 }
7105 }
7106 // Update the minute part
7107 if ($m) {
7108 if ($fullday) {
7109 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7110 }
7111 //$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); ';
7112 if ($addnowlink == 1) {
7113 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7114 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7115 } elseif ($addnowlink == 2) {
7116 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(d.getMinutes().pad());';
7117 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7118 }
7119 if ($fullday) {
7120 $reset_scripts .= ' } ';
7121 }
7122 }
7123 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7124 if ($reset_scripts && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7125 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonNow" type="button" name="_useless" value="now" onClick="' . $reset_scripts . '">';
7126 $retstring .= $langs->trans("Now");
7127 $retstring .= '</button> ';
7128 }
7129 }
7130
7131 // Add a "Plus one hour" link
7132 if ($conf->use_javascript_ajax && $addplusone) {
7133 // Script which will be inserted in the onClick of the "Add plusone" link
7134 $reset_scripts = "";
7135
7136 // Generate the date part, depending on the use or not of the javascript calendar
7137 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'dayinputnoreduce', 'tzuserrel') . '\');';
7138 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7139 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7140 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7141 // Update the hour part
7142 if ($h) {
7143 if ($fullday) {
7144 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7145 }
7146 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7147 if ($fullday) {
7148 $reset_scripts .= ' } ';
7149 }
7150 }
7151 // Update the minute part
7152 if ($m) {
7153 if ($fullday) {
7154 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7155 }
7156 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7157 if ($fullday) {
7158 $reset_scripts .= ' } ';
7159 }
7160 }
7161 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7162 if ($reset_scripts && empty($conf->dol_optimize_smallscreen)) {
7163 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonPlusOne" type="button" name="_useless2" value="plusone" onClick="' . $reset_scripts . '">';
7164 $retstring .= $langs->trans("DateStartPlusOne");
7165 $retstring .= '</button> ';
7166 }
7167 }
7168
7169 // Add a link to set data
7170 if ($conf->use_javascript_ajax && !empty($adddateof)) {
7171 if (!is_array($adddateof)) {
7172 $arrayofdateof = array(array('adddateof'=>$adddateof, 'labeladddateof'=>$labeladddateof));
7173 } else {
7174 $arrayofdateof = $adddateof;
7175 }
7176 foreach ($arrayofdateof as $valuedateof) {
7177 $tmpadddateof = empty($valuedateof['adddateof']) ? 0 : $valuedateof['adddateof'];
7178 $tmplabeladddateof = empty($valuedateof['labeladddateof']) ? '' : $valuedateof['labeladddateof'];
7179 $tmparray = dol_getdate($tmpadddateof);
7180 if (empty($tmplabeladddateof)) {
7181 $tmplabeladddateof = $langs->trans("DateInvoice");
7182 }
7183 $reset_scripts = 'console.log(\'Click on now link\'); ';
7184 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date($tmpadddateof, 'dayinputnoreduce').'\');';
7185 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.$tmparray['mday'].'\');';
7186 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.$tmparray['mon'].'\');';
7187 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.$tmparray['year'].'\');';
7188 $retstring .= ' - <button class="dpInvisibleButtons datenowlink" id="dateofinvoice" type="button" name="_dateofinvoice" value="now" onclick="'.$reset_scripts.'">'.$tmplabeladddateof.'</button>';
7189 }
7190 }
7191
7192 return $retstring;
7193 }
7194
7203 public function selectTypeDuration($prefix, $selected = 'i', $excludetypes = array())
7204 {
7205 global $langs;
7206
7207 $TDurationTypes = array(
7208 'y' => $langs->trans('Years'),
7209 'm' => $langs->trans('Month'),
7210 'w' => $langs->trans('Weeks'),
7211 'd' => $langs->trans('Days'),
7212 'h' => $langs->trans('Hours'),
7213 'i' => $langs->trans('Minutes')
7214 );
7215
7216 // Removed undesired duration types
7217 foreach ($excludetypes as $value) {
7218 unset($TDurationTypes[$value]);
7219 }
7220
7221 $retstring = '<select class="flat minwidth75 maxwidth100" id="select_' . $prefix . 'type_duration" name="' . $prefix . 'type_duration">';
7222 foreach ($TDurationTypes as $key => $typeduration) {
7223 $retstring .= '<option value="' . $key . '"';
7224 if ($key == $selected) {
7225 $retstring .= " selected";
7226 }
7227 $retstring .= ">" . $typeduration . "</option>";
7228 }
7229 $retstring .= "</select>";
7230
7231 $retstring .= ajax_combobox('select_' . $prefix . 'type_duration');
7232
7233 return $retstring;
7234 }
7235
7236 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
7237
7251 public function select_duration($prefix, $iSecond = '', $disabled = 0, $typehour = 'select', $minunderhours = 0, $nooutput = 0)
7252 {
7253 // phpcs:enable
7254 global $langs;
7255
7256 $retstring = '<span class="nowraponall">';
7257
7258 $hourSelected = '';
7259 $minSelected = '';
7260
7261 // Hours
7262 if ($iSecond != '') {
7263 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7264
7265 $hourSelected = convertSecondToTime($iSecond, 'allhour');
7266 $minSelected = convertSecondToTime($iSecond, 'min');
7267 }
7268
7269 if ($typehour == 'select') {
7270 $retstring .= '<select class="flat" id="select_' . $prefix . 'hour" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . '>';
7271 for ($hour = 0; $hour < 25; $hour++) { // For a duration, we allow 24 hours
7272 $retstring .= '<option value="' . $hour . '"';
7273 if (is_numeric($hourSelected) && $hourSelected == $hour) {
7274 $retstring .= " selected";
7275 }
7276 $retstring .= ">" . $hour . "</option>";
7277 }
7278 $retstring .= "</select>";
7279 } elseif ($typehour == 'text' || $typehour == 'textselect') {
7280 $retstring .= '<input placeholder="' . $langs->trans('HourShort') . '" type="number" min="0" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputhour right" value="' . (($hourSelected != '') ? ((int) $hourSelected) : '') . '">';
7281 } else {
7282 return 'BadValueForParameterTypeHour';
7283 }
7284
7285 if ($typehour != 'text') {
7286 $retstring .= ' ' . $langs->trans('HourShort');
7287 } else {
7288 $retstring .= '<span class="">:</span>';
7289 }
7290
7291 // Minutes
7292 if ($minunderhours) {
7293 $retstring .= '<br>';
7294 } else {
7295 if ($typehour != 'text') {
7296 $retstring .= '<span class="hideonsmartphone">&nbsp;</span>';
7297 }
7298 }
7299
7300 if ($typehour == 'select' || $typehour == 'textselect') {
7301 $retstring .= '<select class="flat" id="select_' . $prefix . 'min" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . '>';
7302 for ($min = 0; $min <= 55; $min = $min + 5) {
7303 $retstring .= '<option value="' . $min . '"';
7304 if (is_numeric($minSelected) && $minSelected == $min) {
7305 $retstring .= ' selected';
7306 }
7307 $retstring .= '>' . $min . '</option>';
7308 }
7309 $retstring .= "</select>";
7310 } elseif ($typehour == 'text') {
7311 $retstring .= '<input placeholder="' . $langs->trans('MinuteShort') . '" type="number" min="0" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputminute right" value="' . (($minSelected != '') ? ((int) $minSelected) : '') . '">';
7312 }
7313
7314 if ($typehour != 'text') {
7315 $retstring .= ' ' . $langs->trans('MinuteShort');
7316 }
7317
7318 $retstring .= "</span>";
7319
7320 if (!empty($nooutput)) {
7321 return $retstring;
7322 }
7323
7324 print $retstring;
7325
7326 return '';
7327 }
7328
7348 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)
7349 {
7350 global $langs, $conf;
7351
7352 $out = '';
7353
7354 // check parameters
7355 if (is_null($ajaxoptions)) {
7356 $ajaxoptions = array();
7357 }
7358
7359 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7360 $placeholder = '';
7361
7362 if ($selected && empty($selected_input_value)) {
7363 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7364 $tickettmpselect = new Ticket($this->db);
7365 $tickettmpselect->fetch($selected);
7366 $selected_input_value = $tickettmpselect->ref;
7367 unset($tickettmpselect);
7368 }
7369
7370 $urloption = '';
7371 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/ticket/ajax/tickets.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7372
7373 if (empty($hidelabel)) {
7374 $out .= $langs->trans("RefOrLabel") . ' : ';
7375 } elseif ($hidelabel > 1) {
7376 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7377 if ($hidelabel == 2) {
7378 $out .= img_picto($langs->trans("Search"), 'search');
7379 }
7380 }
7381 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7382 if ($hidelabel == 3) {
7383 $out .= img_picto($langs->trans("Search"), 'search');
7384 }
7385 } else {
7386 $out .= $this->selectTicketsList($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss);
7387 }
7388
7389 if (empty($nooutput)) {
7390 print $out;
7391 } else {
7392 return $out;
7393 }
7394 return '';
7395 }
7396
7397
7414 public function selectTicketsList($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7415 {
7416 global $langs, $conf;
7417
7418 $out = '';
7419 $outarray = array();
7420
7421 $selectFields = " p.rowid, p.ref, p.message";
7422
7423 $sql = "SELECT ";
7424 $sql .= $selectFields;
7425 $sql .= " FROM " . $this->db->prefix() . "ticket as p";
7426 $sql .= ' WHERE p.entity IN (' . getEntity('ticket') . ')';
7427
7428 // Add criteria on ref/label
7429 if ($filterkey != '') {
7430 $sql .= ' AND (';
7431 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7432 // For natural search
7433 $scrit = explode(' ', $filterkey);
7434 $i = 0;
7435 if (count($scrit) > 1) {
7436 $sql .= "(";
7437 }
7438 foreach ($scrit as $crit) {
7439 if ($i > 0) {
7440 $sql .= " AND ";
7441 }
7442 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.subject LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7443 $sql .= ")";
7444 $i++;
7445 }
7446 if (count($scrit) > 1) {
7447 $sql .= ")";
7448 }
7449 $sql .= ')';
7450 }
7451
7452 $sql .= $this->db->plimit($limit, 0);
7453
7454 // Build output string
7455 dol_syslog(get_class($this) . "::selectTicketsList search tickets", LOG_DEBUG);
7456 $result = $this->db->query($sql);
7457 if ($result) {
7458 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7459 require_once DOL_DOCUMENT_ROOT . '/core/lib/ticket.lib.php';
7460
7461 $num = $this->db->num_rows($result);
7462
7463 $events = null;
7464
7465 if (!$forcecombo) {
7466 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7467 $out .= ajax_combobox($htmlname, $events, $conf->global->TICKET_USE_SEARCH_TO_SELECT);
7468 }
7469
7470 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7471
7472 $textifempty = '';
7473 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7474 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7475 if (getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7476 if ($showempty && !is_numeric($showempty)) {
7477 $textifempty = $langs->trans($showempty);
7478 } else {
7479 $textifempty .= $langs->trans("All");
7480 }
7481 } else {
7482 if ($showempty && !is_numeric($showempty)) {
7483 $textifempty = $langs->trans($showempty);
7484 }
7485 }
7486 if ($showempty) {
7487 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7488 }
7489
7490 $i = 0;
7491 while ($num && $i < $num) {
7492 $opt = '';
7493 $optJson = array();
7494 $objp = $this->db->fetch_object($result);
7495
7496 $this->constructTicketListOption($objp, $opt, $optJson, $selected, $filterkey);
7497 // Add new entry
7498 // "key" value of json key array is used by jQuery automatically as selected value
7499 // "label" value of json key array is used by jQuery automatically as text for combo box
7500 $out .= $opt;
7501 array_push($outarray, $optJson);
7502
7503 $i++;
7504 }
7505
7506 $out .= '</select>';
7507
7508 $this->db->free($result);
7509
7510 if (empty($outputmode)) {
7511 return $out;
7512 }
7513 return $outarray;
7514 } else {
7515 dol_print_error($this->db);
7516 }
7517
7518 return array();
7519 }
7520
7532 protected function constructTicketListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7533 {
7534 $outkey = '';
7535 $outref = '';
7536 $outtype = '';
7537
7538 $outkey = $objp->rowid;
7539 $outref = $objp->ref;
7540 $outtype = $objp->fk_product_type;
7541
7542 $opt = '<option value="' . $objp->rowid . '"';
7543 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7544 $opt .= '>';
7545 $opt .= $objp->ref;
7546 $objRef = $objp->ref;
7547 if (!empty($filterkey) && $filterkey != '') {
7548 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
7549 }
7550
7551 $opt .= "</option>\n";
7552 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
7553 }
7554
7574 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)
7575 {
7576 global $langs, $conf;
7577
7578 $out = '';
7579
7580 // check parameters
7581 if (is_null($ajaxoptions)) {
7582 $ajaxoptions = array();
7583 }
7584
7585 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7586 $placeholder = '';
7587
7588 if ($selected && empty($selected_input_value)) {
7589 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7590 $projecttmpselect = new Project($this->db);
7591 $projecttmpselect->fetch($selected);
7592 $selected_input_value = $projecttmpselect->ref;
7593 unset($projecttmpselect);
7594 }
7595
7596 $urloption = '';
7597 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/projet/ajax/projects.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7598
7599 if (empty($hidelabel)) {
7600 $out .= $langs->trans("RefOrLabel") . ' : ';
7601 } elseif ($hidelabel > 1) {
7602 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7603 if ($hidelabel == 2) {
7604 $out .= img_picto($langs->trans("Search"), 'search');
7605 }
7606 }
7607 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7608 if ($hidelabel == 3) {
7609 $out .= img_picto($langs->trans("Search"), 'search');
7610 }
7611 } else {
7612 $out .= $this->selectProjectsList($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss);
7613 }
7614
7615 if (empty($nooutput)) {
7616 print $out;
7617 } else {
7618 return $out;
7619 }
7620 return '';
7621 }
7622
7639 public function selectProjectsList($selected = '', $htmlname = 'projectid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7640 {
7641 global $langs, $conf;
7642
7643 $out = '';
7644 $outarray = array();
7645
7646 $selectFields = " p.rowid, p.ref";
7647
7648 $sql = "SELECT ";
7649 $sql .= $selectFields;
7650 $sql .= " FROM " . $this->db->prefix() . "projet as p";
7651 $sql .= ' WHERE p.entity IN (' . getEntity('project') . ')';
7652
7653 // Add criteria on ref/label
7654 if ($filterkey != '') {
7655 $sql .= ' AND (';
7656 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7657 // For natural search
7658 $scrit = explode(' ', $filterkey);
7659 $i = 0;
7660 if (count($scrit) > 1) {
7661 $sql .= "(";
7662 }
7663 foreach ($scrit as $crit) {
7664 if ($i > 0) {
7665 $sql .= " AND ";
7666 }
7667 $sql .= "p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7668 $sql .= "";
7669 $i++;
7670 }
7671 if (count($scrit) > 1) {
7672 $sql .= ")";
7673 }
7674 $sql .= ')';
7675 }
7676
7677 $sql .= $this->db->plimit($limit, 0);
7678
7679 // Build output string
7680 dol_syslog(get_class($this) . "::selectProjectsList search projects", LOG_DEBUG);
7681 $result = $this->db->query($sql);
7682 if ($result) {
7683 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7684 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
7685
7686 $num = $this->db->num_rows($result);
7687
7688 $events = null;
7689
7690 if (!$forcecombo) {
7691 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7692 $out .= ajax_combobox($htmlname, $events, $conf->global->PROJECT_USE_SEARCH_TO_SELECT);
7693 }
7694
7695 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7696
7697 $textifempty = '';
7698 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7699 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7700 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
7701 if ($showempty && !is_numeric($showempty)) {
7702 $textifempty = $langs->trans($showempty);
7703 } else {
7704 $textifempty .= $langs->trans("All");
7705 }
7706 } else {
7707 if ($showempty && !is_numeric($showempty)) {
7708 $textifempty = $langs->trans($showempty);
7709 }
7710 }
7711 if ($showempty) {
7712 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7713 }
7714
7715 $i = 0;
7716 while ($num && $i < $num) {
7717 $opt = '';
7718 $optJson = array();
7719 $objp = $this->db->fetch_object($result);
7720
7721 $this->constructProjectListOption($objp, $opt, $optJson, $selected, $filterkey);
7722 // Add new entry
7723 // "key" value of json key array is used by jQuery automatically as selected value
7724 // "label" value of json key array is used by jQuery automatically as text for combo box
7725 $out .= $opt;
7726 array_push($outarray, $optJson);
7727
7728 $i++;
7729 }
7730
7731 $out .= '</select>';
7732
7733 $this->db->free($result);
7734
7735 if (empty($outputmode)) {
7736 return $out;
7737 }
7738 return $outarray;
7739 } else {
7740 dol_print_error($this->db);
7741 }
7742
7743 return array();
7744 }
7745
7757 protected function constructProjectListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7758 {
7759 $outkey = '';
7760 $outref = '';
7761 $outtype = '';
7762
7763 $label = $objp->label;
7764
7765 $outkey = $objp->rowid;
7766 $outref = $objp->ref;
7767 $outlabel = $objp->label;
7768 $outtype = $objp->fk_product_type;
7769
7770 $opt = '<option value="' . $objp->rowid . '"';
7771 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7772 $opt .= '>';
7773 $opt .= $objp->ref;
7774 $objRef = $objp->ref;
7775 if (!empty($filterkey) && $filterkey != '') {
7776 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
7777 }
7778
7779 $opt .= "</option>\n";
7780 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
7781 }
7782
7783
7803 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)
7804 {
7805 global $langs, $conf;
7806
7807 $out = '';
7808
7809 // check parameters
7810 if (is_null($ajaxoptions)) {
7811 $ajaxoptions = array();
7812 }
7813
7814 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7815 $placeholder = '';
7816 $urloption = '';
7817
7818 if ($selected && empty($selected_input_value)) {
7819 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
7820 $adherenttmpselect = new Adherent($this->db);
7821 $adherenttmpselect->fetch($selected);
7822 $selected_input_value = $adherenttmpselect->ref;
7823 unset($adherenttmpselect);
7824 }
7825
7826 $urloption = '';
7827
7828 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/adherents/ajax/adherents.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7829
7830 if (empty($hidelabel)) {
7831 $out .= $langs->trans("RefOrLabel") . ' : ';
7832 } elseif ($hidelabel > 1) {
7833 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7834 if ($hidelabel == 2) {
7835 $out .= img_picto($langs->trans("Search"), 'search');
7836 }
7837 }
7838 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7839 if ($hidelabel == 3) {
7840 $out .= img_picto($langs->trans("Search"), 'search');
7841 }
7842 } else {
7843 $filterkey = '';
7844
7845 $out .= $this->selectMembersList($selected, $htmlname, $filtertype, $limit, $filterkey, $status, 0, $showempty, $forcecombo, $morecss);
7846 }
7847
7848 if (empty($nooutput)) {
7849 print $out;
7850 } else {
7851 return $out;
7852 }
7853 return '';
7854 }
7855
7872 public function selectMembersList($selected = '', $htmlname = 'adherentid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7873 {
7874 global $langs, $conf;
7875
7876 $out = '';
7877 $outarray = array();
7878
7879 $selectFields = " p.rowid, p.ref, p.firstname, p.lastname, p.fk_adherent_type";
7880
7881 $sql = "SELECT ";
7882 $sql .= $selectFields;
7883 $sql .= " FROM " . $this->db->prefix() . "adherent as p";
7884 $sql .= ' WHERE p.entity IN (' . getEntity('adherent') . ')';
7885
7886 // Add criteria on ref/label
7887 if ($filterkey != '') {
7888 $sql .= ' AND (';
7889 $prefix = !getDolGlobalString('MEMBER_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7890 // For natural search
7891 $scrit = explode(' ', $filterkey);
7892 $i = 0;
7893 if (count($scrit) > 1) {
7894 $sql .= "(";
7895 }
7896 foreach ($scrit as $crit) {
7897 if ($i > 0) {
7898 $sql .= " AND ";
7899 }
7900 $sql .= "(p.firstname LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7901 $sql .= " OR p.lastname LIKE '" . $this->db->escape($prefix . $crit) . "%')";
7902 $i++;
7903 }
7904 if (count($scrit) > 1) {
7905 $sql .= ")";
7906 }
7907 $sql .= ')';
7908 }
7909 if ($status != -1) {
7910 $sql .= ' AND statut = ' . ((int) $status);
7911 }
7912 $sql .= $this->db->plimit($limit, 0);
7913
7914 // Build output string
7915 dol_syslog(get_class($this) . "::selectMembersList search adherents", LOG_DEBUG);
7916 $result = $this->db->query($sql);
7917 if ($result) {
7918 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
7919 require_once DOL_DOCUMENT_ROOT . '/core/lib/member.lib.php';
7920
7921 $num = $this->db->num_rows($result);
7922
7923 $events = null;
7924
7925 if (!$forcecombo) {
7926 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7927 $out .= ajax_combobox($htmlname, $events, getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT') ? $conf->global->PROJECT_USE_SEARCH_TO_SELECT : '');
7928 }
7929
7930 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7931
7932 $textifempty = '';
7933 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7934 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7935 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
7936 if ($showempty && !is_numeric($showempty)) {
7937 $textifempty = $langs->trans($showempty);
7938 } else {
7939 $textifempty .= $langs->trans("All");
7940 }
7941 } else {
7942 if ($showempty && !is_numeric($showempty)) {
7943 $textifempty = $langs->trans($showempty);
7944 }
7945 }
7946 if ($showempty) {
7947 $out .= '<option value="-1" selected>' . $textifempty . '</option>';
7948 }
7949
7950 $i = 0;
7951 while ($num && $i < $num) {
7952 $opt = '';
7953 $optJson = array();
7954 $objp = $this->db->fetch_object($result);
7955
7956 $this->constructMemberListOption($objp, $opt, $optJson, $selected, $filterkey);
7957
7958 // Add new entry
7959 // "key" value of json key array is used by jQuery automatically as selected value
7960 // "label" value of json key array is used by jQuery automatically as text for combo box
7961 $out .= $opt;
7962 array_push($outarray, $optJson);
7963
7964 $i++;
7965 }
7966
7967 $out .= '</select>';
7968
7969 $this->db->free($result);
7970
7971 if (empty($outputmode)) {
7972 return $out;
7973 }
7974 return $outarray;
7975 } else {
7976 dol_print_error($this->db);
7977 }
7978
7979 return array();
7980 }
7981
7993 protected function constructMemberListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7994 {
7995 $outkey = '';
7996 $outlabel = '';
7997 $outtype = '';
7998
7999 $outkey = $objp->rowid;
8000 $outlabel = dolGetFirstLastname($objp->firstname, $objp->lastname);
8001 $outtype = $objp->fk_adherent_type;
8002
8003 $opt = '<option value="' . $objp->rowid . '"';
8004 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
8005 $opt .= '>';
8006 if (!empty($filterkey) && $filterkey != '') {
8007 $outlabel = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $outlabel, 1);
8008 }
8009 $opt .= $outlabel;
8010 $opt .= "</option>\n";
8011
8012 $optJson = array('key' => $outkey, 'value' => $outlabel, 'type' => $outtype);
8013 }
8014
8035 public function selectForForms($objectdesc, $htmlname, $preSelectedValue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '', $objectfield = '')
8036 {
8037 global $conf, $extrafields, $user;
8038
8039 //var_dump($objectdesc); debug_print_backtrace();
8040
8041 $objectdescorig = $objectdesc;
8042 $objecttmp = null;
8043 $InfoFieldList = array();
8044
8045 if ($objectfield) { // We must retreive the objectdesc from the field or extrafield
8046 // Example: $objectfield = 'product:options_package'
8047 $tmparray = explode(':', $objectfield);
8048
8049 // Load object according to $id and $element
8050 $objectforfieldstmp = fetchObjectByElement(0, strtolower($tmparray[0]));
8051
8052 if (is_object($objectforfieldstmp)) {
8053 $objectdesc = '';
8054
8055 $reg = array();
8056 if (preg_match('/^options_(.*)$/', $tmparray[1], $reg)) {
8057 // For a property in extrafields
8058 $key = $reg[1];
8059 // fetch optionals attributes and labels
8060 $extrafields->fetch_name_optionals_label($objectforfieldstmp->table_element);
8061
8062 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key]) && $extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key] == 'link') {
8063 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options'])) {
8064 $tmpextrafields = array_keys($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options']);
8065 $objectdesc = $tmpextrafields[0];
8066 }
8067 }
8068 } else {
8069 // For a property in ->fields
8070 if (array_key_exists($tmparray[1], $objectforfieldstmp->fields)) {
8071 $objectdesc = $objectforfieldstmp->fields[$tmparray[1]]['type'];
8072 $objectdesc = preg_replace('/^integer[^:]*:/', '', $objectdesc);
8073 }
8074 }
8075 }
8076 }
8077
8078 if ($objectdesc) {
8079 // Example of value for $objectdesc:
8080 // Bom:bom/class/bom.class.php:0:t.status=1
8081 // Bom:bom/class/bom.class.php:0:t.status=1:ref
8082 // Bom:bom/class/bom.class.php:0:(t.status:=:1) OR (t.field2:=:2):ref
8083 $InfoFieldList = explode(":", $objectdesc, 4);
8084 $vartmp = (empty($InfoFieldList[3]) ? '' : $InfoFieldList[3]);
8085 $reg = array();
8086 if (preg_match('/^.*:(\w*)$/', $vartmp, $reg)) {
8087 $InfoFieldList[4] = $reg[1]; // take the sort field
8088 }
8089 $InfoFieldList[3] = preg_replace('/:\w*$/', '', $vartmp); // take the filter field
8090
8091 $classname = $InfoFieldList[0];
8092 $classpath = empty($InfoFieldList[1]) ? '' : $InfoFieldList[1];
8093 //$addcreatebuttonornot = empty($InfoFieldList[2]) ? 0 : $InfoFieldList[2];
8094 $filter = empty($InfoFieldList[3]) ? '' : $InfoFieldList[3];
8095 $sortfield = empty($InfoFieldList[4]) ? '' : $InfoFieldList[4];
8096
8097 // Load object according to $id and $element
8098 $objecttmp = fetchObjectByElement(0, strtolower($InfoFieldList[0]));
8099
8100 // Fallback to another solution to get $objecttmp
8101 if (empty($objecttmp) && !empty($classpath)) {
8102 dol_include_once($classpath);
8103
8104 if ($classname && class_exists($classname)) {
8105 $objecttmp = new $classname($this->db);
8106 }
8107 }
8108 }
8109
8110 // Make some replacement in $filter. May not be used if we used the ajax mode with $objectfield. In such a case
8111 // we propagate the $objectfield and not the filter and replacement is done by the ajax/selectobject.php component.
8112 $sharedentities = getEntity($objecttmp->element);
8113 $filter = str_replace(
8114 array('__ENTITY__', '__SHARED_ENTITIES__', '__USER_ID__'),
8115 array($conf->entity, $sharedentities, $user->id),
8116 $filter
8117 );
8118
8119 if (!is_object($objecttmp)) {
8120 dol_syslog('selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc, LOG_WARNING);
8121 return 'selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc;
8122 }
8123
8124 //var_dump($filter);
8125 $prefixforautocompletemode = $objecttmp->element;
8126 if ($prefixforautocompletemode == 'societe') {
8127 $prefixforautocompletemode = 'company';
8128 }
8129 if ($prefixforautocompletemode == 'product') {
8130 $prefixforautocompletemode = 'produit';
8131 }
8132 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8133
8134 dol_syslog(get_class($this) . "::selectForForms filter=" . $filter, LOG_DEBUG);
8135
8136 // Generate the combo HTML component
8137 $out = '';
8138 if (!empty($conf->use_javascript_ajax) && getDolGlobalString($confkeyforautocompletemode) && !$forcecombo) {
8139 // No immediate load of all database
8140 $placeholder = '';
8141
8142 if ($preSelectedValue && empty($selected_input_value)) {
8143 $objecttmp->fetch($preSelectedValue);
8144 $selected_input_value = ($prefixforautocompletemode == 'company' ? $objecttmp->name : $objecttmp->ref);
8145
8146 $oldValueForShowOnCombobox = 0;
8147 foreach ($objecttmp->fields as $fieldK => $fielV) {
8148 if (!array_key_exists('showoncombobox', $fielV) || !$fielV['showoncombobox'] || empty($objecttmp->$fieldK)) continue;
8149
8150 if (!$oldValueForShowOnCombobox) {
8151 $selected_input_value = '';
8152 }
8153
8154 $selected_input_value .= $oldValueForShowOnCombobox ? ' - ' : '';
8155 $selected_input_value .= $objecttmp->$fieldK;
8156 $oldValueForShowOnCombobox = empty($fielV['showoncombobox']) ? 0 : $fielV['showoncombobox'];
8157 }
8158 }
8159
8160 // Set url and param to call to get json of the search results
8161 $urlforajaxcall = DOL_URL_ROOT . '/core/ajax/selectobject.php';
8162 $urloption = 'htmlname=' . urlencode($htmlname) . '&outjson=1&objectdesc=' . urlencode($objectdescorig) . '&objectfield='.urlencode($objectfield) . ($sortfield ? '&sortfield=' . urlencode($sortfield) : '');
8163
8164 // Activate the auto complete using ajax call.
8165 $out .= ajax_autocompleter($preSelectedValue, $htmlname, $urlforajaxcall, $urloption, getDolGlobalString($confkeyforautocompletemode), 0);
8166 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
8167 $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) . '"' : '') . ' />';
8168 } else {
8169 // Immediate load of table record.
8170 $out .= $this->selectForFormsList($objecttmp, $htmlname, $preSelectedValue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, 0, $disabled, $sortfield, $filter);
8171 }
8172
8173 return $out;
8174 }
8175
8176
8197 public function selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $outputmode = 0, $disabled = 0, $sortfield = '', $filter = '')
8198 {
8199 global $langs, $user, $hookmanager;
8200
8201 //print "$htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, $outputmode, $disabled";
8202
8203 $prefixforautocompletemode = $objecttmp->element;
8204 if ($prefixforautocompletemode == 'societe') {
8205 $prefixforautocompletemode = 'company';
8206 }
8207 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8208
8209 if (!empty($objecttmp->fields)) { // For object that declare it, it is better to use declared fields (like societe, contact, ...)
8210 $tmpfieldstoshow = '';
8211 foreach ($objecttmp->fields as $key => $val) {
8212 if (!dol_eval($val['enabled'], 1, 1, '1')) {
8213 continue;
8214 }
8215 if (!empty($val['showoncombobox'])) {
8216 $tmpfieldstoshow .= ($tmpfieldstoshow ? ',' : '') . 't.' . $key;
8217 }
8218 }
8219 if ($tmpfieldstoshow) {
8220 $fieldstoshow = $tmpfieldstoshow;
8221 }
8222 } else {
8223 // For backward compatibility
8224 $objecttmp->fields['ref'] = array('type' => 'varchar(30)', 'label' => 'Ref', 'showoncombobox' => 1);
8225 }
8226
8227 if (empty($fieldstoshow)) {
8228 if (isset($objecttmp->fields['ref'])) {
8229 $fieldstoshow = 't.ref';
8230 } else {
8231 $langs->load("errors");
8232 $this->error = $langs->trans("ErrorNoFieldWithAttributeShowoncombobox");
8233 return $langs->trans('ErrorNoFieldWithAttributeShowoncombobox');
8234 }
8235 }
8236
8237 $out = '';
8238 $outarray = array();
8239 $tmparray = array();
8240
8241 $num = 0;
8242
8243 // Search data
8244 $sql = "SELECT t.rowid, " . $fieldstoshow . " FROM " . $this->db->prefix() . $objecttmp->table_element . " as t";
8245 if (!empty($objecttmp->isextrafieldmanaged)) {
8246 $sql .= " LEFT JOIN " . $this->db->prefix() . $objecttmp->table_element . "_extrafields as e ON t.rowid=e.fk_object";
8247 }
8248 if (isset($objecttmp->ismultientitymanaged)) {
8249 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8250 $tmparray = explode('@', $objecttmp->ismultientitymanaged);
8251 $sql .= " INNER JOIN " . $this->db->prefix() . $tmparray[1] . " as parenttable ON parenttable.rowid = t." . $tmparray[0];
8252 }
8253 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8254 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
8255 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
8256 }
8257 }
8258 }
8259
8260 // Add where from hooks
8261 $parameters = array(
8262 'object' => $objecttmp,
8263 'htmlname' => $htmlname,
8264 'filter' => $filter,
8265 'searchkey' => $searchkey
8266 );
8267
8268 $reshook = $hookmanager->executeHooks('selectForFormsListWhere', $parameters); // Note that $action and $object may have been modified by hook
8269 if (!empty($hookmanager->resPrint)) {
8270 $sql .= $hookmanager->resPrint;
8271 } else {
8272 $sql .= " WHERE 1=1";
8273 if (isset($objecttmp->ismultientitymanaged)) {
8274 if ($objecttmp->ismultientitymanaged == 1) {
8275 $sql .= " AND t.entity IN (" . getEntity($objecttmp->table_element) . ")";
8276 }
8277 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8278 $sql .= " AND parenttable.entity = t." . $tmparray[0];
8279 }
8280 if ($objecttmp->ismultientitymanaged == 1 && !empty($user->socid)) {
8281 if ($objecttmp->element == 'societe') {
8282 $sql .= " AND t.rowid = " . ((int) $user->socid);
8283 } else {
8284 $sql .= " AND t.fk_soc = " . ((int) $user->socid);
8285 }
8286 }
8287 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8288 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
8289 $sql .= " AND t.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
8290 }
8291 }
8292 }
8293 if ($searchkey != '') {
8294 $sql .= natural_search(explode(',', $fieldstoshow), $searchkey);
8295 }
8296
8297 if ($filter) { // Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
8298 $errormessage = '';
8299 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
8300 if ($errormessage) {
8301 return 'Error forging a SQL request from an universal criteria: ' . $errormessage;
8302 }
8303 }
8304 }
8305 $sql .= $this->db->order($sortfield ? $sortfield : $fieldstoshow, "ASC");
8306 //$sql.=$this->db->plimit($limit, 0);
8307 //print $sql;
8308
8309 // Build output string
8310 $resql = $this->db->query($sql);
8311 if ($resql) {
8312 // Construct $out and $outarray
8313 $out .= '<select id="' . $htmlname . '" class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ($moreparams ? ' ' . $moreparams : '') . ' name="' . $htmlname . '">' . "\n";
8314
8315 // 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
8316 $textifempty = '&nbsp;';
8317
8318 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8319 if (getDolGlobalInt($confkeyforautocompletemode)) {
8320 if ($showempty && !is_numeric($showempty)) {
8321 $textifempty = $langs->trans($showempty);
8322 } else {
8323 $textifempty .= $langs->trans("All");
8324 }
8325 }
8326 if ($showempty) {
8327 $out .= '<option value="-1">' . $textifempty . '</option>' . "\n";
8328 }
8329
8330 $num = $this->db->num_rows($resql);
8331 $i = 0;
8332 if ($num) {
8333 while ($i < $num) {
8334 $obj = $this->db->fetch_object($resql);
8335 $label = '';
8336 $labelhtml = '';
8337 $tmparray = explode(',', $fieldstoshow);
8338 $oldvalueforshowoncombobox = 0;
8339 foreach ($tmparray as $key => $val) {
8340 $val = preg_replace('/t\./', '', $val);
8341 $label .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8342 $labelhtml .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8343 $label .= $obj->$val;
8344 $labelhtml .= $obj->$val;
8345
8346 $oldvalueforshowoncombobox = empty($objecttmp->fields[$val]['showoncombobox']) ? 0 : $objecttmp->fields[$val]['showoncombobox'];
8347 }
8348 if (empty($outputmode)) {
8349 if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid) {
8350 $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>';
8351 } else {
8352 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
8353 }
8354 } else {
8355 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label));
8356 }
8357
8358 $i++;
8359 if (($i % 10) == 0) {
8360 $out .= "\n";
8361 }
8362 }
8363 }
8364
8365 $out .= '</select>' . "\n";
8366
8367 if (!$forcecombo) {
8368 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8369 $out .= ajax_combobox($htmlname, null, getDolGlobalInt($confkeyforautocompletemode, 0));
8370 }
8371 } else {
8372 dol_print_error($this->db);
8373 }
8374
8375 $this->result = array('nbofelement' => $num);
8376
8377 if ($outputmode) {
8378 return $outarray;
8379 }
8380 return $out;
8381 }
8382
8383
8407 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)
8408 {
8409 global $conf, $langs;
8410
8411 // Do we want a multiselect ?
8412 //$jsbeautify = 0;
8413 //if (preg_match('/^multi/',$htmlname)) $jsbeautify = 1;
8414 $jsbeautify = 1;
8415
8416 if ($value_as_key) {
8417 $array = array_combine($array, $array);
8418 }
8419
8420 $out = '';
8421
8422 if ($addjscombo < 0) {
8423 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8424 $addjscombo = 1;
8425 } else {
8426 $addjscombo = 0;
8427 }
8428 }
8429 $idname = str_replace(array('[', ']'), array('', ''), $htmlname);
8430 $out .= '<select id="' . preg_replace('/^\./', '', $idname) . '" ' . ($disabled ? 'disabled="disabled" ' : '') . 'class="flat ' . (preg_replace('/^\./', '', $htmlname)) . ($morecss ? ' ' . $morecss : '') . ' selectformat"';
8431 $out .= ' name="' . preg_replace('/^\./', '', $htmlname) . '" ' . ($moreparam ? $moreparam : '');
8432 $out .= '>'."\n";
8433
8434 if ($show_empty) {
8435 $textforempty = ' ';
8436 if (!empty($conf->use_javascript_ajax)) {
8437 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
8438 }
8439 if (!is_numeric($show_empty)) {
8440 $textforempty = $show_empty;
8441 }
8442 $out .= '<option class="optiongrey" ' . ($moreparamonempty ? $moreparamonempty . ' ' : '') . 'value="' . (((int) $show_empty) < 0 ? $show_empty : -1) . '"' . ($id == $show_empty ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
8443 }
8444 if (is_array($array)) {
8445 // Translate
8446 if ($translate) {
8447 foreach ($array as $key => $value) {
8448 if (!is_array($value)) {
8449 $array[$key] = $langs->trans($value);
8450 } else {
8451 $array[$key]['label'] = $langs->trans($value['label']);
8452 }
8453 }
8454 }
8455 // Sort
8456 if ($sort == 'ASC') {
8457 asort($array);
8458 } elseif ($sort == 'DESC') {
8459 arsort($array);
8460 }
8461 foreach ($array as $key => $tmpvalue) {
8462 if (is_array($tmpvalue)) {
8463 $value = $tmpvalue['label'];
8464 $disabled = empty($tmpvalue['disabled']) ? '' : ' disabled';
8465 $style = empty($tmpvalue['css']) ? '' : ' class="' . $tmpvalue['css'] . '"';
8466 } else {
8467 $value = $tmpvalue;
8468 $disabled = '';
8469 $style = '';
8470 }
8471 if (!empty($disablebademail)) {
8472 if (($disablebademail == 1 && !preg_match('/&lt;.+@.+&gt;/', $value))
8473 || ($disablebademail == 2 && preg_match('/---/', $value))) {
8474 $disabled = ' disabled';
8475 $style = ' class="warning"';
8476 }
8477 }
8478 if ($key_in_label) {
8479 if (empty($nohtmlescape)) {
8480 $selectOptionValue = dol_escape_htmltag($key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value));
8481 } else {
8482 $selectOptionValue = $key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value);
8483 }
8484 } else {
8485 if (empty($nohtmlescape)) {
8486 $selectOptionValue = dol_escape_htmltag($maxlen ? dol_trunc($value, $maxlen) : $value);
8487 } else {
8488 $selectOptionValue = $maxlen ? dol_trunc($value, $maxlen) : $value;
8489 }
8490 if ($value == '' || $value == '-') {
8491 $selectOptionValue = '&nbsp;';
8492 }
8493 }
8494 $out .= '<option value="' . $key . '"';
8495 $out .= $style . $disabled;
8496 if (is_array($id)) {
8497 if (in_array($key, $id) && !$disabled) {
8498 $out .= ' selected'; // To preselect a value
8499 }
8500 } else {
8501 $id = (string) $id; // if $id = 0, then $id = '0'
8502 if ($id != '' && ($id == $key || ($id == 'ifone' && count($array) == 1)) && !$disabled) {
8503 $out .= ' selected'; // To preselect a value
8504 }
8505 }
8506 if ($nohtmlescape) {
8507 $out .= ' data-html="' . dol_escape_htmltag($selectOptionValue) . '"';
8508 }
8509 if (is_array($tmpvalue)) {
8510 foreach ($tmpvalue as $keyforvalue => $valueforvalue) {
8511 if (preg_match('/^data-/', $keyforvalue)) {
8512 $out .= ' '.$keyforvalue.'="'.dol_escape_htmltag($valueforvalue).'"';
8513 }
8514 }
8515 }
8516 $out .= '>';
8517 $out .= $selectOptionValue;
8518 $out .= "</option>\n";
8519 }
8520 }
8521 $out .= "</select>";
8522 // Add code for jquery to use multiselect
8523 if ($addjscombo && $jsbeautify) {
8524 // Enhance with select2
8525 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8526 $out .= ajax_combobox($idname, array(), 0, 0, 'resolve', (((int) $show_empty) < 0 ? (string) $show_empty : '-1'), $morecss);
8527 }
8528
8529 return $out;
8530 }
8531
8550 public static function selectArrayAjax($htmlname, $url, $id = '', $moreparam = '', $moreparamtourl = '', $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0)
8551 {
8552 global $conf, $langs;
8553 global $delayedhtmlcontent; // Will be used later outside of this function
8554
8555 // TODO Use an internal dolibarr component instead of select2
8556 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8557 return '';
8558 }
8559
8560 $out = '<select type="text" class="' . $htmlname . ($morecss ? ' ' . $morecss : '') . '" ' . ($moreparam ? $moreparam . ' ' : '') . 'name="' . $htmlname . '"></select>';
8561
8562 $outdelayed = '';
8563 if (!empty($conf->use_javascript_ajax)) {
8564 $tmpplugin = 'select2';
8565 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8566 <script nonce="' . getNonce() . '">
8567 $(document).ready(function () {
8568
8569 ' . ($callurlonselect ? 'var saveRemoteData = [];' : '') . '
8570
8571 $(".' . $htmlname . '").select2({
8572 ajax: {
8573 dir: "ltr",
8574 url: "' . $url . '",
8575 dataType: \'json\',
8576 delay: 250,
8577 data: function (params) {
8578 return {
8579 q: params.term, // search term
8580 page: params.page
8581 }
8582 },
8583 processResults: function (data) {
8584 // parse the results into the format expected by Select2.
8585 // since we are using custom formatting functions we do not need to alter the remote JSON data
8586 //console.log(data);
8587 saveRemoteData = data;
8588 /* format json result for select2 */
8589 result = []
8590 $.each( data, function( key, value ) {
8591 result.push({id: key, text: value.text});
8592 });
8593 //return {results:[{id:\'none\', text:\'aa\'}, {id:\'rrr\', text:\'Red\'},{id:\'bbb\', text:\'Search a into projects\'}], more:false}
8594 //console.log(result);
8595 return {results: result, more: false}
8596 },
8597 cache: true
8598 },
8599 language: select2arrayoflanguage,
8600 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8601 placeholder: "' . dol_escape_js($placeholder) . '",
8602 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8603 minimumInputLength: ' . ((int) $minimumInputLength) . ',
8604 formatResult: function (result, container, query, escapeMarkup) {
8605 return escapeMarkup(result.text);
8606 },
8607 });
8608
8609 ' . ($callurlonselect ? '
8610 /* Code to execute a GET when we select a value */
8611 $(".' . $htmlname . '").change(function() {
8612 var selected = $(".' . $htmlname . '").val();
8613 console.log("We select in selectArrayAjax the entry "+selected)
8614 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8615 $.each( saveRemoteData, function( key, value ) {
8616 if (key == selected)
8617 {
8618 console.log("selectArrayAjax - Do a redirect to "+value.url)
8619 location.assign(value.url);
8620 }
8621 });
8622 });' : '') . '
8623
8624 });
8625 </script>';
8626 }
8627
8628 if ($acceptdelayedhtml) {
8629 $delayedhtmlcontent .= $outdelayed;
8630 } else {
8631 $out .= $outdelayed;
8632 }
8633 return $out;
8634 }
8635
8655 public static function selectArrayFilter($htmlname, $array, $id = '', $moreparam = '', $disableFiltering = 0, $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0, $textfortitle = '')
8656 {
8657 global $conf, $langs;
8658 global $delayedhtmlcontent; // Will be used later outside of this function
8659
8660 // TODO Use an internal dolibarr component instead of select2
8661 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8662 return '';
8663 }
8664
8665 $out = '<select type="text"'.($textfortitle ? ' title="'.dol_escape_htmltag($textfortitle).'"' : '').' id="'.$htmlname.'" class="'.$htmlname.($morecss ? ' ' . $morecss : '').'"'.($moreparam ? ' '.$moreparam : '').' name="'.$htmlname.'"><option></option></select>';
8666
8667 $formattedarrayresult = array();
8668
8669 foreach ($array as $key => $value) {
8670 $o = new stdClass();
8671 $o->id = $key;
8672 $o->text = $value['text'];
8673 $o->url = $value['url'];
8674 $formattedarrayresult[] = $o;
8675 }
8676
8677 $outdelayed = '';
8678 if (!empty($conf->use_javascript_ajax)) {
8679 $tmpplugin = 'select2';
8680 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8681 <script nonce="' . getNonce() . '">
8682 $(document).ready(function () {
8683 var data = ' . json_encode($formattedarrayresult) . ';
8684
8685 ' . ($callurlonselect ? 'var saveRemoteData = ' . json_encode($array) . ';' : '') . '
8686
8687 $(".' . $htmlname . '").select2({
8688 data: data,
8689 language: select2arrayoflanguage,
8690 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8691 placeholder: "' . dol_escape_js($placeholder) . '",
8692 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8693 minimumInputLength: ' . $minimumInputLength . ',
8694 formatResult: function (result, container, query, escapeMarkup) {
8695 return escapeMarkup(result.text);
8696 },
8697 matcher: function (params, data) {
8698
8699 if(! data.id) return null;';
8700
8701 if ($callurlonselect) {
8702 // We forge the url with 'sall='
8703 $outdelayed .= '
8704
8705 var urlBase = data.url;
8706 var separ = urlBase.indexOf("?") >= 0 ? "&" : "?";
8707 /* console.log("params.term="+params.term); */
8708 /* console.log("params.term encoded="+encodeURIComponent(params.term)); */
8709 saveRemoteData[data.id].url = urlBase + separ + "search_all=" + encodeURIComponent(params.term.replace(/\"/g, ""));';
8710 }
8711
8712 if (!$disableFiltering) {
8713 $outdelayed .= '
8714
8715 if(data.text.match(new RegExp(params.term))) {
8716 return data;
8717 }
8718
8719 return null;';
8720 } else {
8721 $outdelayed .= '
8722
8723 return data;';
8724 }
8725
8726 $outdelayed .= '
8727 }
8728 });
8729
8730 ' . ($callurlonselect ? '
8731 /* Code to execute a GET when we select a value */
8732 $(".' . $htmlname . '").change(function() {
8733 var selected = $(".' . $htmlname . '").val();
8734 console.log("We select "+selected)
8735
8736 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8737 $.each( saveRemoteData, function( key, value ) {
8738 if (key == selected)
8739 {
8740 console.log("selectArrayFilter - Do a redirect to "+value.url)
8741 location.assign(value.url);
8742 }
8743 });
8744 });' : '') . '
8745
8746 });
8747 </script>';
8748 }
8749
8750 if ($acceptdelayedhtml) {
8751 $delayedhtmlcontent .= $outdelayed;
8752 } else {
8753 $out .= $outdelayed;
8754 }
8755 return $out;
8756 }
8757
8776 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)
8777 {
8778 global $conf, $langs;
8779
8780 $out = '';
8781
8782 if ($addjscombo < 0) {
8783 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8784 $addjscombo = 1;
8785 } else {
8786 $addjscombo = 0;
8787 }
8788 }
8789
8790 $useenhancedmultiselect = 0;
8791 if (!empty($conf->use_javascript_ajax) && (getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT'))) {
8792 if ($addjscombo) {
8793 $useenhancedmultiselect = 1; // Use the js multiselect in one line. Possible only if $addjscombo not 0.
8794 }
8795 }
8796
8797 // We need a hidden field because when using the multiselect, if we unselect all, there is no
8798 // variable submitted at all, so no way to make a difference between variable not submited and variable
8799 // submited to nothing.
8800 $out .= '<input type="hidden" name="'.$htmlname.'_multiselect" value="1">';
8801 // Output select component
8802 $out .= '<select id="' . $htmlname . '" class="multiselect' . ($useenhancedmultiselect ? ' multiselectononeline' : '') . ($morecss ? ' ' . $morecss : '') . '" multiple name="' . $htmlname . '[]"' . ($moreattrib ? ' ' . $moreattrib : '') . ($width ? ' style="width: ' . (preg_match('/%/', $width) ? $width : $width . 'px') . '"' : '') . '>' . "\n";
8803 if (is_array($array) && !empty($array)) {
8804 if ($value_as_key) {
8805 $array = array_combine($array, $array);
8806 }
8807
8808 if (!empty($array)) {
8809 foreach ($array as $key => $value) {
8810 $tmpkey = $key;
8811 $tmpvalue = $value;
8812 $tmpcolor = '';
8813 $tmppicto = '';
8814 $tmplabelhtml = '';
8815 if (is_array($value) && array_key_exists('id', $value) && array_key_exists('label', $value)) {
8816 $tmpkey = $value['id'];
8817 $tmpvalue = empty($value['label']) ? '' : $value['label'];
8818 $tmpcolor = empty($value['color']) ? '' : $value['color'];
8819 $tmppicto = empty($value['picto']) ? '' : $value['picto'];
8820 $tmplabelhtml = empty($value['labelhtml']) ? '' : $value['labelhtml'];
8821 }
8822 $newval = ($translate ? $langs->trans($tmpvalue) : $tmpvalue);
8823 $newval = ($key_in_label ? $tmpkey . ' - ' . $newval : $newval);
8824
8825 $out .= '<option value="' . $tmpkey . '"';
8826 if (is_array($selected) && !empty($selected) && in_array((string) $tmpkey, $selected) && ((string) $tmpkey != '')) {
8827 $out .= ' selected';
8828 }
8829 if (!empty($tmplabelhtml)) {
8830 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
8831 } else {
8832 $tmplabelhtml = ($tmppicto ? img_picto('', $tmppicto, 'class="pictofixedwidth" style="color: #' . $tmpcolor . '"') : '') . $newval;
8833 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
8834 }
8835 $out .= '>';
8836 $out .= dol_htmlentitiesbr($newval);
8837 $out .= '</option>' . "\n";
8838 }
8839 }
8840 }
8841 $out .= '</select>' . "\n";
8842
8843 // Add code for jquery to use multiselect
8844 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT')) {
8845 $out .= "\n" . '<!-- JS CODE TO ENABLE select for id ' . $htmlname . ', addjscombo=' . $addjscombo . ' -->';
8846 $out .= "\n" . '<script nonce="' . getNonce() . '">' . "\n";
8847 if ($addjscombo == 1) {
8848 $tmpplugin = !getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT;
8849 $out .= 'function formatResult(record, container) {' . "\n";
8850 // If property html set, we decode html entities and use this.
8851 // Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, '', 0, 1) when building the select option.
8852 $out .= ' if ($(record.element).attr("data-html") != undefined) { return htmlEntityDecodeJs($(record.element).attr("data-html")); }'."\n";
8853 $out .= ' return record.text;';
8854 $out .= '}' . "\n";
8855 $out .= 'function formatSelection(record) {' . "\n";
8856 if ($elemtype == 'category') {
8857 $out .= 'return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';';
8858 } else {
8859 $out .= 'return record.text;';
8860 }
8861 $out .= '}' . "\n";
8862 $out .= '$(document).ready(function () {
8863 $(\'#' . $htmlname . '\').' . $tmpplugin . '({';
8864 if ($placeholder) {
8865 $out .= '
8866 placeholder: {
8867 id: \'-1\',
8868 text: \'' . dol_escape_js($placeholder) . '\'
8869 },';
8870 }
8871 $out .= ' dir: \'ltr\',
8872 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag (ko with multiselect) */
8873 dropdownCssClass: \'' . $morecss . '\', /* Line to add class on the new <span class="select2-selection...> tag (ok with multiselect) */
8874 // Specify format function for dropdown item
8875 formatResult: formatResult,
8876 templateResult: formatResult, /* For 4.0 */
8877 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8878 // Specify format function for selected item
8879 formatSelection: formatSelection,
8880 templateSelection: formatSelection /* For 4.0 */
8881 });
8882
8883 /* Add also morecss to the css .select2 that is after the #htmlname, for component that are show dynamically after load, because select2 set
8884 the size only if component is not hidden by default on load */
8885 $(\'#' . $htmlname . ' + .select2\').addClass(\'' . $morecss . '\');
8886 });' . "\n";
8887 } elseif ($addjscombo == 2 && !defined('DISABLE_MULTISELECT')) {
8888 // Add other js lib
8889 // TODO external lib multiselect/jquery.multi-select.js must have been loaded to use this multiselect plugin
8890 // ...
8891 $out .= 'console.log(\'addjscombo=2 for htmlname=' . $htmlname . '\');';
8892 $out .= '$(document).ready(function () {
8893 $(\'#' . $htmlname . '\').multiSelect({
8894 containerHTML: \'<div class="multi-select-container">\',
8895 menuHTML: \'<div class="multi-select-menu">\',
8896 buttonHTML: \'<span class="multi-select-button ' . $morecss . '">\',
8897 menuItemHTML: \'<label class="multi-select-menuitem">\',
8898 activeClass: \'multi-select-container--open\',
8899 noneText: \'' . $placeholder . '\'
8900 });
8901 })';
8902 }
8903 $out .= '</script>';
8904 }
8905
8906 return $out;
8907 }
8908
8909
8920 public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage, $pos = '')
8921 {
8922 global $conf, $langs, $user, $extrafields;
8923
8924 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8925 return '';
8926 }
8927 if (empty($array)) {
8928 return '';
8929 }
8930
8931 $tmpvar = "MAIN_SELECTEDFIELDS_" . $varpage; // To get list of saved selected fields to show
8932
8933 if (!empty($user->conf->$tmpvar)) { // A list of fields was already customized for user
8934 $tmparray = explode(',', $user->conf->$tmpvar);
8935 foreach ($array as $key => $val) {
8936 //var_dump($key);
8937 //var_dump($tmparray);
8938 if (in_array($key, $tmparray)) {
8939 $array[$key]['checked'] = 1;
8940 } else {
8941 $array[$key]['checked'] = 0;
8942 }
8943 }
8944 } else { // There is no list of fields already customized for user
8945 foreach ($array as $key => $val) {
8946 if (!empty($array[$key]['checked']) && $array[$key]['checked'] < 0) {
8947 $array[$key]['checked'] = 0;
8948 }
8949 }
8950 }
8951
8952 $listoffieldsforselection = '';
8953 $listcheckedstring = '';
8954
8955 foreach ($array as $key => $val) {
8956 // var_dump($val);
8957 // var_dump(array_key_exists('enabled', $val));
8958 // var_dump(!$val['enabled']);
8959 if (array_key_exists('enabled', $val) && isset($val['enabled']) && !$val['enabled']) {
8960 unset($array[$key]); // We don't want this field
8961 continue;
8962 }
8963 if (!empty($val['type']) && $val['type'] == 'separate') {
8964 // Field remains in array but we don't add it into $listoffieldsforselection
8965 //$listoffieldsforselection .= '<li>-----</li>';
8966 continue;
8967 }
8968 if ($val['label']) {
8969 if (!empty($val['langfile']) && is_object($langs)) {
8970 $langs->load($val['langfile']);
8971 }
8972
8973 // Note: $val['checked'] <> 0 means we must show the field into the combo list
8974 $listoffieldsforselection .= '<li><input type="checkbox" id="checkbox' . $key . '" value="' . $key . '"' . ((empty($val['checked']) || $val['checked'] == '-1') ? '' : ' checked="checked"') . '/><label for="checkbox' . $key . '">' . dol_escape_htmltag($langs->trans($val['label'])) . '</label></li>';
8975 $listcheckedstring .= (empty($val['checked']) ? '' : $key . ',');
8976 }
8977 }
8978
8979 $out = '<!-- Component multiSelectArrayWithCheckbox ' . $htmlname . ' -->
8980
8981 <dl class="dropdown">
8982 <dt>
8983 <a href="#' . $htmlname . '">
8984 ' . img_picto('', 'list') . '
8985 </a>
8986 <input type="hidden" class="' . $htmlname . '" name="' . $htmlname . '" value="' . $listcheckedstring . '">
8987 </dt>
8988 <dd class="dropdowndd">
8989 <div class="multiselectcheckbox'.$htmlname.'">
8990 <ul class="'.$htmlname.($pos == '1' ? 'left' : '').'">
8991 <li><input class="inputsearch_dropdownselectedfields width90p minwidth200imp" style="width:90%;" type="text" placeholder="'.$langs->trans('Search').'"></li>
8992 '.$listoffieldsforselection.'
8993 </ul>
8994 </div>
8995 </dd>
8996 </dl>
8997
8998 <script nonce="' . getNonce() . '" type="text/javascript">
8999 jQuery(document).ready(function () {
9000 $(\'.multiselectcheckbox' . $htmlname . ' input[type="checkbox"]\').on(\'click\', function () {
9001 console.log("A new field was added/removed, we edit field input[name=formfilteraction]");
9002
9003 $("input:hidden[name=formfilteraction]").val(\'listafterchangingselectedfields\'); // Update field so we know we changed something on selected fields after POST
9004
9005 var title = $(this).val() + ",";
9006 if ($(this).is(\':checked\')) {
9007 $(\'.' . $htmlname . '\').val(title + $(\'.' . $htmlname . '\').val());
9008 }
9009 else {
9010 $(\'.' . $htmlname . '\').val( $(\'.' . $htmlname . '\').val().replace(title, \'\') )
9011 }
9012 // Now, we submit page
9013 //$(this).parents(\'form:first\').submit();
9014 });
9015 $("input.inputsearch_dropdownselectedfields").on("keyup", function() {
9016 var value = $(this).val().toLowerCase();
9017 $(\'.multiselectcheckbox'.$htmlname.' li > label\').filter(function() {
9018 $(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
9019 });
9020 });
9021
9022
9023 });
9024 </script>
9025
9026 ';
9027 return $out;
9028 }
9029
9039 public function showCategories($id, $type, $rendermode = 0, $nolink = 0)
9040 {
9041 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
9042
9043 $cat = new Categorie($this->db);
9044 $categories = $cat->containing($id, $type);
9045
9046 if ($rendermode == 1) {
9047 $toprint = array();
9048 foreach ($categories as $c) {
9049 $ways = $c->print_all_ways(' &gt;&gt; ', ($nolink ? 'none' : ''), 0, 1); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formated text
9050 foreach ($ways as $way) {
9051 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . $way . '</li>';
9052 }
9053 }
9054 return '<div class="select2-container-multi-dolibarr"><ul class="select2-choices-dolibarr">' . implode(' ', $toprint) . '</ul></div>';
9055 }
9056
9057 if ($rendermode == 0) {
9058 $arrayselected = array();
9059 $cate_arbo = $this->select_all_categories($type, '', 'parent', 64, 0, 1);
9060 foreach ($categories as $c) {
9061 $arrayselected[] = $c->id;
9062 }
9063
9064 return $this->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, '', 0, '100%', 'disabled', 'category');
9065 }
9066
9067 return 'ErrorBadValueForParameterRenderMode'; // Should not happened
9068 }
9069
9079 public function showLinkedObjectBlock($object, $morehtmlright = '', $compatibleImportElementsList = array(), $title = 'RelatedObjects')
9080 {
9081 global $conf, $langs, $hookmanager;
9082 global $bc, $action;
9083
9084 $object->fetchObjectLinked();
9085
9086 // Bypass the default method
9087 $hookmanager->initHooks(array('commonobject'));
9088 $parameters = array(
9089 'morehtmlright' => $morehtmlright,
9090 'compatibleImportElementsList' => &$compatibleImportElementsList,
9091 );
9092 $reshook = $hookmanager->executeHooks('showLinkedObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9093
9094 $nbofdifferenttypes = count($object->linkedObjects);
9095
9096 if (empty($reshook)) {
9097 print '<!-- showLinkedObjectBlock -->';
9098 print load_fiche_titre($langs->trans($title), $morehtmlright, '', 0, 0, 'showlinkedobjectblock');
9099
9100
9101 print '<div class="div-table-responsive-no-min">';
9102 print '<table class="noborder allwidth" data-block="showLinkedObject" data-element="' . $object->element . '" data-elementid="' . $object->id . '" >';
9103
9104 print '<tr class="liste_titre">';
9105 print '<td>' . $langs->trans("Type") . '</td>';
9106 print '<td>' . $langs->trans("Ref") . '</td>';
9107 print '<td class="center"></td>';
9108 print '<td class="center">' . $langs->trans("Date") . '</td>';
9109 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9110 print '<td class="right">' . $langs->trans("Status") . '</td>';
9111 print '<td></td>';
9112 print '</tr>';
9113
9114 $nboftypesoutput = 0;
9115
9116 foreach ($object->linkedObjects as $objecttype => $objects) {
9117 $tplpath = $element = $subelement = $objecttype;
9118
9119 // to display inport button on tpl
9120 $showImportButton = false;
9121 if (!empty($compatibleImportElementsList) && in_array($element, $compatibleImportElementsList)) {
9122 $showImportButton = true;
9123 }
9124
9125 $regs = array();
9126 if ($objecttype != 'supplier_proposal' && preg_match('/^([^_]+)_([^_]+)/i', $objecttype, $regs)) {
9127 $element = $regs[1];
9128 $subelement = $regs[2];
9129 $tplpath = $element . '/' . $subelement;
9130 }
9131 $tplname = 'linkedobjectblock';
9132
9133 // To work with non standard path
9134 if ($objecttype == 'facture') {
9135 $tplpath = 'compta/' . $element;
9136 if (!isModEnabled('facture')) {
9137 continue; // Do not show if module disabled
9138 }
9139 } elseif ($objecttype == 'facturerec') {
9140 $tplpath = 'compta/facture';
9141 $tplname = 'linkedobjectblockForRec';
9142 if (!isModEnabled('facture')) {
9143 continue; // Do not show if module disabled
9144 }
9145 } elseif ($objecttype == 'propal') {
9146 $tplpath = 'comm/' . $element;
9147 if (!isModEnabled('propal')) {
9148 continue; // Do not show if module disabled
9149 }
9150 } elseif ($objecttype == 'supplier_proposal') {
9151 if (!isModEnabled('supplier_proposal')) {
9152 continue; // Do not show if module disabled
9153 }
9154 } elseif ($objecttype == 'shipping' || $objecttype == 'shipment' || $objecttype == 'expedition') {
9155 $tplpath = 'expedition';
9156 if (!isModEnabled('expedition')) {
9157 continue; // Do not show if module disabled
9158 }
9159 } elseif ($objecttype == 'reception') {
9160 $tplpath = 'reception';
9161 if (!isModEnabled('reception')) {
9162 continue; // Do not show if module disabled
9163 }
9164 } elseif ($objecttype == 'delivery') {
9165 $tplpath = 'delivery';
9166 if (!isModEnabled('expedition')) {
9167 continue; // Do not show if module disabled
9168 }
9169 } elseif ($objecttype == 'ficheinter') {
9170 $tplpath = 'fichinter';
9171 if (!isModEnabled('ficheinter')) {
9172 continue; // Do not show if module disabled
9173 }
9174 } elseif ($objecttype == 'invoice_supplier') {
9175 $tplpath = 'fourn/facture';
9176 } elseif ($objecttype == 'order_supplier') {
9177 $tplpath = 'fourn/commande';
9178 } elseif ($objecttype == 'expensereport') {
9179 $tplpath = 'expensereport';
9180 } elseif ($objecttype == 'subscription') {
9181 $tplpath = 'adherents';
9182 } elseif ($objecttype == 'conferenceorbooth') {
9183 $tplpath = 'eventorganization';
9184 } elseif ($objecttype == 'conferenceorboothattendee') {
9185 $tplpath = 'eventorganization';
9186 } elseif ($objecttype == 'mo') {
9187 $tplpath = 'mrp';
9188 if (!isModEnabled('mrp')) {
9189 continue; // Do not show if module disabled
9190 }
9191 }
9192
9193 global $linkedObjectBlock;
9194 $linkedObjectBlock = $objects;
9195
9196 // Output template part (modules that overwrite templates must declare this into descriptor)
9197 $dirtpls = array_merge($conf->modules_parts['tpl'], array('/' . $tplpath . '/tpl'));
9198 foreach ($dirtpls as $reldir) {
9199 if ($nboftypesoutput == ($nbofdifferenttypes - 1)) { // No more type to show after
9200 global $noMoreLinkedObjectBlockAfter;
9201 $noMoreLinkedObjectBlockAfter = 1;
9202 }
9203
9204 $res = @include dol_buildpath($reldir . '/' . $tplname . '.tpl.php');
9205 if ($res) {
9206 $nboftypesoutput++;
9207 break;
9208 }
9209 }
9210 }
9211
9212 if (!$nboftypesoutput) {
9213 print '<tr><td class="impair" colspan="7"><span class="opacitymedium">' . $langs->trans("None") . '</span></td></tr>';
9214 }
9215
9216 print '</table>';
9217
9218 if (!empty($compatibleImportElementsList)) {
9219 $res = @include dol_buildpath('core/tpl/objectlinked_lineimport.tpl.php');
9220 }
9221
9222 print '</div>';
9223 }
9224
9225 return $nbofdifferenttypes;
9226 }
9227
9236 public function showLinkToObjectBlock($object, $restrictlinksto = array(), $excludelinksto = array())
9237 {
9238 global $conf, $langs, $hookmanager;
9239 global $action;
9240
9241 $linktoelem = '';
9242 $linktoelemlist = '';
9243 $listofidcompanytoscan = '';
9244
9245 if (!is_object($object->thirdparty)) {
9246 $object->fetch_thirdparty();
9247 }
9248
9249 $possiblelinks = array();
9250 if (is_object($object->thirdparty) && !empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
9251 $listofidcompanytoscan = $object->thirdparty->id;
9252 if (($object->thirdparty->parent > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PARENT_IN_LINKTO')) {
9253 $listofidcompanytoscan .= ',' . $object->thirdparty->parent;
9254 }
9255 if (($object->fk_project > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PROJECT_THIRDPARY_IN_LINKTO')) {
9256 include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
9257 $tmpproject = new Project($this->db);
9258 $tmpproject->fetch($object->fk_project);
9259 if ($tmpproject->socid > 0 && ($tmpproject->socid != $object->thirdparty->id)) {
9260 $listofidcompanytoscan .= ',' . $tmpproject->socid;
9261 }
9262 unset($tmpproject);
9263 }
9264
9265 $possiblelinks = array(
9266 'propal' => array(
9267 'enabled' => isModEnabled('propal'),
9268 'perms' => 1,
9269 'label' => 'LinkToProposal',
9270 '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') . ')'),
9271 'shipping' => array(
9272 'enabled' => isModEnabled('expedition'),
9273 'perms' => 1,
9274 'label' => 'LinkToExpedition',
9275 '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') . ')'),
9276 'order' => array(
9277 'enabled' => isModEnabled('commande'),
9278 'perms' => 1,
9279 'label' => 'LinkToOrder',
9280 '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') . ')'),
9281 'invoice' => array(
9282 'enabled' => isModEnabled('facture'),
9283 'perms' => 1,
9284 'label' => 'LinkToInvoice',
9285 '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') . ')'),
9286 'invoice_template' => array(
9287 'enabled' => isModEnabled('facture'),
9288 'perms' => 1,
9289 'label' => 'LinkToTemplateInvoice',
9290 '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') . ')'),
9291 'contrat' => array(
9292 'enabled' => isModEnabled('contrat'),
9293 'perms' => 1,
9294 'label' => 'LinkToContract',
9295 '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
9296 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'
9297 ),
9298 'fichinter' => array(
9299 'enabled' => isModEnabled('ficheinter'),
9300 'perms' => 1,
9301 'label' => 'LinkToIntervention',
9302 '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') . ')'),
9303 'supplier_proposal' => array(
9304 'enabled' => isModEnabled('supplier_proposal'),
9305 'perms' => 1,
9306 'label' => 'LinkToSupplierProposal',
9307 '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') . ')'),
9308 'order_supplier' => array(
9309 'enabled' => isModEnabled("supplier_order"),
9310 'perms' => 1,
9311 'label' => 'LinkToSupplierOrder',
9312 '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') . ')'),
9313 'invoice_supplier' => array(
9314 'enabled' => isModEnabled("supplier_invoice"),
9315 'perms' => 1, 'label' => 'LinkToSupplierInvoice',
9316 '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') . ')'),
9317 'ticket' => array(
9318 'enabled' => isModEnabled('ticket'),
9319 'perms' => 1,
9320 'label' => 'LinkToTicket',
9321 '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') . ')'),
9322 'mo' => array(
9323 'enabled' => isModEnabled('mrp'),
9324 'perms' => 1,
9325 'label' => 'LinkToMo',
9326 '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') . ')')
9327 );
9328 }
9329
9330 if ($object->table_element == 'commande_fournisseur') {
9331 $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').')';
9332 } elseif ($object->table_element == 'mrp_mo') {
9333 $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').')';
9334 }
9335
9336 if (!empty($listofidcompanytoscan)) { // If empty, we don't have criteria to scan the object we can link to
9337 // Can complete the possiblelink array
9338 $hookmanager->initHooks(array('commonobject'));
9339 $parameters = array('listofidcompanytoscan' => $listofidcompanytoscan, 'possiblelinks' => $possiblelinks);
9340 $reshook = $hookmanager->executeHooks('showLinkToObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9341 }
9342
9343 if (empty($reshook)) {
9344 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9345 $possiblelinks = array_merge($possiblelinks, $hookmanager->resArray);
9346 }
9347 } elseif ($reshook > 0) {
9348 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9349 $possiblelinks = $hookmanager->resArray;
9350 }
9351 }
9352
9353 foreach ($possiblelinks as $key => $possiblelink) {
9354 $num = 0;
9355
9356 if (empty($possiblelink['enabled'])) {
9357 continue;
9358 }
9359
9360 if (!empty($possiblelink['perms']) && (empty($restrictlinksto) || in_array($key, $restrictlinksto)) && (empty($excludelinksto) || !in_array($key, $excludelinksto))) {
9361 print '<div id="' . $key . 'list"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display:none"') . '>';
9362
9363 if (getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9364 print '<br>'."\n";
9365 print '<!-- form to add a link from anywhere -->'."\n";
9366 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinkedbyref' . $key . '">';
9367 print '<input type="hidden" name="id" value="' . $object->id . '">';
9368 print '<input type="hidden" name="action" value="addlinkbyref">';
9369 print '<input type="hidden" name="token" value="' . newToken() . '">';
9370 print '<input type="hidden" name="addlink" value="' . $key . '">';
9371 print '<table class="noborder">';
9372 print '<tr>';
9373 //print '<td>' . $langs->trans("Ref") . '</td>';
9374 print '<td class="center"><input type="text" placeholder="'.dol_escape_htmltag($langs->trans("Ref")).'" name="reftolinkto" value="' . dol_escape_htmltag(GETPOST('reftolinkto', 'alpha')) . '">&nbsp;';
9375 print '<input type="submit" class="button small valignmiddle" value="' . $langs->trans('ToLink') . '">&nbsp;';
9376 print '<input type="submit" class="button small" name="cancel" value="' . $langs->trans('Cancel') . '"></td>';
9377 print '</tr>';
9378 print '</table>';
9379 print '</form>';
9380 }
9381
9382 $sql = $possiblelink['sql'];
9383
9384 $resqllist = $this->db->query($sql);
9385 if ($resqllist) {
9386 $num = $this->db->num_rows($resqllist);
9387 $i = 0;
9388
9389 print '<br>';
9390 print '<!-- form to add a link from object to same thirdparty -->'."\n";
9391 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinked' . $key . '">';
9392 print '<input type="hidden" name="action" value="addlink">';
9393 print '<input type="hidden" name="token" value="' . newToken() . '">';
9394 print '<input type="hidden" name="id" value="' . $object->id . '">';
9395 print '<input type="hidden" name="addlink" value="' . $key . '">';
9396 print '<table class="noborder">';
9397 print '<tr class="liste_titre">';
9398 print '<td class="nowrap"></td>';
9399 print '<td class="center">' . $langs->trans("Ref") . '</td>';
9400 print '<td class="left">' . $langs->trans("RefCustomer") . '</td>';
9401 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9402 print '<td class="left">' . $langs->trans("Company") . '</td>';
9403 print '</tr>';
9404 while ($i < $num) {
9405 $objp = $this->db->fetch_object($resqllist);
9406
9407 print '<tr class="oddeven">';
9408 print '<td class="left">';
9409 print '<input type="radio" name="idtolinkto" id="' . $key . '_' . $objp->rowid . '" value="' . $objp->rowid . '">';
9410 print '</td>';
9411 print '<td class="center"><label for="' . $key . '_' . $objp->rowid . '">' . $objp->ref . '</label></td>';
9412 print '<td>' . (!empty($objp->ref_client) ? $objp->ref_client : (!empty($objp->ref_supplier) ? $objp->ref_supplier : '')) . '</td>';
9413 print '<td class="right">';
9414 if ($possiblelink['label'] == 'LinkToContract') {
9415 $form = new Form($this->db);
9416 print $form->textwithpicto('', $langs->trans("InformationOnLinkToContract")) . ' ';
9417 }
9418 print '<span class="amount">' . (isset($objp->total_ht) ? price($objp->total_ht) : '') . '</span>';
9419 print '</td>';
9420 print '<td>' . $objp->name . '</td>';
9421 print '</tr>';
9422 $i++;
9423 }
9424 print '</table>';
9425 print '<div class="center">';
9426 if ($num) {
9427 print '<input type="submit" class="button valignmiddle marginleftonly marginrightonly small" value="' . $langs->trans('ToLink') . '">';
9428 }
9429 if (empty($conf->use_javascript_ajax)) {
9430 print '<input type="submit" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9431 } else {
9432 print '<input type="submit" onclick="jQuery(\'#' . $key . 'list\').toggle(); return false;" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9433 }
9434 print '</form>';
9435 $this->db->free($resqllist);
9436 } else {
9437 dol_print_error($this->db);
9438 }
9439 print '</div>';
9440
9441 //$linktoelem.=($linktoelem?' &nbsp; ':'');
9442 if ($num > 0 || getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9443 $linktoelemlist .= '<li><a href="#linkto' . $key . '" class="linkto dropdowncloseonclick" rel="' . $key . '">' . $langs->trans($possiblelink['label']) . ' (' . $num . ')</a></li>';
9444 // } else $linktoelem.=$langs->trans($possiblelink['label']);
9445 } else {
9446 $linktoelemlist .= '<li><span class="linktodisabled">' . $langs->trans($possiblelink['label']) . ' (0)</span></li>';
9447 }
9448 }
9449 }
9450
9451 if ($linktoelemlist) {
9452 $linktoelem = '
9453 <dl class="dropdown" id="linktoobjectname">
9454 ';
9455 if (!empty($conf->use_javascript_ajax)) {
9456 $linktoelem .= '<dt><a href="#linktoobjectname"><span class="fas fa-link paddingrightonly"></span>' . $langs->trans("LinkTo") . '...</a></dt>';
9457 }
9458 $linktoelem .= '<dd>
9459 <div class="multiselectlinkto">
9460 <ul class="ulselectedfields">' . $linktoelemlist . '
9461 </ul>
9462 </div>
9463 </dd>
9464 </dl>';
9465 } else {
9466 $linktoelem = '';
9467 }
9468
9469 if (!empty($conf->use_javascript_ajax)) {
9470 print '<!-- Add js to show linkto box -->
9471 <script nonce="' . getNonce() . '">
9472 jQuery(document).ready(function() {
9473 jQuery(".linkto").click(function() {
9474 console.log("We choose to show/hide links for rel="+jQuery(this).attr(\'rel\')+" so #"+jQuery(this).attr(\'rel\')+"list");
9475 jQuery("#"+jQuery(this).attr(\'rel\')+"list").toggle();
9476 });
9477 });
9478 </script>
9479 ';
9480 }
9481
9482 return $linktoelem;
9483 }
9484
9499 public function selectyesno($htmlname, $value = '', $option = 0, $disabled = false, $useempty = 0, $addjscombo = 0, $morecss = '', $labelyes = 'Yes', $labelno = 'No')
9500 {
9501 global $langs;
9502
9503 $yes = "yes";
9504 $no = "no";
9505 if ($option) {
9506 $yes = "1";
9507 $no = "0";
9508 }
9509
9510 $disabled = ($disabled ? ' disabled' : '');
9511
9512 $resultyesno = '<select class="flat width75' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '"' . $disabled . '>' . "\n";
9513 if ($useempty) {
9514 $resultyesno .= '<option value="-1"' . (($value < 0) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
9515 }
9516 if (("$value" == 'yes') || ($value == 1)) {
9517 $resultyesno .= '<option value="' . $yes . '" selected>' . $langs->trans($labelyes) . '</option>' . "\n";
9518 $resultyesno .= '<option value="' . $no . '">' . $langs->trans($labelno) . '</option>' . "\n";
9519 } else {
9520 $selected = (($useempty && $value != '0' && $value != 'no') ? '' : ' selected');
9521 $resultyesno .= '<option value="' . $yes . '">' . $langs->trans($labelyes) . '</option>' . "\n";
9522 $resultyesno .= '<option value="' . $no . '"' . $selected . '>' . $langs->trans($labelno) . '</option>' . "\n";
9523 }
9524 $resultyesno .= '</select>' . "\n";
9525
9526 if ($addjscombo) {
9527 $resultyesno .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($useempty < 0 ? (string) $useempty : '-1'), $morecss);
9528 }
9529
9530 return $resultyesno;
9531 }
9532
9533 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
9534
9544 public function select_export_model($selected = '', $htmlname = 'exportmodelid', $type = '', $useempty = 0)
9545 {
9546 // phpcs:enable
9547 $sql = "SELECT rowid, label";
9548 $sql .= " FROM " . $this->db->prefix() . "export_model";
9549 $sql .= " WHERE type = '" . $this->db->escape($type) . "'";
9550 $sql .= " ORDER BY rowid";
9551 $result = $this->db->query($sql);
9552 if ($result) {
9553 print '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
9554 if ($useempty) {
9555 print '<option value="-1">&nbsp;</option>';
9556 }
9557
9558 $num = $this->db->num_rows($result);
9559 $i = 0;
9560 while ($i < $num) {
9561 $obj = $this->db->fetch_object($result);
9562 if ($selected == $obj->rowid) {
9563 print '<option value="' . $obj->rowid . '" selected>';
9564 } else {
9565 print '<option value="' . $obj->rowid . '">';
9566 }
9567 print $obj->label;
9568 print '</option>';
9569 $i++;
9570 }
9571 print "</select>";
9572 } else {
9573 dol_print_error($this->db);
9574 }
9575 }
9576
9595 public function showrefnav($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $morehtmlright = '')
9596 {
9597 global $conf, $langs, $hookmanager, $extralanguages;
9598
9599 $ret = '';
9600 if (empty($fieldid)) {
9601 $fieldid = 'rowid';
9602 }
9603 if (empty($fieldref)) {
9604 $fieldref = 'ref';
9605 }
9606
9607 // Preparing gender's display if there is one
9608 $addgendertxt = '';
9609 if (property_exists($object, 'gender') && !empty($object->gender)) {
9610 $addgendertxt = ' ';
9611 switch ($object->gender) {
9612 case 'man':
9613 $addgendertxt .= '<i class="fas fa-mars"></i>';
9614 break;
9615 case 'woman':
9616 $addgendertxt .= '<i class="fas fa-venus"></i>';
9617 break;
9618 case 'other':
9619 $addgendertxt .= '<i class="fas fa-transgender"></i>';
9620 break;
9621 }
9622 }
9623
9624 // Add where from hooks
9625 if (is_object($hookmanager)) {
9626 $parameters = array('showrefnav' => true);
9627 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
9628 $object->next_prev_filter .= $hookmanager->resPrint;
9629 }
9630 $previous_ref = $next_ref = '';
9631 if ($shownav) {
9632 //print "paramid=$paramid,morehtml=$morehtml,shownav=$shownav,$fieldid,$fieldref,$morehtmlref,$moreparam";
9633 $object->load_previous_next_ref((isset($object->next_prev_filter) ? $object->next_prev_filter : ''), $fieldid, $nodbprefix);
9634
9635 $navurl = $_SERVER["PHP_SELF"];
9636 // Special case for project/task page
9637 if ($paramid == 'project_ref') {
9638 if (preg_match('/\/tasks\/(task|contact|note|document)\.php/', $navurl)) { // TODO Remove this when nav with project_ref on task pages are ok
9639 $navurl = preg_replace('/\/tasks\/(task|contact|time|note|document)\.php/', '/tasks.php', $navurl);
9640 $paramid = 'ref';
9641 }
9642 }
9643
9644 // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox
9645 // accesskey is for Mac: CTRL + key for all browsers
9646 $stringforfirstkey = $langs->trans("KeyboardShortcut");
9647 if ($conf->browser->name == 'chrome') {
9648 $stringforfirstkey .= ' ALT +';
9649 } elseif ($conf->browser->name == 'firefox') {
9650 $stringforfirstkey .= ' ALT + SHIFT +';
9651 } else {
9652 $stringforfirstkey .= ' CTL +';
9653 }
9654
9655 $previous_ref = $object->ref_previous ? '<a accesskey="p" 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>';
9656 $next_ref = $object->ref_next ? '<a accesskey="n" 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>';
9657 }
9658
9659 //print "xx".$previous_ref."x".$next_ref;
9660 $ret .= '<!-- Start banner content --><div style="vertical-align: middle">';
9661
9662 // Right part of banner
9663 if ($morehtmlright) {
9664 $ret .= '<div class="inline-block floatleft">' . $morehtmlright . '</div>';
9665 }
9666
9667 if ($previous_ref || $next_ref || $morehtml) {
9668 $ret .= '<div class="pagination paginationref"><ul class="right">';
9669 }
9670 if ($morehtml) {
9671 $ret .= '<li class="noborder litext' . (($shownav && $previous_ref && $next_ref) ? ' clearbothonsmartphone' : '') . '">' . $morehtml . '</li>';
9672 }
9673 if ($shownav && ($previous_ref || $next_ref)) {
9674 $ret .= '<li class="pagination">' . $previous_ref . '</li>';
9675 $ret .= '<li class="pagination">' . $next_ref . '</li>';
9676 }
9677 if ($previous_ref || $next_ref || $morehtml) {
9678 $ret .= '</ul></div>';
9679 }
9680
9681 // Status
9682 $parameters = array('morehtmlstatus' => $morehtmlstatus);
9683 $reshook = $hookmanager->executeHooks('moreHtmlStatus', $parameters, $object); // Note that $action and $object may have been modified by hook
9684 if (empty($reshook)) {
9685 $morehtmlstatus .= $hookmanager->resPrint;
9686 } else {
9687 $morehtmlstatus = $hookmanager->resPrint;
9688 }
9689 if ($morehtmlstatus) {
9690 $ret .= '<div class="statusref">' . $morehtmlstatus . '</div>';
9691 }
9692
9693 $parameters = array();
9694 $reshook = $hookmanager->executeHooks('moreHtmlRef', $parameters, $object); // Note that $action and $object may have been modified by hook
9695 if (empty($reshook)) {
9696 $morehtmlref .= $hookmanager->resPrint;
9697 } elseif ($reshook > 0) {
9698 $morehtmlref = $hookmanager->resPrint;
9699 }
9700
9701 // Left part of banner
9702 if ($morehtmlleft) {
9703 if ($conf->browser->layout == 'phone') {
9704 $ret .= '<!-- morehtmlleft --><div class="floatleft">' . $morehtmlleft . '</div>';
9705 } else {
9706 $ret .= '<!-- morehtmlleft --><div class="inline-block floatleft">' . $morehtmlleft . '</div>';
9707 }
9708 }
9709
9710 //if ($conf->browser->layout == 'phone') $ret.='<div class="clearboth"></div>';
9711 $ret .= '<div class="inline-block floatleft valignmiddle maxwidth750 marginbottomonly refid' . (($shownav && ($previous_ref || $next_ref)) ? ' refidpadding' : '') . '">';
9712
9713 // For thirdparty, contact, user, member, the ref is the id, so we show something else
9714 if ($object->element == 'societe') {
9715 $ret .= dol_htmlentities($object->name);
9716
9717 // List of extra languages
9718 $arrayoflangcode = array();
9719 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
9720 $arrayoflangcode[] = $conf->global->PDF_USE_ALSO_LANGUAGE_CODE;
9721 }
9722
9723 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
9724 if (!is_object($extralanguages)) {
9725 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
9726 $extralanguages = new ExtraLanguages($this->db);
9727 }
9728 $extralanguages->fetch_name_extralanguages('societe');
9729
9730 if (!empty($extralanguages->attributes['societe']['name'])) {
9731 $object->fetchValuesForExtraLanguages();
9732
9733 $htmltext = '';
9734 // If there is extra languages
9735 foreach ($arrayoflangcode as $extralangcode) {
9736 $htmltext .= picto_from_langcode($extralangcode, 'class="pictoforlang paddingright"');
9737 if ($object->array_languages['name'][$extralangcode]) {
9738 $htmltext .= $object->array_languages['name'][$extralangcode];
9739 } else {
9740 $htmltext .= '<span class="opacitymedium">' . $langs->trans("SwitchInEditModeToAddTranslation") . '</span>';
9741 }
9742 }
9743 $ret .= '<!-- Show translations of name -->' . "\n";
9744 $ret .= $this->textwithpicto('', $htmltext, -1, 'language', 'opacitymedium paddingleft');
9745 }
9746 }
9747 } elseif ($object->element == 'member') {
9748 $ret .= $object->ref . '<br>';
9749 $fullname = $object->getFullName($langs);
9750 if ($object->morphy == 'mor' && $object->societe) {
9751 $ret .= dol_htmlentities($object->societe) . ((!empty($fullname) && $object->societe != $fullname) ? ' (' . dol_htmlentities($fullname) . $addgendertxt . ')' : '');
9752 } else {
9753 $ret .= dol_htmlentities($fullname) . $addgendertxt . ((!empty($object->societe) && $object->societe != $fullname) ? ' (' . dol_htmlentities($object->societe) . ')' : '');
9754 }
9755 } elseif (in_array($object->element, array('contact', 'user'))) {
9756 $ret .= dol_htmlentities($object->getFullName($langs)) . $addgendertxt;
9757 } elseif ($object->element == 'usergroup') {
9758 $ret .= dol_htmlentities($object->name);
9759 } elseif (in_array($object->element, array('action', 'agenda'))) {
9760 $ret .= $object->ref . '<br>' . $object->label;
9761 } elseif (in_array($object->element, array('adherent_type'))) {
9762 $ret .= $object->label;
9763 } elseif ($object->element == 'ecm_directories') {
9764 $ret .= '';
9765 } elseif ($fieldref != 'none') {
9766 $ret .= dol_htmlentities(!empty($object->$fieldref) ? $object->$fieldref : "");
9767 }
9768 if ($morehtmlref) {
9769 // don't add a additional space, when "$morehtmlref" starts with a HTML div tag
9770 if (substr($morehtmlref, 0, 4) != '<div') {
9771 $ret .= ' ';
9772 }
9773
9774 $ret .= $morehtmlref;
9775 }
9776
9777 $ret .= '</div>';
9778
9779 $ret .= '</div><!-- End banner content -->';
9780
9781 return $ret;
9782 }
9783
9784
9793 public function showbarcode(&$object, $width = 100, $morecss = '')
9794 {
9795 global $conf;
9796
9797 //Check if barcode is filled in the card
9798 if (empty($object->barcode)) {
9799 return '';
9800 }
9801
9802 // Complete object if not complete
9803 if (empty($object->barcode_type_code) || empty($object->barcode_type_coder)) {
9804 $result = $object->fetch_barcode();
9805 //Check if fetch_barcode() failed
9806 if ($result < 1) {
9807 return '<!-- ErrorFetchBarcode -->';
9808 }
9809 }
9810
9811 // Barcode image
9812 $url = DOL_URL_ROOT . '/viewimage.php?modulepart=barcode&generator=' . urlencode($object->barcode_type_coder) . '&code=' . urlencode($object->barcode) . '&encoding=' . urlencode($object->barcode_type_code);
9813 $out = '<!-- url barcode = ' . $url . ' -->';
9814 $out .= '<img src="' . $url . '"' . ($morecss ? ' class="' . $morecss . '"' : '') . '>';
9815
9816 return $out;
9817 }
9818
9835 public static function showphoto($modulepart, $object, $width = 100, $height = 0, $caneditfield = 0, $cssclass = 'photowithmargin', $imagesize = '', $addlinktofullsize = 1, $cache = 0, $forcecapture = '', $noexternsourceoverwrite = 0)
9836 {
9837 global $conf, $langs;
9838
9839 $entity = (empty($object->entity) ? $conf->entity : $object->entity);
9840 $id = (empty($object->id) ? $object->rowid : $object->id);
9841
9842 $ret = '';
9843 $dir = '';
9844 $file = '';
9845 $originalfile = '';
9846 $altfile = '';
9847 $email = '';
9848 $capture = '';
9849 if ($modulepart == 'societe') {
9850 $dir = $conf->societe->multidir_output[$entity];
9851 if (!empty($object->logo)) {
9852 if (dolIsAllowedForPreview($object->logo)) {
9853 if ((string) $imagesize == 'mini') {
9854 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_mini'); // getImageFileNameForSize include the thumbs
9855 } elseif ((string) $imagesize == 'small') {
9856 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_small');
9857 } else {
9858 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
9859 }
9860 $originalfile = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
9861 }
9862 }
9863 $email = $object->email;
9864 } elseif ($modulepart == 'contact') {
9865 $dir = $conf->societe->multidir_output[$entity] . '/contact';
9866 if (!empty($object->photo)) {
9867 if (dolIsAllowedForPreview($object->photo)) {
9868 if ((string) $imagesize == 'mini') {
9869 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
9870 } elseif ((string) $imagesize == 'small') {
9871 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
9872 } else {
9873 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
9874 }
9875 $originalfile = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
9876 }
9877 }
9878 $email = $object->email;
9879 $capture = 'user';
9880 } elseif ($modulepart == 'userphoto') {
9881 $dir = $conf->user->dir_output;
9882 if (!empty($object->photo)) {
9883 if (dolIsAllowedForPreview($object->photo)) {
9884 if ((string) $imagesize == 'mini') {
9885 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
9886 } elseif ((string) $imagesize == 'small') {
9887 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
9888 } else {
9889 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
9890 }
9891 $originalfile = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
9892 }
9893 }
9894 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
9895 $altfile = $object->id . ".jpg"; // For backward compatibility
9896 }
9897 $email = $object->email;
9898 $capture = 'user';
9899 } elseif ($modulepart == 'memberphoto') {
9900 $dir = $conf->adherent->dir_output;
9901 if (!empty($object->photo)) {
9902 if (dolIsAllowedForPreview($object->photo)) {
9903 if ((string) $imagesize == 'mini') {
9904 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
9905 } elseif ((string) $imagesize == 'small') {
9906 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
9907 } else {
9908 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
9909 }
9910 $originalfile = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
9911 }
9912 }
9913 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
9914 $altfile = $object->id . ".jpg"; // For backward compatibility
9915 }
9916 $email = $object->email;
9917 $capture = 'user';
9918 } else {
9919 // Generic case to show photos
9920 $dir = $conf->$modulepart->dir_output;
9921 if (!empty($object->photo)) {
9922 if (dolIsAllowedForPreview($object->photo)) {
9923 if ((string) $imagesize == 'mini') {
9924 $file = get_exdir($id, 2, 0, 0, $object, $modulepart) . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
9925 } elseif ((string) $imagesize == 'small') {
9926 $file = get_exdir($id, 2, 0, 0, $object, $modulepart) . 'photos/' . getImageFileNameForSize($object->photo, '_small');
9927 } else {
9928 $file = get_exdir($id, 2, 0, 0, $object, $modulepart) . 'photos/' . $object->photo;
9929 }
9930 $originalfile = get_exdir($id, 2, 0, 0, $object, $modulepart) . 'photos/' . $object->photo;
9931 }
9932 }
9933 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
9934 $altfile = $object->id . ".jpg"; // For backward compatibility
9935 }
9936 $email = $object->email;
9937 }
9938
9939 if ($forcecapture) {
9940 $capture = $forcecapture;
9941 }
9942
9943 if ($dir) {
9944 if ($file && file_exists($dir . "/" . $file)) {
9945 if ($addlinktofullsize) {
9946 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
9947 if ($urladvanced) {
9948 $ret .= '<a href="' . $urladvanced . '">';
9949 } else {
9950 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
9951 }
9952 }
9953 $ret .= '<img alt="Photo" 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 . '">';
9954 if ($addlinktofullsize) {
9955 $ret .= '</a>';
9956 }
9957 } elseif ($altfile && file_exists($dir . "/" . $altfile)) {
9958 if ($addlinktofullsize) {
9959 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
9960 if ($urladvanced) {
9961 $ret .= '<a href="' . $urladvanced . '">';
9962 } else {
9963 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
9964 }
9965 }
9966 $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 . '">';
9967 if ($addlinktofullsize) {
9968 $ret .= '</a>';
9969 }
9970 } else {
9971 $nophoto = '/public/theme/common/nophoto.png';
9972 $defaultimg = 'identicon'; // For gravatar
9973 if (in_array($modulepart, array('societe', 'userphoto', 'contact', 'memberphoto'))) { // For modules that need a special image when photo not found
9974 if ($modulepart == 'societe' || ($modulepart == 'memberphoto' && !empty($object->morphy) && strpos($object->morphy, 'mor')) !== false) {
9975 $nophoto = 'company';
9976 } else {
9977 $nophoto = '/public/theme/common/user_anonymous.png';
9978 if (!empty($object->gender) && $object->gender == 'man') {
9979 $nophoto = '/public/theme/common/user_man.png';
9980 }
9981 if (!empty($object->gender) && $object->gender == 'woman') {
9982 $nophoto = '/public/theme/common/user_woman.png';
9983 }
9984 }
9985 }
9986
9987 if (isModEnabled('gravatar') && $email && empty($noexternsourceoverwrite)) {
9988 // see https://gravatar.com/site/implement/images/php/
9989 $ret .= '<!-- Put link to gravatar -->';
9990 $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
9991 } else {
9992 if ($nophoto == 'company') {
9993 $ret .= '<div class="divforspanimg photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . '>' . img_picto('', 'company') . '</div>';
9994 $ret .= '<div class="difforspanimgright"></div>';
9995 } else {
9996 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . $nophoto . '">';
9997 }
9998 }
9999 }
10000
10001 if ($caneditfield) {
10002 if ($object->photo) {
10003 $ret .= "<br>\n";
10004 }
10005 $ret .= '<table class="nobordernopadding centpercent">';
10006 if ($object->photo) {
10007 $ret .= '<tr><td><input type="checkbox" class="flat photodelete" name="deletephoto" id="photodelete"> <label for="photodelete">' . $langs->trans("Delete") . '</label><br><br></td></tr>';
10008 }
10009 $ret .= '<tr><td class="tdoverflow">';
10010 $maxfilesizearray = getMaxFileSizeArray();
10011 $maxmin = $maxfilesizearray['maxmin'];
10012 if ($maxmin > 0) {
10013 $ret .= '<input type="hidden" name="MAX_FILE_SIZE" value="' . ($maxmin * 1024) . '">'; // MAX_FILE_SIZE must precede the field type=file
10014 }
10015 $ret .= '<input type="file" class="flat maxwidth200onsmartphone" name="photo" id="photoinput" accept="image/*"' . ($capture ? ' capture="' . $capture . '"' : '') . '>';
10016 $ret .= '</td></tr>';
10017 $ret .= '</table>';
10018 }
10019 }
10020
10021 return $ret;
10022 }
10023
10024 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
10025
10042 public function select_dolgroups($selected = '', $htmlname = 'groupid', $show_empty = 0, $exclude = '', $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0', $multiple = false, $morecss = '')
10043 {
10044 // phpcs:enable
10045 global $conf, $user, $langs;
10046
10047 // Permettre l'exclusion de groupes
10048 $excludeGroups = null;
10049 if (is_array($exclude)) {
10050 $excludeGroups = implode(",", $exclude);
10051 }
10052 // Permettre l'inclusion de groupes
10053 $includeGroups = null;
10054 if (is_array($include)) {
10055 $includeGroups = implode(",", $include);
10056 }
10057
10058 if (!is_array($selected)) {
10059 $selected = array($selected);
10060 }
10061
10062 $out = '';
10063
10064 // On recherche les groupes
10065 $sql = "SELECT ug.rowid, ug.nom as name";
10066 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10067 $sql .= ", e.label";
10068 }
10069 $sql .= " FROM " . $this->db->prefix() . "usergroup as ug ";
10070 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10071 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid=ug.entity";
10072 if ($force_entity) {
10073 $sql .= " WHERE ug.entity IN (0, " . $force_entity . ")";
10074 } else {
10075 $sql .= " WHERE ug.entity IS NOT NULL";
10076 }
10077 } else {
10078 $sql .= " WHERE ug.entity IN (0, " . $conf->entity . ")";
10079 }
10080 if (is_array($exclude) && $excludeGroups) {
10081 $sql .= " AND ug.rowid NOT IN (" . $this->db->sanitize($excludeGroups) . ")";
10082 }
10083 if (is_array($include) && $includeGroups) {
10084 $sql .= " AND ug.rowid IN (" . $this->db->sanitize($includeGroups) . ")";
10085 }
10086 $sql .= " ORDER BY ug.nom ASC";
10087
10088 dol_syslog(get_class($this) . "::select_dolgroups", LOG_DEBUG);
10089 $resql = $this->db->query($sql);
10090 if ($resql) {
10091 // Enhance with select2
10092 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10093
10094 $out .= '<select class="flat minwidth200' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
10095
10096 $num = $this->db->num_rows($resql);
10097 $i = 0;
10098 if ($num) {
10099 if ($show_empty && !$multiple) {
10100 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
10101 }
10102
10103 while ($i < $num) {
10104 $obj = $this->db->fetch_object($resql);
10105 $disableline = 0;
10106 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
10107 $disableline = 1;
10108 }
10109
10110 $label = $obj->name;
10111 $labelhtml = $obj->name;
10112 if (isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1) {
10113 $label .= " (" . $obj->label . ")";
10114 $labelhtml .= ' <span class="opacitymedium">(' . $obj->label . ')</span>';
10115 }
10116
10117 $out .= '<option value="' . $obj->rowid . '"';
10118 if ($disableline) {
10119 $out .= ' disabled';
10120 }
10121 if ((isset($selected[0]) && is_object($selected[0]) && $selected[0]->id == $obj->rowid) || ((!isset($selected[0]) || !is_object($selected[0])) && !empty($selected) && in_array($obj->rowid, $selected))) {
10122 $out .= ' selected';
10123 }
10124 $out .= ' data-html="'.dol_escape_htmltag($labelhtml).'"';
10125 $out .= '>';
10126 $out .= $label;
10127 $out .= '</option>';
10128 $i++;
10129 }
10130 } else {
10131 if ($show_empty) {
10132 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '></option>' . "\n";
10133 }
10134 $out .= '<option value="" disabled>' . $langs->trans("NoUserGroupDefined") . '</option>';
10135 }
10136 $out .= '</select>';
10137
10138 $out .= ajax_combobox($htmlname);
10139 } else {
10140 dol_print_error($this->db);
10141 }
10142
10143 return $out;
10144 }
10145
10146
10153 public function showFilterButtons($pos = '')
10154 {
10155 $out = '<div class="nowraponall">';
10156 if ($pos == 'left') {
10157 $out .= '<button type="submit" class="liste_titre button_search reposition" name="button_search_x" value="x"><span class="fas fa-search"></span></button>';
10158 $out .= '<button type="submit" class="liste_titre button_removefilter reposition" name="button_removefilter_x" value="x"><span class="fas fa-times"></span></button>';
10159 } else {
10160 $out .= '<button type="submit" class="liste_titre button_search reposition" name="button_search_x" value="x"><span class="fas fa-search"></span></button>';
10161 $out .= '<button type="submit" class="liste_titre button_removefilter reposition" name="button_removefilter_x" value="x"><span class="fas fa-times"></span></button>';
10162 }
10163 $out .= '</div>';
10164
10165 return $out;
10166 }
10167
10176 public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10177 {
10178 global $conf;
10179
10180 $out = '';
10181
10182 if (!empty($conf->use_javascript_ajax)) {
10183 $out .= '<div class="inline-block checkallactions"><input type="checkbox" id="' . $cssclass . 's" name="' . $cssclass . 's" class="checkallactions"></div>';
10184 }
10185 $out .= '<script nonce="' . getNonce() . '">
10186 $(document).ready(function() {
10187 $("#' . $cssclass . 's").click(function() {
10188 if($(this).is(\':checked\')){
10189 console.log("We check all ' . $cssclass . ' and trigger the change method");
10190 $(".' . $cssclass . '").prop(\'checked\', true).trigger(\'change\');
10191 }
10192 else
10193 {
10194 console.log("We uncheck all");
10195 $(".' . $cssclass . '").prop(\'checked\', false).trigger(\'change\');
10196 }' . "\n";
10197 if ($calljsfunction) {
10198 $out .= 'if (typeof initCheckForSelect == \'function\') { initCheckForSelect(0, "' . $massactionname . '", "' . $cssclass . '"); } else { console.log("No function initCheckForSelect found. Call won\'t be done."); }';
10199 }
10200 $out .= ' });
10201 $(".' . $cssclass . '").change(function() {
10202 $(this).closest("tr").toggleClass("highlight", this.checked);
10203 });
10204 });
10205 </script>';
10206
10207 return $out;
10208 }
10209
10219 public function showFilterAndCheckAddButtons($addcheckuncheckall = 0, $cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10220 {
10221 $out = $this->showFilterButtons();
10222 if ($addcheckuncheckall) {
10223 $out .= $this->showCheckAddButtons($cssclass, $calljsfunction, $massactionname);
10224 }
10225 return $out;
10226 }
10227
10241 public function selectExpenseCategories($selected = '', $htmlname = 'fk_c_exp_tax_cat', $useempty = 0, $excludeid = array(), $target = '', $default_selected = 0, $params = array(), $info_admin = 1)
10242 {
10243 global $langs, $user;
10244
10245 $out = '';
10246 $sql = "SELECT rowid, label FROM " . $this->db->prefix() . "c_exp_tax_cat WHERE active = 1";
10247 $sql .= " AND entity IN (0," . getEntity('exp_tax_cat') . ")";
10248 if (!empty($excludeid)) {
10249 $sql .= " AND rowid NOT IN (" . $this->db->sanitize(implode(',', $excludeid)) . ")";
10250 }
10251 $sql .= " ORDER BY label";
10252
10253 $resql = $this->db->query($sql);
10254 if ($resql) {
10255 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp maxwidth200">';
10256 if ($useempty) {
10257 $out .= '<option value="0">&nbsp;</option>';
10258 }
10259
10260 while ($obj = $this->db->fetch_object($resql)) {
10261 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . $langs->trans($obj->label) . '</option>';
10262 }
10263 $out .= '</select>';
10264 $out .= ajax_combobox('select_' . $htmlname);
10265
10266 if (!empty($htmlname) && $user->admin && $info_admin) {
10267 $out .= ' ' . info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
10268 }
10269
10270 if (!empty($target)) {
10271 $sql = "SELECT c.id FROM " . $this->db->prefix() . "c_type_fees as c WHERE c.code = 'EX_KME' AND c.active = 1";
10272 $resql = $this->db->query($sql);
10273 if ($resql) {
10274 if ($this->db->num_rows($resql) > 0) {
10275 $obj = $this->db->fetch_object($resql);
10276 $out .= '<script nonce="' . getNonce() . '">
10277 $(function() {
10278 $("select[name=' . $target . ']").on("change", function() {
10279 var current_val = $(this).val();
10280 if (current_val == ' . $obj->id . ') {';
10281 if (!empty($default_selected) || !empty($selected)) {
10282 $out .= '$("select[name=' . $htmlname . ']").val("' . ($default_selected > 0 ? $default_selected : $selected) . '");';
10283 }
10284
10285 $out .= '
10286 $("select[name=' . $htmlname . ']").change();
10287 }
10288 });
10289
10290 $("select[name=' . $htmlname . ']").change(function() {
10291
10292 if ($("select[name=' . $target . ']").val() == ' . $obj->id . ') {
10293 // get price of kilometer to fill the unit price
10294 $.ajax({
10295 method: "POST",
10296 dataType: "json",
10297 data: { fk_c_exp_tax_cat: $(this).val(), token: \'' . currentToken() . '\' },
10298 url: "' . (DOL_URL_ROOT . '/expensereport/ajax/ajaxik.php?' . join('&', $params)) . '",
10299 }).done(function( data, textStatus, jqXHR ) {
10300 console.log(data);
10301 if (typeof data.up != "undefined") {
10302 $("input[name=value_unit]").val(data.up);
10303 $("select[name=' . $htmlname . ']").attr("title", data.title);
10304 } else {
10305 $("input[name=value_unit]").val("");
10306 $("select[name=' . $htmlname . ']").attr("title", "");
10307 }
10308 });
10309 }
10310 });
10311 });
10312 </script>';
10313 }
10314 }
10315 }
10316 } else {
10317 dol_print_error($this->db);
10318 }
10319
10320 return $out;
10321 }
10322
10331 public function selectExpenseRanges($selected = '', $htmlname = 'fk_range', $useempty = 0)
10332 {
10333 global $conf, $langs;
10334
10335 $out = '';
10336 $sql = "SELECT rowid, range_ik FROM " . $this->db->prefix() . "c_exp_tax_range";
10337 $sql .= " WHERE entity = " . $conf->entity . " AND active = 1";
10338
10339 $resql = $this->db->query($sql);
10340 if ($resql) {
10341 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10342 if ($useempty) {
10343 $out .= '<option value="0"></option>';
10344 }
10345
10346 while ($obj = $this->db->fetch_object($resql)) {
10347 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . price($obj->range_ik, 0, $langs, 1, 0) . '</option>';
10348 }
10349 $out .= '</select>';
10350 } else {
10351 dol_print_error($this->db);
10352 }
10353
10354 return $out;
10355 }
10356
10367 public function selectExpense($selected = '', $htmlname = 'fk_c_type_fees', $useempty = 0, $allchoice = 1, $useid = 0)
10368 {
10369 global $langs;
10370
10371 $out = '';
10372 $sql = "SELECT id, code, label";
10373 $sql .= " FROM ".$this->db->prefix()."c_type_fees";
10374 $sql .= " WHERE active = 1";
10375
10376 $resql = $this->db->query($sql);
10377 if ($resql) {
10378 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10379 if ($useempty) {
10380 $out .= '<option value="0"></option>';
10381 }
10382 if ($allchoice) {
10383 $out .= '<option value="-1">' . $langs->trans('AllExpenseReport') . '</option>';
10384 }
10385
10386 $field = 'code';
10387 if ($useid) {
10388 $field = 'id';
10389 }
10390
10391 while ($obj = $this->db->fetch_object($resql)) {
10392 $key = $langs->trans($obj->code);
10393 $out .= '<option ' . ($selected == $obj->{$field} ? 'selected="selected"' : '') . ' value="' . $obj->{$field} . '">' . ($key != $obj->code ? $key : $obj->label) . '</option>';
10394 }
10395 $out .= '</select>';
10396
10397 $out .= ajax_combobox('select_'.$htmlname);
10398 } else {
10399 dol_print_error($this->db);
10400 }
10401
10402 return $out;
10403 }
10404
10423 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)
10424 {
10425 global $user, $conf, $langs;
10426
10427 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
10428
10429 if (is_null($usertofilter)) {
10430 $usertofilter = $user;
10431 }
10432
10433 $out = '';
10434
10435 $hideunselectables = false;
10436 if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
10437 $hideunselectables = true;
10438 }
10439
10440 if (empty($projectsListId)) {
10441 if (!$usertofilter->hasRight('projet', 'all', 'lire')) {
10442 $projectstatic = new Project($this->db);
10443 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertofilter, 0, 1);
10444 }
10445 }
10446
10447 // Search all projects
10448 $sql = "SELECT f.rowid, f.ref as fref, 'nolabel' as flabel, p.rowid as pid, f.ref,
10449 p.title, p.fk_soc, p.fk_statut, p.public,";
10450 $sql .= ' s.nom as name';
10451 $sql .= ' FROM ' . $this->db->prefix() . 'projet as p';
10452 $sql .= ' LEFT JOIN ' . $this->db->prefix() . 'societe as s ON s.rowid = p.fk_soc,';
10453 $sql .= ' ' . $this->db->prefix() . 'facture as f';
10454 $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
10455 $sql .= " AND f.fk_projet = p.rowid AND f.fk_statut=0"; //Brouillons seulement
10456 //if ($projectsListId) $sql.= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")";
10457 //if ($socid == 0) $sql.= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
10458 //if ($socid > 0) $sql.= " AND (p.fk_soc=".((int) $socid)." OR p.fk_soc IS NULL)";
10459 $sql .= " ORDER BY p.ref, f.ref ASC";
10460
10461 $resql = $this->db->query($sql);
10462 if ($resql) {
10463 // Use select2 selector
10464 if (!empty($conf->use_javascript_ajax)) {
10465 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10466 $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus);
10467 $out .= $comboenhancement;
10468 $morecss = 'minwidth200imp maxwidth500';
10469 }
10470
10471 if (empty($option_only)) {
10472 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10473 }
10474 if (!empty($show_empty)) {
10475 $out .= '<option value="0" class="optiongrey">';
10476 if (!is_numeric($show_empty)) {
10477 $out .= $show_empty;
10478 } else {
10479 $out .= '&nbsp;';
10480 }
10481 $out .= '</option>';
10482 }
10483 $num = $this->db->num_rows($resql);
10484 $i = 0;
10485 if ($num) {
10486 while ($i < $num) {
10487 $obj = $this->db->fetch_object($resql);
10488 // 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.
10489 if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$usertofilter->hasRight('societe', 'lire')) {
10490 // Do nothing
10491 } else {
10492 if ($discard_closed == 1 && $obj->fk_statut == Project::STATUS_CLOSED) {
10493 $i++;
10494 continue;
10495 }
10496
10497 $labeltoshow = '';
10498
10499 if ($showproject == 'all') {
10500 $labeltoshow .= dol_trunc($obj->ref, 18); // Invoice ref
10501 if ($obj->name) {
10502 $labeltoshow .= ' - ' . $obj->name; // Soc name
10503 }
10504
10505 $disabled = 0;
10506 if ($obj->fk_statut == Project::STATUS_DRAFT) {
10507 $disabled = 1;
10508 $labeltoshow .= ' - ' . $langs->trans("Draft");
10509 } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
10510 if ($discard_closed == 2) {
10511 $disabled = 1;
10512 }
10513 $labeltoshow .= ' - ' . $langs->trans("Closed");
10514 } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
10515 $disabled = 1;
10516 $labeltoshow .= ' - ' . $langs->trans("LinkedToAnotherCompany");
10517 }
10518 }
10519
10520 if (!empty($selected) && $selected == $obj->rowid) {
10521 $out .= '<option value="' . $obj->rowid . '" selected';
10522 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10523 $out .= '>' . $labeltoshow . '</option>';
10524 } else {
10525 if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
10526 $resultat = '';
10527 } else {
10528 $resultat = '<option value="' . $obj->rowid . '"';
10529 if ($disabled) {
10530 $resultat .= ' disabled';
10531 }
10532 //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
10533 //else $labeltoshow.=' ('.$langs->trans("Private").')';
10534 $resultat .= '>';
10535 $resultat .= $labeltoshow;
10536 $resultat .= '</option>';
10537 }
10538 $out .= $resultat;
10539 }
10540 }
10541 $i++;
10542 }
10543 }
10544 if (empty($option_only)) {
10545 $out .= '</select>';
10546 }
10547
10548 $this->db->free($resql);
10549
10550 return $out;
10551 } else {
10552 dol_print_error($this->db);
10553 return '';
10554 }
10555 }
10556
10570 public function selectInvoiceRec($selected = '', $htmlname = 'facrecid', $maxlength = 24, $option_only = 0, $show_empty = '1', $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500')
10571 {
10572 global $conf, $langs;
10573
10574 $out = '';
10575
10576 dol_syslog('FactureRec::fetch', LOG_DEBUG);
10577
10578 $sql = 'SELECT f.rowid, f.entity, f.titre as title, f.suspended, f.fk_soc';
10579 //$sql.= ', el.fk_source';
10580 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_rec as f';
10581 $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
10582 $sql .= " ORDER BY f.titre ASC";
10583
10584 $resql = $this->db->query($sql);
10585 if ($resql) {
10586 // Use select2 selector
10587 if (!empty($conf->use_javascript_ajax)) {
10588 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10589 $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus);
10590 $out .= $comboenhancement;
10591 $morecss = 'minwidth200imp maxwidth500';
10592 }
10593
10594 if (empty($option_only)) {
10595 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10596 }
10597 if (!empty($show_empty)) {
10598 $out .= '<option value="0" class="optiongrey">';
10599 if (!is_numeric($show_empty)) {
10600 $out .= $show_empty;
10601 } else {
10602 $out .= '&nbsp;';
10603 }
10604 $out .= '</option>';
10605 }
10606 $num = $this->db->num_rows($resql);
10607 if ($num) {
10608 while ($obj = $this->db->fetch_object($resql)) {
10609 $labeltoshow = dol_trunc($obj->title, 18); // Invoice ref
10610
10611 $disabled = 0;
10612 if (!empty($obj->suspended)) {
10613 $disabled = 1;
10614 $labeltoshow .= ' - ' . $langs->trans("Closed");
10615 }
10616
10617
10618 if (!empty($selected) && $selected == $obj->rowid) {
10619 $out .= '<option value="' . $obj->rowid . '" selected';
10620 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10621 $out .= '>' . $labeltoshow . '</option>';
10622 } else {
10623 if ($disabled && ($selected != $obj->rowid)) {
10624 $resultat = '';
10625 } else {
10626 $resultat = '<option value="' . $obj->rowid . '"';
10627 if ($disabled) {
10628 $resultat .= ' disabled';
10629 }
10630 $resultat .= '>';
10631 $resultat .= $labeltoshow;
10632 $resultat .= '</option>';
10633 }
10634 $out .= $resultat;
10635 }
10636 }
10637 }
10638 if (empty($option_only)) {
10639 $out .= '</select>';
10640 }
10641
10642 print $out;
10643
10644 $this->db->free($resql);
10645 return $num;
10646 } else {
10647 $this->errors[] = $this->db->lasterror;
10648 return -1;
10649 }
10650 }
10651
10661 public function searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput = array(), $search_component_params_hidden = '')
10662 {
10663 global $langs;
10664
10665 if ($search_component_params_hidden != '' && !preg_match('/^\‍(.*\‍)$/', $search_component_params_hidden)) { // If $search_component_params_hidden does not start and end with ()
10666 $search_component_params_hidden = '(' . $search_component_params_hidden . ')';
10667 }
10668
10669 $ret = '';
10670
10671 $ret .= '<div class="divadvancedsearchfieldcomp inline-block">';
10672 $ret .= '<a href="#" class="dropdownsearch-toggle unsetcolor">';
10673 $ret .= '<span class="fas fa-filter linkobject boxfilter paddingright pictofixedwidth" title="' . dol_escape_htmltag($langs->trans("Filters")) . '" id="idsubimgproductdistribution"></span>';
10674 $ret .= '</a>';
10675
10676 $ret .= '<div class="divadvancedsearchfieldcompinput inline-block minwidth500 maxwidth300onsmartphone">';
10677
10678 // Show select fields as tags.
10679 $ret .= '<div name="divsearch_component_params" class="noborderbottom search_component_params inline-block valignmiddle">';
10680
10681 if ($search_component_params_hidden) {
10682 // Split the criteria on each AND
10683 //var_dump($search_component_params_hidden);
10684
10685 $nbofchars = dol_strlen($search_component_params_hidden);
10686 $arrayofandtags = array();
10687 $i = 0;
10688 $s = '';
10689 $countparenthesis = 0;
10690 while ($i < $nbofchars) {
10691 $char = dol_substr($search_component_params_hidden, $i, 1);
10692
10693 if ($char == '(') {
10694 $countparenthesis++;
10695 } elseif ($char == ')') {
10696 $countparenthesis--;
10697 }
10698
10699 if ($countparenthesis == 0) {
10700 $char2 = dol_substr($search_component_params_hidden, $i+1, 1);
10701 $char3 = dol_substr($search_component_params_hidden, $i+2, 1);
10702 if ($char == 'A' && $char2 == 'N' && $char3 == 'D') {
10703 // We found a AND
10704 $arrayofandtags[] = trim($s);
10705 $s = '';
10706 $i+=2;
10707 } else {
10708 $s .= $char;
10709 }
10710 } else {
10711 $s .= $char;
10712 }
10713 $i++;
10714 }
10715 if ($s) {
10716 $arrayofandtags[] = trim($s);
10717 }
10718
10719 // Show each AND part
10720 foreach ($arrayofandtags as $tmpkey => $tmpval) {
10721 $errormessage = '';
10722 $searchtags = forgeSQLFromUniversalSearchCriteria($tmpval, $errormessage, 1, 1);
10723 if ($errormessage) {
10724 $this->error = 'ERROR in parsing search string: '.$errormessage;
10725 }
10726 // Remove first and last parenthesis but only if first is the opening and last the closing of the same group
10727 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
10728 $searchtags = removeGlobalParenthesis($searchtags);
10729
10730 $ret .= '<span class="marginleftonlyshort valignmiddle tagsearch" data-ufilterid="'.($tmpkey+1).'" data-ufilter="'.dol_escape_htmltag($tmpval).'">';
10731 $ret .= '<span class="tagsearchdelete select2-selection__choice__remove" data-ufilterid="'.($tmpkey+1).'">x</span> ';
10732 $ret .= dol_escape_htmltag($searchtags);
10733 $ret .= '</span>';
10734 }
10735 }
10736
10737 //$ret .= '<button type="submit" class="liste_titre button_search paddingleftonly" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
10738
10739 //$ret .= search_component_params
10740 //$texttoshow = '<div class="opacitymedium inline-block search_component_searchtext">'.$langs->trans("Search").'</div>';
10741 //$ret .= '<div class="search_component inline-block valignmiddle">'.$texttoshow.'</div>';
10742
10743 $show_search_component_params_hidden = 1;
10744 if ($show_search_component_params_hidden) {
10745 $ret .= '<input type="hidden" name="show_search_component_params_hidden" value="1">';
10746 }
10747 $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%')) -->";
10748 $ret .= '<input type="hidden" name="search_component_params_hidden" value="' . dol_escape_htmltag($search_component_params_hidden) . '">';
10749 // $ret .= "<!-- sql= ".forgeSQLFromUniversalSearchCriteria($search_component_params_hidden, $errormessage)." -->";
10750
10751 // For compatibility with forms that show themself the search criteria in addition of this component, we output these fields
10752 foreach ($arrayofcriterias as $criterias) {
10753 foreach ($criterias as $criteriafamilykey => $criteriafamilyval) {
10754 if (in_array('search_' . $criteriafamilykey, $arrayofinputfieldsalreadyoutput)) {
10755 continue;
10756 }
10757 if (in_array($criteriafamilykey, array('rowid', 'ref_ext', 'entity', 'extraparams'))) {
10758 continue;
10759 }
10760 if (in_array($criteriafamilyval['type'], array('date', 'datetime', 'timestamp'))) {
10761 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_start">';
10762 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startyear">';
10763 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startmonth">';
10764 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startday">';
10765 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_end">';
10766 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endyear">';
10767 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endmonth">';
10768 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endday">';
10769 } else {
10770 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '">';
10771 }
10772 }
10773 }
10774
10775 $ret .= '</div>';
10776
10777 $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";
10778 $ret .= '<input type="text" placeholder="' . $langs->trans("Search") . '" name="search_component_params_input" class="noborderbottom search_component_input" value="">';
10779
10780 $ret .= '</div>';
10781 $ret .= '</div>';
10782
10783 $ret .= '<script>
10784 jQuery(".tagsearchdelete").click(function() {
10785 var filterid = $(this).parents().data("ufilterid");
10786 console.log("We click to delete a criteria nb "+filterid);
10787 // TODO Update the search_component_params_hidden with all data-ufilter except the one delete and post page
10788
10789 });
10790 </script>
10791 ';
10792
10793
10794 return $ret;
10795 }
10796
10806 public function selectModelMail($prefix, $modelType = '', $default = 0, $addjscombo = 0)
10807 {
10808 global $langs, $user;
10809
10810 $retstring = '';
10811
10812 $TModels = array();
10813
10814 include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
10815 $formmail = new FormMail($this->db);
10816 $result = $formmail->fetchAllEMailTemplate($modelType, $user, $langs);
10817
10818 if ($default) {
10819 $TModels[0] = $langs->trans('DefaultMailModel');
10820 }
10821 if ($result > 0) {
10822 foreach ($formmail->lines_model as $model) {
10823 $TModels[$model->id] = $model->label;
10824 }
10825 }
10826
10827 $retstring .= '<select class="flat" id="select_' . $prefix . 'model_mail" name="' . $prefix . 'model_mail">';
10828
10829 foreach ($TModels as $id_model => $label_model) {
10830 $retstring .= '<option value="' . $id_model . '"';
10831 $retstring .= ">" . $label_model . "</option>";
10832 }
10833
10834 $retstring .= "</select>";
10835
10836 if ($addjscombo) {
10837 $retstring .= ajax_combobox('select_' . $prefix . 'model_mail');
10838 }
10839
10840 return $retstring;
10841 }
10842
10854 public function buttonsSaveCancel($save_label = 'Save', $cancel_label = 'Cancel', $morebuttons = array(), $withoutdiv = false, $morecss = '', $dol_openinpopup = '')
10855 {
10856 global $langs;
10857
10858 $buttons = array();
10859
10860 $save = array(
10861 'name' => 'save',
10862 'label_key' => $save_label,
10863 );
10864
10865 if ($save_label == 'Create' || $save_label == 'Add') {
10866 $save['name'] = 'add';
10867 } elseif ($save_label == 'Modify') {
10868 $save['name'] = 'edit';
10869 }
10870
10871 $cancel = array(
10872 'name' => 'cancel',
10873 'label_key' => 'Cancel',
10874 );
10875
10876 !empty($save_label) ? $buttons[] = $save : '';
10877
10878 if (!empty($morebuttons)) {
10879 $buttons[] = $morebuttons;
10880 }
10881
10882 !empty($cancel_label) ? $buttons[] = $cancel : '';
10883
10884 $retstring = $withoutdiv ? '' : '<div class="center">';
10885
10886 foreach ($buttons as $button) {
10887 $addclass = empty($button['addclass']) ? '' : $button['addclass'];
10888 $retstring .= '<input type="submit" class="button button-' . $button['name'] . ($morecss ? ' ' . $morecss : '') . ' ' . $addclass . '" name="' . $button['name'] . '" value="' . dol_escape_htmltag($langs->trans($button['label_key'])) . '">';
10889 }
10890 $retstring .= $withoutdiv ? '' : '</div>';
10891
10892 if ($dol_openinpopup) {
10893 $retstring .= '<!-- buttons are shown into a $dol_openinpopup=' . $dol_openinpopup . ' context, so we enable the close of dialog on cancel -->' . "\n";
10894 $retstring .= '<script nonce="' . getNonce() . '">';
10895 $retstring .= 'jQuery(".button-cancel").click(function(e) {
10896 e.preventDefault(); console.log(\'We click on cancel in iframe popup ' . $dol_openinpopup . '\');
10897 window.parent.jQuery(\'#idfordialog' . $dol_openinpopup . '\').dialog(\'close\');
10898 });';
10899 $retstring .= '</script>';
10900 }
10901
10902 return $retstring;
10903 }
10904
10905
10906 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
10907
10914 {
10915 // phpcs:enable
10916 global $langs;
10917
10918 $num = count($this->cache_invoice_subtype);
10919 if ($num > 0) {
10920 return 0; // Cache already loaded
10921 }
10922
10923 dol_syslog(__METHOD__, LOG_DEBUG);
10924
10925 $sql = "SELECT rowid, code, label as label";
10926 $sql .= " FROM " . MAIN_DB_PREFIX . 'c_invoice_subtype';
10927 $sql .= " WHERE active = 1";
10928
10929 $resql = $this->db->query($sql);
10930 if ($resql) {
10931 $num = $this->db->num_rows($resql);
10932 $i = 0;
10933 while ($i < $num) {
10934 $obj = $this->db->fetch_object($resql);
10935
10936 // If translation exists, we use it, otherwise we take the default wording
10937 $label = ($langs->trans("InvoiceSubtype" . $obj->rowid) != "InvoiceSubtype" . $obj->rowid) ? $langs->trans("InvoiceSubtype" . $obj->rowid) : (($obj->label != '-') ? $obj->label : '');
10938 $this->cache_invoice_subtype[$obj->rowid]['rowid'] = $obj->rowid;
10939 $this->cache_invoice_subtype[$obj->rowid]['code'] = $obj->code;
10940 $this->cache_invoice_subtype[$obj->rowid]['label'] = $label;
10941 $i++;
10942 }
10943
10944 $this->cache_invoice_subtype = dol_sort_array($this->cache_invoice_subtype, 'code', 'asc', 0, 0, 1);
10945
10946 return $num;
10947 } else {
10948 dol_print_error($this->db);
10949 return -1;
10950 }
10951 }
10952
10953
10964 public function getSelectInvoiceSubtype($selected = 0, $htmlname = 'subtypeid', $addempty = 0, $noinfoadmin = 0, $morecss = '')
10965 {
10966 global $langs, $user;
10967
10968 $out = '';
10969 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
10970
10971 $this->load_cache_invoice_subtype();
10972
10973 $out .= '<select id="' . $htmlname . '" class="flat selectsubtype' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
10974 if ($addempty) {
10975 $out .= '<option value="0">&nbsp;</option>';
10976 }
10977
10978 foreach ($this->cache_invoice_subtype as $rowid => $subtype) {
10979 $label = $subtype['label'];
10980 $out .= '<option value="' . $subtype['rowid'] . '"';
10981 if ($selected == $subtype['rowid']) {
10982 $out .= ' selected="selected"';
10983 }
10984 $out .= '>';
10985 $out .= $label;
10986 $out .= '</option>';
10987 }
10988
10989 $out .= '</select>';
10990 if ($user->admin && empty($noinfoadmin)) {
10991 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
10992 }
10993 $out .= ajax_combobox($htmlname);
10994
10995 return $out;
10996 }
10997}
ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLength=2, $autoselect=0, $ajaxoptions=array(), $moreparams='')
Generic function that return javascript to add to a page to transform a common input field into an au...
Definition ajax.lib.php:47
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:447
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 field into an au...
Definition ajax.lib.php:295
ajax_event($htmlname, $events)
Add event management script.
Definition ajax.lib.php:548
$object ref
Definition info.php:79
Class to manage bank accounts.
Class to manage categories.
Class to manage a WYSIWYG editor.
DAO Resource object.
const STATUS_OPEN_INTERNAL
Warehouse open and only operations for stock transfers/corrections allowed (not for customer shipping...
const STATUS_OPEN_ALL
Warehouse open and any operations are allowed (customer shipping, supplier dispatch,...
const STATUS_CLOSED
Warehouse closed, inactive.
Class to manage standard extra languages.
Class to manage invoices.
Class to manage generation of HTML components Only common components must be here.
selectModelMail($prefix, $modelType='', $default=0, $addjscombo=0)
selectModelMail
showFilterButtons($pos='')
Return HTML to show the search and clear seach button.
selectyesno($htmlname, $value='', $option=0, $disabled=false, $useempty=0, $addjscombo=0, $morecss='', $labelyes='Yes', $labelno='No')
Return an html string with a select combo box to choose yes or no.
load_cache_vatrates($country_code)
Load into the cache vat rates of a country.
select_type_of_lines($selected='', $htmlname='type', $showempty=0, $hidetext=0, $forceall=0)
Return list of types of lines (product or service) Example: 0=product, 1=service, 9=other (for extern...
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.
select_contacts($socid, $selected='', $htmlname='contactid', $showempty=0, $exclude='', $limitto='', $showfunction=0, $morecss='', $showsoc=0, $forcecombo=0, $events=array(), $options_only=false, $moreparam='', $htmlid='')
Return list of all contacts (for a third party or all)
form_availability($page, $selected='', $htmlname='availability', $addempty=0)
Show a form to select a delivery delay.
showLinkedObjectBlock($object, $morehtmlright='', $compatibleImportElementsList=array(), $title='RelatedObjects')
Show linked object block.
select_produits_fournisseurs($socid, $selected='', $htmlname='productid', $filtertype='', $filtre='', $ajaxoptions=array(), $hidelabel=0, $alsoproductwithnosupplierprice=0, $morecss='', $placeholder='')
Return list of products for customer (in Ajax if Ajax activated or go to select_produits_fournisseurs...
selectMassAction($selected, $arrayofaction, $alwaysvisible=0, $name='massaction', $cssclass='checkforselect')
Generate select HTML to choose massaction.
select_dolresources_forevent($action='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include=array(), $enableonly=array(), $force_entity='0', $maxlength=0, $showstatus=0, $morefilter='', $showproperties=0, $listofresourceid=array())
Return select list of resources.
formconfirm($page, $title, $question, $action, $formquestion='', $selectedchoice='', $useajax=0, $height=0, $width=500, $disableformtag=0, $labelbuttonyes='Yes', $labelbuttonno='No')
form_multicurrency_code($page, $selected='', $htmlname='multicurrency_code')
Show form with multicurrency code.
select_produits($selected=0, $htmlname='productid', $filtertype='', $limit=0, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(), $socid=0, $showempty='1', $forcecombo=0, $morecss='', $hidepriceinlabel=0, $warehouseStatus='', $selected_combinations=null, $nooutput=0, $status_purchase=-1)
Return list of products for customer in Ajax if Ajax activated or go to select_produits_list.
showFilterAndCheckAddButtons($addcheckuncheckall=0, $cssclass='checkforaction', $calljsfunction=0, $massactionname="massaction")
Return HTML to show the search and clear seach 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.
textwithpicto($text, $htmltext, $direction=1, $type='help', $extracss='', $noencodehtmltext=0, $notabs=3, $tooltiptrigger='', $forcenowrap=0)
Show a text with a picto and a tooltip on picto.
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_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 optionaly hours and minute...
select_types_paiements($selected='', $htmlname='paiementtype', $filtertype='', $format=0, $empty=1, $noadmininfo=0, $maxlength=0, $active=1, $morecss='', $nooutput=0)
Return list of payment methods Constant MAIN_DEFAULT_PAYMENT_TYPE_ID can used to set default value bu...
select_currency($selected='', $htmlname='currency_id')
Retourne la liste des devises, dans la langue de l'utilisateur.
formSelectTransportMode($page, $selected='', $htmlname='transport_mode_id', $active=1, $addempty=0)
Show form with transport mode.
selectShippingMethod($selected='', $htmlname='shipping_method_id', $filtre='', $useempty=0, $moreattrib='', $noinfoadmin=0, $morecss='')
Return a HTML select list of shipping mode.
formSelectShippingMethod($page, $selected='', $htmlname='shipping_method_id', $addempty=0)
Display form to select shipping mode.
getSelectInvoiceSubtype($selected=0, $htmlname='subtypeid', $addempty=0, $noinfoadmin=0, $morecss='')
Return list of invoice subtypes.
form_contacts($page, $societe, $selected='', $htmlname='contactid')
Show forms to select a contact.
selectMultiCurrency($selected='', $htmlname='multicurrency_code', $useempty=0, $filter='', $excludeConfCurrency=false, $morecss='')
Return array of currencies in user language.
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.
select_dolgroups($selected='', $htmlname='groupid', $show_empty=0, $exclude='', $disabled=0, $include='', $enableonly=array(), $force_entity='0', $multiple=false, $morecss='')
Return select list of groups.
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='')
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.
select_conditions_paiements($selected=0, $htmlname='condid', $filtertype=-1, $addempty=0, $noinfoadmin=0, $morecss='', $deposit_percent=-1)
print list of payment modes.
showLinkToObjectBlock($object, $restrictlinksto=array(), $excludelinksto=array())
Show block with links to link to other objects.
form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter='', $maxvalue=0, $more='', $hidelist=0, $discount_type=0)
Show a select box with available absolute discounts.
select_all_categories($type, $selected='', $htmlname="parent", $maxlength=64, $markafterid=0, $outputmode=0, $include=0, $morecss='')
Return list of categories having choosed type.
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='')
selectcontacts($socid, $selected=array(), $htmlname='contactid', $showempty=0, $exclude='', $limitto='', $showfunction=0, $morecss='', $options_only=false, $showsoc=0, $forcecombo=0, $events=array(), $moreparam='', $htmlid='', $multiple=false, $disableifempty=0)
Return HTML code of the SELECT of list of all contacts (for a third party or all).
static showphoto($modulepart, $object, $width=100, $height=0, $caneditfield=0, $cssclass='photowithmargin', $imagesize='', $addlinktofullsize=1, $cache=0, $forcecapture='', $noexternsourceoverwrite=0)
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()
selectPriceBaseType($selected='', $htmlname='price_base_type', $addjscombo=0)
Selection HT or TTC.
load_cache_transport_mode()
select_remises($selected, $htmlname, $filter, $socid, $maxvalue=0)
Return HTML combo list of absolute discounts.
showbarcode(&$object, $width=100, $morecss='')
Return HTML code to output a barcode.
form_confirm($page, $title, $question, $action, $formquestion=array(), $selectedchoice="", $useajax=0, $height=170, $width=500)
load_cache_conditions_paiements()
form_project($page, $socid, $selected='', $htmlname='projectid', $discard_closed=0, $maxlength=20, $forcefocus=0, $nooutput=0, $textifnoproject='', $morecss='')
Show a form to select a project.
selectExpenseCategories($selected='', $htmlname='fk_c_exp_tax_cat', $useempty=0, $excludeid=array(), $target='', $default_selected=0, $params=array(), $info_admin=1)
Return HTML to show the select of expense categories.
select_product_fourn_price($productid, $htmlname='productfournpriceid', $selected_supplier=0)
Return list of suppliers prices for a product.
select_produits_list($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $filterkey='', $status=1, $finished=2, $outputmode=0, $socid=0, $showempty='1', $forcecombo=0, $morecss='', $hidepriceinlabel=0, $warehouseStatus='', $status_purchase=-1)
Return list of products for a customer.
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.
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_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 optionaly hours and minute...
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 optionaly hours and minute...
textwithtooltip($text, $htmltext, $tooltipon=1, $direction=0, $img='', $extracss='', $notabs=3, $incbefore='', $noencodehtmltext=0, $tooltiptrigger='', $forcenowrap=0)
Show a text and picto with tooltip on text or picto.
searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput=array(), $search_component_params_hidden='')
Output the component to make advanced search criteries.
select_dolusers($selected='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly='', $force_entity='', $maxlength=0, $showstatus=0, $morefilter='', $show_every=0, $enableonlytext='', $morecss='', $notdisabled=0, $outputmode=0, $multiple=false, $forcecombo=0)
Return select list of users.
getSelectConditionsPaiements($selected=0, $htmlname='condid', $filtertype=-1, $addempty=0, $noinfoadmin=0, $morecss='', $deposit_percent=-1)
Return list of payment modes.
widgetForTranslation($fieldname, $object, $perm, $typeofdata='string', $check='', $morecss='')
Output edit in place form.
load_cache_types_fees()
Load into cache cache_types_fees, array of types of fees.
static multiselectarray($htmlname, $array, $selected=array(), $key_in_label=0, $value_as_key=0, $morecss='', $translate=0, $width=0, $moreattrib='', $elemtype='', $placeholder='', $addjscombo=-1)
Show a multiselect form from an array.
form_thirdparty($page, $selected='', $htmlname='socid', $filter='', $showempty=0, $showtype=0, $forcecombo=0, $events=array(), $nooutput=0, $excludeids=array(), $textifnothirdparty='')
Output html select to select thirdparty.
selectEstablishments($selected='', $htmlname='entity', $status=0, $filtre='', $useempty=0, $moreattrib='')
Return a HTML select list of establishment.
formSelectAccount($page, $selected='', $htmlname='fk_account', $addempty=0)
Display form to select bank account.
form_users($page, $selected='', $htmlname='userid', $exclude=array(), $include=array())
Show a select form to choose a user.
editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata='string', $moreparam='', $fieldrequired=0, $notabletag=0, $paramid='id', $help='')
Output key field for an editable field.
showCategories($id, $type, $rendermode=0, $nolink=0)
Render list of categories linked to object with id $id and type $type.
load_tva($htmlname='tauxtva', $selectedrate='', $societe_vendeuse=null, $societe_acheteuse=null, $idprod=0, $info_bits=0, $type='', $options_only=false, $mode=0)
Output an HTML select vat rate.
load_cache_types_paiements()
selectAvailabilityDelay($selected='', $htmlname='availid', $filtertype='', $addempty=0, $morecss='')
selectForForms($objectdesc, $htmlname, $preSelectedValue, $showempty='', $searchkey='', $placeholder='', $morecss='', $moreparams='', $forcecombo=0, $disabled=0, $selected_input_value='', $objectfield='')
Generic method to select a component from a combo list.
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...
Classe permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new For...
Class to manage building of HTML components.
Class to manage forms for the module resource.
Class to manage hooks.
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.
currency_name($code_iso, $withcode='', $outputlangs=null)
Return label of currency or code+label.
getCountry($searchkey, $withcode='', $dbtouse=0, $outputlangs='', $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or 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...
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formated 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.
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_help($usehelpcursor=1, $usealttitle=1)
Show help logo with cursor "?".
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_print_email($email, $cid=0, $socid=0, $addlink=0, $max=64, $showinvalid=1, $withpicto=0)
Show EMail link formatted for HTML output.
dol_print_phone($phone, $countrycode='', $cid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0)
Format phone numbers according to country.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles=1, $removeclassattribute=1, $cleanalsojavascript=0, $allowiframe=0, $allowed_tags=array(), $allowlink=0)
Clean a string to keep only desirable HTML tags.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by second index function, which produces ascending (default) or descending output...
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
dol_string_neverthesehtmltags($stringtoclean, $disallowed_tags=array('textarea'), $cleanalsosomestyles=0)
Clean a string from some undesirable HTML tags.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that returns whether VAT must be recoverable collected VAT (e.g.: VAT NPR in France)
dol_htmlentities($string, $flags=ENT_QUOTES|ENT_SUBSTITUTE, $encoding='UTF-8', $double_encode=false)
Replace htmlentities functions.
getImageFileNameForSize($file, $extName, $extImgTarget='')
Return the filename of file to get the thumbs.
dol_substr($string, $start, $length=null, $stringencoding='', $trunconbytes=0)
Make a substring.
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.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getNonce()
Return a random string to be used as a nonce value for js.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox=0, $check='restricthtml')
Sanitize a HTML to remove js, dangerous content and external link.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier 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...
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall right right takeposterminal SELECT e rowid
Definition invoice.php:1907
testSqlAndScriptInject($val, $type)
Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET,...
Definition main.inc.php:89
ui dialog ui datepicker calendar ui widget content ui state ui datepicker calendar ui widget header ui state ui datepicker calendar ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
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:121
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:124
getMaxFileSizeArray()
Return the max allowed for file upload.
dol_hash($chain, $type='0', $nosalt=0)
Returns a hash (non reversible encryption) of a string.
Contact()
Old copy.
Definition index.php:572