dolibarr 19.0.4
html.form.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
5 * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
6 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
7 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com>
8 * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
9 * Copyright (C) 2006 Marc Barilley/Ocebo <marc@ocebo.com>
10 * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerker@telenet.be>
11 * Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
12 * Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
13 * Copyright (C) 2010-2021 Philippe Grand <philippe.grand@atoo-net.com>
14 * Copyright (C) 2011 Herve Prot <herve.prot@symeos.com>
15 * Copyright (C) 2012-2016 Marcos García <marcosgdf@gmail.com>
16 * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
17 * Copyright (C) 2012-2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
18 * Copyright (C) 2014-2023 Alexandre Spangaro <aspangaro@open-dsi.fr>
19 * Copyright (C) 2018-2022 Ferran Marcet <fmarcet@2byte.es>
20 * Copyright (C) 2018-2021 Frédéric France <frederic.france@netlogic.fr>
21 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
22 * Copyright (C) 2018 Christophe Battarel <christophe@altairis.fr>
23 * Copyright (C) 2018 Josep Lluis Amador <joseplluis@lliuretic.cat>
24 * Copyright (C) 2023 Joachim Kueter <git-jk@bloxera.com>
25 * Copyright (C) 2023 Nick Fragoulis
26 *
27 * This program is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License as published by
29 * the Free Software Foundation; either version 3 of the License, or
30 * (at your option) any later version.
31 *
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with this program. If not, see <https://www.gnu.org/licenses/>.
39 */
40
54class Form
55{
59 public $db;
60
64 public $error = '';
65
69 public $errors = array();
70
71 // Some properties used to return data by some methods
72 public $result;
73 public $num;
74
75 // Cache arrays
76 public $cache_types_paiements = array();
77 public $cache_conditions_paiements = array();
78 public $cache_transport_mode = array();
79 public $cache_availability = array();
80 public $cache_demand_reason = array();
81 public $cache_types_fees = array();
82 public $cache_vatrates = array();
83 public $cache_invoice_subtype = array();
84
85
91 public function __construct($db)
92 {
93 $this->db = $db;
94 }
95
112 public function editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata = 'string', $moreparam = '', $fieldrequired = 0, $notabletag = 0, $paramid = 'id', $help = '')
113 {
114 global $conf, $langs;
115
116 $ret = '';
117
118 // TODO change for compatibility
119 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;/', $typeofdata)) {
120 if (!empty($perm)) {
121 $tmp = explode(':', $typeofdata);
122 $ret .= '<div class="editkey_' . $tmp[0] . (!empty($tmp[1]) ? ' ' . $tmp[1] : '') . '" id="' . $htmlname . '">';
123 if ($fieldrequired) {
124 $ret .= '<span class="fieldrequired">';
125 }
126 if ($help) {
127 $ret .= $this->textwithpicto($langs->trans($text), $help);
128 } else {
129 $ret .= $langs->trans($text);
130 }
131 if ($fieldrequired) {
132 $ret .= '</span>';
133 }
134 $ret .= '</div>' . "\n";
135 } else {
136 if ($fieldrequired) {
137 $ret .= '<span class="fieldrequired">';
138 }
139 if ($help) {
140 $ret .= $this->textwithpicto($langs->trans($text), $help);
141 } else {
142 $ret .= $langs->trans($text);
143 }
144 if ($fieldrequired) {
145 $ret .= '</span>';
146 }
147 }
148 } else {
149 if (empty($notabletag) && $perm) {
150 $ret .= '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
151 }
152 if ($fieldrequired) {
153 $ret .= '<span class="fieldrequired">';
154 }
155 if ($help) {
156 $ret .= $this->textwithpicto($langs->trans($text), $help);
157 } else {
158 $ret .= $langs->trans($text);
159 }
160 if ($fieldrequired) {
161 $ret .= '</span>';
162 }
163 if (!empty($notabletag)) {
164 $ret .= ' ';
165 }
166 if (empty($notabletag) && $perm) {
167 $ret .= '</td>';
168 }
169 if (empty($notabletag) && $perm) {
170 $ret .= '<td class="right">';
171 }
172 if ($htmlname && GETPOST('action', 'aZ09') != 'edit' . $htmlname && $perm) {
173 $ret .= '<a class="editfielda reposition" href="' . $_SERVER["PHP_SELF"] . '?action=edit' . $htmlname . '&token=' . newToken() . '&' . $paramid . '=' . $object->id . $moreparam . '">' . img_edit($langs->trans('Edit'), ($notabletag ? 0 : 1)) . '</a>';
174 }
175 if (!empty($notabletag) && $notabletag == 1) {
176 if ($text) {
177 $ret .= ' : ';
178 } else {
179 $ret .= ' ';
180 }
181 }
182 if (!empty($notabletag) && $notabletag == 3) {
183 $ret .= ' ';
184 }
185 if (empty($notabletag) && $perm) {
186 $ret .= '</td>';
187 }
188 if (empty($notabletag) && $perm) {
189 $ret .= '</tr></table>';
190 }
191 }
192
193 return $ret;
194 }
195
219 public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 1, $formatfunc = '', $paramid = 'id', $gm = 'auto', $moreoptions = array(), $editaction = '')
220 {
221 global $conf, $langs;
222
223 $ret = '';
224
225 // Check parameters
226 if (empty($typeofdata)) {
227 return 'ErrorBadParameter typeofdata is empty';
228 }
229 // Clean paramater $typeofdata
230 if ($typeofdata == 'datetime') {
231 $typeofdata = 'dayhour';
232 }
233 $reg = array();
234 if (preg_match('/^(\w+)\‍((\d+)\‍)$/', $typeofdata, $reg)) {
235 if ($reg[1] == 'varchar') {
236 $typeofdata = 'string';
237 } elseif ($reg[1] == 'int') {
238 $typeofdata = 'numeric';
239 } else {
240 return 'ErrorBadParameter ' . $typeofdata;
241 }
242 }
243
244 // When option to edit inline is activated
245 if (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE') && !preg_match('/^select;|day|datepicker|dayhour|datehourpicker/', $typeofdata)) { // TODO add jquery timepicker and support select
246 $ret .= $this->editInPlace($object, $value, $htmlname, $perm, $typeofdata, $editvalue, $extObject, $custommsg);
247 } else {
248 if ($editaction == '') {
249 $editaction = GETPOST('action', 'aZ09');
250 }
251 $editmode = ($editaction == 'edit' . $htmlname);
252 if ($editmode) { // edit mode
253 $ret .= "\n";
254 $ret .= '<form method="post" action="' . $_SERVER["PHP_SELF"] . ($moreparam ? '?' . $moreparam : '') . '">';
255 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
256 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
257 $ret .= '<input type="hidden" name="' . $paramid . '" value="' . $object->id . '">';
258 if (empty($notabletag)) {
259 $ret .= '<table class="nobordernopadding centpercent">';
260 }
261 if (empty($notabletag)) {
262 $ret .= '<tr><td>';
263 }
264 if (preg_match('/^(string|safehtmlstring|email|phone|url)/', $typeofdata)) {
265 $tmp = explode(':', $typeofdata);
266 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($editvalue ? $editvalue : $value) . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
267 } elseif (preg_match('/^(integer)/', $typeofdata)) {
268 $tmp = explode(':', $typeofdata);
269 $valuetoshow = price2num($editvalue ? $editvalue : $value, 0);
270 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . $valuetoshow . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
271 } elseif (preg_match('/^(numeric|amount)/', $typeofdata)) {
272 $tmp = explode(':', $typeofdata);
273 $valuetoshow = price2num($editvalue ? $editvalue : $value);
274 $ret .= '<input type="text" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($valuetoshow != '' ? price($valuetoshow) : '') . '"' . (empty($tmp[1]) ? '' : ' size="' . $tmp[1] . '"') . ' autofocus>';
275 } elseif (preg_match('/^(checkbox)/', $typeofdata)) {
276 $tmp = explode(':', $typeofdata);
277 $ret .= '<input type="checkbox" id="' . $htmlname . '" name="' . $htmlname . '" value="' . ($value ? $value : 'on') . '"' . ($value ? ' checked' : '') . (empty($tmp[1]) ? '' : $tmp[1]) . '/>';
278 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) { // if wysiwyg is enabled $typeofdata = 'ckeditor'
279 $tmp = explode(':', $typeofdata);
280 $cols = (empty($tmp[2]) ? '' : $tmp[2]);
281 $morealt = '';
282 if (preg_match('/%/', $cols)) {
283 $morealt = ' style="width: ' . $cols . '"';
284 $cols = '';
285 }
286 $valuetoshow = ($editvalue ? $editvalue : $value);
287 $ret .= '<textarea id="' . $htmlname . '" name="' . $htmlname . '" wrap="soft" rows="' . (empty($tmp[1]) ? '20' : $tmp[1]) . '"' . ($cols ? ' cols="' . $cols . '"' : 'class="quatrevingtpercent"') . $morealt . '" autofocus>';
288 // textarea convert automatically entities chars into simple chars.
289 // So we convert & into &amp; so a string like 'a &lt; <b>b</b><br>é<br>&lt;script&gt;alert('X');&lt;script&gt;' stay a correct html and is not converted by textarea component when wysiwig is off.
290 $valuetoshow = str_replace('&', '&amp;', $valuetoshow);
291 $ret .= dol_htmlwithnojs(dol_string_neverthesehtmltags($valuetoshow, array('textarea')));
292 $ret .= '</textarea>';
293 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
294 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
295 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
296 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
297 $ret .= $this->selectDate($value, $htmlname, 0, 0, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
298 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
299 $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink'];
300 $adddateof = empty($moreoptions['adddateof']) ? '' : $moreoptions['adddateof'];
301 $labeladddateof = empty($moreoptions['labeladddateof']) ? '' : $moreoptions['labeladddateof'];
302 $ret .= $this->selectDate($value, $htmlname, 1, 1, 1, 'form' . $htmlname, 1, $addnowlink, 0, '', '', $adddateof, '', 1, $labeladddateof, '', $gm);
303 } elseif (preg_match('/^select;/', $typeofdata)) {
304 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
305 $arraylist = array();
306 foreach ($arraydata as $val) {
307 $tmp = explode(':', $val);
308 $tmpkey = str_replace('|', ':', $tmp[0]);
309 $arraylist[$tmpkey] = $tmp[1];
310 }
311 $ret .= $this->selectarray($htmlname, $arraylist, $value);
312 } elseif (preg_match('/^link/', $typeofdata)) {
313 // TODO Not yet implemented. See code for extrafields
314 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
315 $tmp = explode(':', $typeofdata); // Example: ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols:uselocalbrowser
316 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
317 $doleditor = new DolEditor($htmlname, ($editvalue ? $editvalue : $value), (empty($tmp[2]) ? '' : $tmp[2]), (empty($tmp[3]) ? '100' : $tmp[3]), (empty($tmp[1]) ? 'dolibarr_notes' : $tmp[1]), 'In', (empty($tmp[5]) ? 0 : $tmp[5]), (isset($tmp[8]) ? ($tmp[8] ? true : false) : true), true, (empty($tmp[6]) ? '20' : $tmp[6]), (empty($tmp[7]) ? '100' : $tmp[7]));
318 $ret .= $doleditor->Create(1);
319 } elseif ($typeofdata == 'asis') {
320 $ret .= ($editvalue ? $editvalue : $value);
321 }
322 if (empty($notabletag)) {
323 $ret .= '</td>';
324 }
325
326 // Button save-cancel
327 if (empty($notabletag)) {
328 $ret .= '<td>';
329 }
330 //else $ret.='<div class="clearboth"></div>';
331 $ret .= '<input type="submit" class="smallpaddingimp button' . (empty($notabletag) ? '' : ' ') . '" name="modify" value="' . $langs->trans("Modify") . '">';
332 if (preg_match('/ckeditor|textarea/', $typeofdata) && empty($notabletag)) {
333 $ret .= '<br>' . "\n";
334 }
335 $ret .= '<input type="submit" class="smallpaddingimp button button-cancel' . (empty($notabletag) ? '' : ' ') . '" name="cancel" value="' . $langs->trans("Cancel") . '">';
336 if (empty($notabletag)) {
337 $ret .= '</td>';
338 }
339
340 if (empty($notabletag)) {
341 $ret .= '</tr></table>' . "\n";
342 }
343 $ret .= '</form>' . "\n";
344 } else { // view mode
345 if (preg_match('/^email/', $typeofdata)) {
346 $ret .= dol_print_email($value, 0, 0, 0, 0, 1);
347 } elseif (preg_match('/^phone/', $typeofdata)) {
348 $ret .= dol_print_phone($value, '_blank', 32, 1);
349 } elseif (preg_match('/^url/', $typeofdata)) {
350 $ret .= dol_print_url($value, '_blank', 32, 1);
351 } elseif (preg_match('/^(amount|numeric)/', $typeofdata)) {
352 $ret .= ($value != '' ? price($value, '', $langs, 0, -1, -1, $conf->currency) : '');
353 } elseif (preg_match('/^checkbox/', $typeofdata)) {
354 $tmp = explode(':', $typeofdata);
355 $ret .= '<input type="checkbox" disabled id="' . $htmlname . '" name="' . $htmlname . '" value="' . $value . '"' . ($value ? ' checked' : '') . ($tmp[1] ? $tmp[1] : '') . '/>';
356 } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) {
358 } elseif (preg_match('/^(safehtmlstring|restricthtml)/', $typeofdata)) { // 'restricthtml' is not an allowed type for editfieldval. Value is 'safehtmlstring'
360 } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') {
361 $ret .= '<span class="valuedate">' . dol_print_date($value, 'day', $gm) . '</span>';
362 } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') {
363 $ret .= '<span class="valuedate">' . dol_print_date($value, 'dayhour', $gm) . '</span>';
364 } elseif (preg_match('/^select;/', $typeofdata)) {
365 $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata));
366 $arraylist = array();
367 foreach ($arraydata as $val) {
368 $tmp = explode(':', $val);
369 $arraylist[$tmp[0]] = $tmp[1];
370 }
371 $ret .= $arraylist[$value];
372 if ($htmlname == 'fk_product_type') {
373 if ($value == 0) {
374 $ret = img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
375 } else {
376 $ret = img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"') . $ret;
377 }
378 }
379 } elseif (preg_match('/^ckeditor/', $typeofdata)) {
380 $tmpcontent = dol_htmlentitiesbr($value);
381 if (getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
382 $firstline = preg_replace('/<br>.*/', '', $tmpcontent);
383 $firstline = preg_replace('/[\n\r].*/', '', $firstline);
384 $tmpcontent = $firstline . ((strlen($firstline) != strlen($tmpcontent)) ? '...' : '');
385 }
386 // We dont use dol_escape_htmltag to get the html formating active, but this need we must also
387 // clean data from some dangerous html
389 } else {
390 if (empty($moreoptions['valuealreadyhtmlescaped'])) {
391 $ret .= dol_escape_htmltag($value);
392 } else {
393 $ret .= $value; // $value must be already html escaped.
394 }
395 }
396
397 // Custom format if parameter $formatfunc has been provided
398 if ($formatfunc && method_exists($object, $formatfunc)) {
399 $ret = $object->$formatfunc($ret);
400 }
401 }
402 }
403 return $ret;
404 }
405
417 public function widgetForTranslation($fieldname, $object, $perm, $typeofdata = 'string', $check = '', $morecss = '')
418 {
419 global $conf, $langs, $extralanguages;
420
421 $result = '';
422
423 // List of extra languages
424 $arrayoflangcode = array();
425 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
426 $arrayoflangcode[] = $conf->global->PDF_USE_ALSO_LANGUAGE_CODE;
427 }
428
429 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
430 if (!is_object($extralanguages)) {
431 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
432 $extralanguages = new ExtraLanguages($this->db);
433 }
434 $extralanguages->fetch_name_extralanguages('societe');
435
436 if (!is_array($extralanguages->attributes[$object->element]) || empty($extralanguages->attributes[$object->element][$fieldname])) {
437 return ''; // No extralang field to show
438 }
439
440 $result .= '<!-- Widget for translation -->' . "\n";
441 $result .= '<div class="inline-block paddingleft image-' . $object->element . '-' . $fieldname . '">';
442 $s = img_picto($langs->trans("ShowOtherLanguages"), 'language', '', false, 0, 0, '', 'fa-15 editfieldlang');
443 $result .= $s;
444 $result .= '</div>';
445
446 $result .= '<div class="inline-block hidden field-' . $object->element . '-' . $fieldname . '">';
447
448 $resultforextrlang = '';
449 foreach ($arrayoflangcode as $langcode) {
450 $valuetoshow = GETPOSTISSET('field-' . $object->element . "-" . $fieldname . "-" . $langcode) ? GETPOST('field-' . $object->element . '-' . $fieldname . "-" . $langcode, $check) : '';
451 if (empty($valuetoshow)) {
452 $object->fetchValuesForExtraLanguages();
453 //var_dump($object->array_languages);
454 $valuetoshow = $object->array_languages[$fieldname][$langcode];
455 }
456
457 $s = picto_from_langcode($langcode, 'class="pictoforlang paddingright"');
458 $resultforextrlang .= $s;
459
460 // TODO Use the showInputField() method of ExtraLanguages object
461 if ($typeofdata == 'textarea') {
462 $resultforextrlang .= '<textarea name="field-' . $object->element . "-" . $fieldname . "-" . $langcode . '" id="' . $fieldname . "-" . $langcode . '" class="' . $morecss . '" rows="' . ROWS_2 . '" wrap="soft">';
463 $resultforextrlang .= $valuetoshow;
464 $resultforextrlang .= '</textarea>';
465 } else {
466 $resultforextrlang .= '<input type="text" class="inputfieldforlang ' . ($morecss ? ' ' . $morecss : '') . '" name="field-' . $object->element . '-' . $fieldname . '-' . $langcode . '" value="' . $valuetoshow . '">';
467 }
468 }
469 $result .= $resultforextrlang;
470
471 $result .= '</div>';
472 $result .= '<script nonce="' . getNonce() . '">$(".image-' . $object->element . '-' . $fieldname . '").click(function() { console.log("Toggle lang widget"); jQuery(".field-' . $object->element . '-' . $fieldname . '").toggle(); });</script>';
473 }
474
475 return $result;
476 }
477
491 protected function editInPlace($object, $value, $htmlname, $condition, $inputType = 'textarea', $editvalue = null, $extObject = null, $custommsg = null)
492 {
493 global $conf;
494
495 $out = '';
496
497 // Check parameters
498 if (preg_match('/^text/', $inputType)) {
499 $value = dol_nl2br($value);
500 } elseif (preg_match('/^numeric/', $inputType)) {
501 $value = price($value);
502 } elseif ($inputType == 'day' || $inputType == 'datepicker') {
503 $value = dol_print_date($value, 'day');
504 }
505
506 if ($condition) {
507 $element = false;
508 $table_element = false;
509 $fk_element = false;
510 $loadmethod = false;
511 $savemethod = false;
512 $ext_element = false;
513 $button_only = false;
514 $inputOption = '';
515 $rows = '';
516 $cols = '';
517
518 if (is_object($object)) {
519 $element = $object->element;
520 $table_element = $object->table_element;
521 $fk_element = $object->id;
522 }
523
524 if (is_object($extObject)) {
525 $ext_element = $extObject->element;
526 }
527
528 if (preg_match('/^(string|email|numeric)/', $inputType)) {
529 $tmp = explode(':', $inputType);
530 $inputType = $tmp[0];
531 if (!empty($tmp[1])) {
532 $inputOption = $tmp[1];
533 }
534 if (!empty($tmp[2])) {
535 $savemethod = $tmp[2];
536 }
537 $out .= '<input id="width_' . $htmlname . '" value="' . $inputOption . '" type="hidden"/>' . "\n";
538 } elseif ((preg_match('/^day$/', $inputType)) || (preg_match('/^datepicker/', $inputType)) || (preg_match('/^datehourpicker/', $inputType))) {
539 $tmp = explode(':', $inputType);
540 $inputType = $tmp[0];
541 if (!empty($tmp[1])) {
542 $inputOption = $tmp[1];
543 }
544 if (!empty($tmp[2])) {
545 $savemethod = $tmp[2];
546 }
547
548 $out .= '<input id="timestamp" type="hidden"/>' . "\n"; // Use for timestamp format
549 } elseif (preg_match('/^(select|autocomplete)/', $inputType)) {
550 $tmp = explode(':', $inputType);
551 $inputType = $tmp[0];
552 $loadmethod = $tmp[1];
553 if (!empty($tmp[2])) {
554 $savemethod = $tmp[2];
555 }
556 if (!empty($tmp[3])) {
557 $button_only = true;
558 }
559 } elseif (preg_match('/^textarea/', $inputType)) {
560 $tmp = explode(':', $inputType);
561 $inputType = $tmp[0];
562 $rows = (empty($tmp[1]) ? '8' : $tmp[1]);
563 $cols = (empty($tmp[2]) ? '80' : $tmp[2]);
564 } elseif (preg_match('/^ckeditor/', $inputType)) {
565 $tmp = explode(':', $inputType);
566 $inputType = $tmp[0];
567 $toolbar = $tmp[1];
568 if (!empty($tmp[2])) {
569 $width = $tmp[2];
570 }
571 if (!empty($tmp[3])) {
572 $heigth = $tmp[3];
573 }
574 if (!empty($tmp[4])) {
575 $savemethod = $tmp[4];
576 }
577
578 if (isModEnabled('fckeditor')) {
579 $out .= '<input id="ckeditor_toolbar" value="' . $toolbar . '" type="hidden"/>' . "\n";
580 } else {
581 $inputType = 'textarea';
582 }
583 }
584
585 $out .= '<input id="element_' . $htmlname . '" value="' . $element . '" type="hidden"/>' . "\n";
586 $out .= '<input id="table_element_' . $htmlname . '" value="' . $table_element . '" type="hidden"/>' . "\n";
587 $out .= '<input id="fk_element_' . $htmlname . '" value="' . $fk_element . '" type="hidden"/>' . "\n";
588 $out .= '<input id="loadmethod_' . $htmlname . '" value="' . $loadmethod . '" type="hidden"/>' . "\n";
589 if (!empty($savemethod)) {
590 $out .= '<input id="savemethod_' . $htmlname . '" value="' . $savemethod . '" type="hidden"/>' . "\n";
591 }
592 if (!empty($ext_element)) {
593 $out .= '<input id="ext_element_' . $htmlname . '" value="' . $ext_element . '" type="hidden"/>' . "\n";
594 }
595 if (!empty($custommsg)) {
596 if (is_array($custommsg)) {
597 if (!empty($custommsg['success'])) {
598 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg['success'] . '" type="hidden"/>' . "\n";
599 }
600 if (!empty($custommsg['error'])) {
601 $out .= '<input id="errormsg_' . $htmlname . '" value="' . $custommsg['error'] . '" type="hidden"/>' . "\n";
602 }
603 } else {
604 $out .= '<input id="successmsg_' . $htmlname . '" value="' . $custommsg . '" type="hidden"/>' . "\n";
605 }
606 }
607 if ($inputType == 'textarea') {
608 $out .= '<input id="textarea_' . $htmlname . '_rows" value="' . $rows . '" type="hidden"/>' . "\n";
609 $out .= '<input id="textarea_' . $htmlname . '_cols" value="' . $cols . '" type="hidden"/>' . "\n";
610 }
611 $out .= '<span id="viewval_' . $htmlname . '" class="viewval_' . $inputType . ($button_only ? ' inactive' : ' active') . '">' . $value . '</span>' . "\n";
612 $out .= '<span id="editval_' . $htmlname . '" class="editval_' . $inputType . ($button_only ? ' inactive' : ' active') . ' hideobject">' . (!empty($editvalue) ? $editvalue : $value) . '</span>' . "\n";
613 } else {
614 $out = $value;
615 }
616
617 return $out;
618 }
619
638 public function textwithtooltip($text, $htmltext, $tooltipon = 1, $direction = 0, $img = '', $extracss = '', $notabs = 3, $incbefore = '', $noencodehtmltext = 0, $tooltiptrigger = '', $forcenowrap = 0)
639 {
640 if ($incbefore) {
641 $text = $incbefore . $text;
642 }
643 if (!$htmltext) {
644 return $text;
645 }
646 $direction = (int) $direction; // For backward compatibility when $direction was set to '' instead of 0
647
648 $tag = 'td';
649 if ($notabs == 2) {
650 $tag = 'div';
651 }
652 if ($notabs == 3) {
653 $tag = 'span';
654 }
655 // Sanitize tooltip
656 $htmltext = str_replace(array("\r", "\n"), '', $htmltext);
657
658 $extrastyle = '';
659 if ($direction < 0) {
660 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
661 $extrastyle = 'padding: 0px; padding-left: 3px;';
662 }
663 if ($direction > 0) {
664 $extracss = ($extracss ? $extracss . ' ' : '') . ($notabs != 3 ? 'inline-block' : '');
665 $extrastyle = 'padding: 0px; padding-right: 3px;';
666 }
667
668 $classfortooltip = 'classfortooltip';
669
670 $s = '';
671 $textfordialog = '';
672
673 if ($tooltiptrigger == '') {
674 $htmltext = str_replace('"', '&quot;', $htmltext);
675 } else {
676 $classfortooltip = 'classfortooltiponclick';
677 $textfordialog .= '<div style="display: none;" id="idfortooltiponclick_' . $tooltiptrigger . '" class="classfortooltiponclicktext">' . $htmltext . '</div>';
678 }
679 if ($tooltipon == 2 || $tooltipon == 3) {
680 $paramfortooltipimg = ' class="' . $classfortooltip . ($notabs != 3 ? ' inline-block' : '') . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '"';
681 if ($tooltiptrigger == '') {
682 $paramfortooltipimg .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribut to put on img tag to store tooltip
683 } else {
684 $paramfortooltipimg .= ' dolid="' . $tooltiptrigger . '"';
685 }
686 } else {
687 $paramfortooltipimg = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribut to put on td text tag
688 }
689 if ($tooltipon == 1 || $tooltipon == 3) {
690 $paramfortooltiptd = ' class="' . ($tooltipon == 3 ? 'cursorpointer ' : '') . $classfortooltip . ' inline-block' . ($extracss ? ' ' . $extracss : '') . '" style="padding: 0px;' . ($extrastyle ? ' ' . $extrastyle : '') . '" ';
691 if ($tooltiptrigger == '') {
692 $paramfortooltiptd .= ' title="' . ($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)) . '"'; // Attribut to put on td tag to store tooltip
693 } else {
694 $paramfortooltiptd .= ' dolid="' . $tooltiptrigger . '"';
695 }
696 } else {
697 $paramfortooltiptd = ($extracss ? ' class="' . $extracss . '"' : '') . ($extrastyle ? ' style="' . $extrastyle . '"' : ''); // Attribut to put on td text tag
698 }
699 if (empty($notabs)) {
700 $s .= '<table class="nobordernopadding"><tr style="height: auto;">';
701 } elseif ($notabs == 2) {
702 $s .= '<div class="inline-block' . ($forcenowrap ? ' nowrap' : '') . '">';
703 }
704 // Define value if value is before
705 if ($direction < 0) {
706 $s .= '<' . $tag . $paramfortooltipimg;
707 if ($tag == 'td') {
708 $s .= ' class="valigntop" width="14"';
709 }
710 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
711 }
712 // Use another method to help avoid having a space in value in order to use this value with jquery
713 // Define label
714 if ((string) $text != '') {
715 $s .= '<' . $tag . $paramfortooltiptd . '>' . $text . '</' . $tag . '>';
716 }
717 // Define value if value is after
718 if ($direction > 0) {
719 $s .= '<' . $tag . $paramfortooltipimg;
720 if ($tag == 'td') {
721 $s .= ' class="valignmiddle" width="14"';
722 }
723 $s .= '>' . $textfordialog . $img . '</' . $tag . '>';
724 }
725 if (empty($notabs)) {
726 $s .= '</tr></table>';
727 } elseif ($notabs == 2) {
728 $s .= '</div>';
729 }
730
731 return $s;
732 }
733
748 public function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 3, $tooltiptrigger = '', $forcenowrap = 0)
749 {
750 global $conf, $langs;
751
752 //For backwards compatibility
753 if ($type == '0') {
754 $type = 'info';
755 } elseif ($type == '1') {
756 $type = 'help';
757 }
758 // Clean parameters
759 $tooltiptrigger = preg_replace('/[^a-z0-9]/i', '', $tooltiptrigger);
760
761 if (preg_match('/onsmartphone$/', $tooltiptrigger) && empty($conf->dol_no_mouse_hover)) {
762 $tooltiptrigger = preg_replace('/^.*onsmartphone$/', '', $tooltiptrigger);
763 }
764 $alt = '';
765 if ($tooltiptrigger) {
766 $alt = $langs->transnoentitiesnoconv("ClickToShowHelp");
767 }
768
769 // If info or help with no javascript, show only text
770 if (empty($conf->use_javascript_ajax)) {
771 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
772 return $text;
773 } else {
774 $alt = $htmltext;
775 $htmltext = '';
776 }
777 }
778
779 // If info or help with smartphone, show only text (tooltip hover can't works)
780 if (!empty($conf->dol_no_mouse_hover) && empty($tooltiptrigger)) {
781 if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') {
782 return $text;
783 }
784 }
785 // If info or help with smartphone, show only text (tooltip on click does not works with dialog on smaprtphone)
786 //if (!empty($conf->dol_no_mouse_hover) && !empty($tooltiptrigger))
787 //{
788 //if ($type == 'info' || $type == 'help') return '<a href="'..'">'.$text.'</a>';
789 //}
790
791 $img = '';
792 if ($type == 'info') {
793 $img = img_help(0, $alt);
794 } elseif ($type == 'help') {
795 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
796 } elseif ($type == 'helpclickable') {
797 $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
798 } elseif ($type == 'superadmin') {
799 $img = img_picto($alt, 'redstar');
800 } elseif ($type == 'admin') {
801 $img = img_picto($alt, 'star');
802 } elseif ($type == 'warning') {
803 $img = img_warning($alt);
804 } elseif ($type != 'none') {
805 $img = img_picto($alt, $type); // $type can be an image path
806 }
807
808 return $this->textwithtooltip($text, $htmltext, ((($tooltiptrigger && !$img) || strpos($type, 'clickable')) ? 3 : 2), $direction, $img, $extracss, $notabs, '', $noencodehtmltext, $tooltiptrigger, $forcenowrap);
809 }
810
821 public function selectMassAction($selected, $arrayofaction, $alwaysvisible = 0, $name = 'massaction', $cssclass = 'checkforselect')
822 {
823 global $conf, $langs, $hookmanager;
824
825 $disabled = 0;
826 $ret = '<div class="centpercent center">';
827 $ret .= '<select class="flat' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'select valignmiddle alignstart" id="' . $name . '" name="' . $name . '"' . ($disabled ? ' disabled="disabled"' : '') . '>';
828
829 // Complete list with data from external modules. THe module can use $_SERVER['PHP_SELF'] to know on which page we are, or use the $parameters['currentcontext'] completed by executeHooks.
830 $parameters = array();
831 $reshook = $hookmanager->executeHooks('addMoreMassActions', $parameters); // Note that $action and $object may have been modified by hook
832 // check if there is a mass action
833
834 if (is_array($arrayofaction) && count($arrayofaction) == 0 && empty($hookmanager->resPrint)) {
835 return;
836 }
837 if (empty($reshook)) {
838 $ret .= '<option value="0"' . ($disabled ? ' disabled="disabled"' : '') . '>-- ' . $langs->trans("SelectAction") . ' --</option>';
839 if (is_array($arrayofaction)) {
840 foreach ($arrayofaction as $code => $label) {
841 $ret .= '<option value="' . $code . '"' . ($disabled ? ' disabled="disabled"' : '') . ' data-html="' . dol_escape_htmltag($label) . '">' . $label . '</option>';
842 }
843 }
844 }
845 $ret .= $hookmanager->resPrint;
846
847 $ret .= '</select>';
848
849 if (empty($conf->dol_optimize_smallscreen)) {
850 $ret .= ajax_combobox('.' . $name . 'select');
851 }
852
853 // Warning: if you set submit button to disabled, post using 'Enter' will no more work if there is no another input submit. So we add a hidden button
854 $ret .= '<input type="submit" name="confirmmassactioninvisible" style="display: none" tabindex="-1">'; // Hidden button BEFORE so it is the one used when we submit with ENTER.
855 $ret .= '<input type="submit" disabled name="confirmmassaction"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display: none"') . ' class="reposition button smallpaddingimp' . (empty($conf->use_javascript_ajax) ? '' : ' hideobject') . ' ' . $name . ' ' . $name . 'confirmed" value="' . dol_escape_htmltag($langs->trans("Confirm")) . '">';
856 $ret .= '</div>';
857
858 if (!empty($conf->use_javascript_ajax)) {
859 $ret .= '<!-- JS CODE TO ENABLE mass action select -->
860 <script nonce="' . getNonce() . '">
861 function initCheckForSelect(mode, name, cssclass) /* mode is 0 during init of page or click all, 1 when we click on 1 checkboxi, "name" refers to the class of the massaction button, "cssclass" to the class of the checkfor select boxes */
862 {
863 atleastoneselected=0;
864 jQuery("."+cssclass).each(function( index ) {
865 /* console.log( index + ": " + $( this ).text() ); */
866 if ($(this).is(\':checked\')) atleastoneselected++;
867 });
868
869 console.log("initCheckForSelect mode="+mode+" name="+name+" cssclass="+cssclass+" atleastoneselected="+atleastoneselected);
870
871 if (atleastoneselected || ' . $alwaysvisible . ')
872 {
873 jQuery("."+name).show();
874 ' . ($selected ? 'if (atleastoneselected) { jQuery("."+name+"select").val("' . $selected . '").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', false); }' : '') . '
875 ' . ($selected ? 'if (! atleastoneselected) { jQuery("."+name+"select").val("0").trigger(\'change\'); jQuery("."+name+"confirmed").prop(\'disabled\', true); } ' : '') . '
876 }
877 else
878 {
879 jQuery("."+name).hide();
880 jQuery("."+name+"other").hide();
881 }
882 }
883
884 jQuery(document).ready(function () {
885 initCheckForSelect(0, "' . $name . '", "' . $cssclass . '");
886 jQuery(".' . $cssclass . '").click(function() {
887 initCheckForSelect(1, "' . $name . '", "' . $cssclass . '");
888 });
889 jQuery(".' . $name . 'select").change(function() {
890 var massaction = $( this ).val();
891 var urlform = $( this ).closest("form").attr("action").replace("#show_files","");
892 if (massaction == "builddoc")
893 {
894 urlform = urlform + "#show_files";
895 }
896 $( this ).closest("form").attr("action", urlform);
897 console.log("we select a mass action name=' . $name . ' massaction="+massaction+" - "+urlform);
898 /* Warning: if you set submit button to disabled, post using Enter will no more work if there is no other button */
899 if ($(this).val() != \'0\')
900 {
901 jQuery(".' . $name . 'confirmed").prop(\'disabled\', false);
902 jQuery(".' . $name . 'other").hide(); /* To disable if another div was open */
903 jQuery(".' . $name . '"+massaction).show();
904 }
905 else
906 {
907 jQuery(".' . $name . 'confirmed").prop(\'disabled\', true);
908 jQuery(".' . $name . 'other").hide(); /* To disable any div open */
909 }
910 });
911 });
912 </script>
913 ';
914 }
915
916 return $ret;
917 }
918
919 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
920
937 public function select_country($selected = '', $htmlname = 'country_id', $htmloption = '', $maxlength = 0, $morecss = 'minwidth300', $usecodeaskey = '', $showempty = 1, $disablefavorites = 0, $addspecialentries = 0, $exclude_country_code = array(), $hideflags = 0)
938 {
939 // phpcs:enable
940 global $conf, $langs, $mysoc;
941
942 $langs->load("dict");
943
944 $out = '';
945 $countryArray = array();
946 $favorite = array();
947 $label = array();
948 $atleastonefavorite = 0;
949
950 $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite, eec";
951 $sql .= " FROM " . $this->db->prefix() . "c_country";
952 $sql .= " WHERE active > 0";
953 //$sql.= " ORDER BY code ASC";
954
955 dol_syslog(get_class($this) . "::select_country", LOG_DEBUG);
956 $resql = $this->db->query($sql);
957 if ($resql) {
958 $out .= '<select id="select' . $htmlname . '" class="flat maxwidth200onsmartphone selectcountry' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" ' . $htmloption . '>';
959 $num = $this->db->num_rows($resql);
960 $i = 0;
961 if ($num) {
962 while ($i < $num) {
963 $obj = $this->db->fetch_object($resql);
964
965 $countryArray[$i]['rowid'] = $obj->rowid;
966 $countryArray[$i]['code_iso'] = $obj->code_iso;
967 $countryArray[$i]['code_iso3'] = $obj->code_iso3;
968 $countryArray[$i]['label'] = ($obj->code_iso && $langs->transnoentitiesnoconv("Country" . $obj->code_iso) != "Country" . $obj->code_iso ? $langs->transnoentitiesnoconv("Country" . $obj->code_iso) : ($obj->label != '-' ? $obj->label : ''));
969 $countryArray[$i]['favorite'] = $obj->favorite;
970 $countryArray[$i]['eec'] = $obj->eec;
971 $favorite[$i] = $obj->favorite;
972 $label[$i] = dol_string_unaccent($countryArray[$i]['label']);
973 $i++;
974 }
975
976 if (empty($disablefavorites)) {
977 $array1_sort_order = SORT_DESC;
978 $array2_sort_order = SORT_ASC;
979 array_multisort($favorite, $array1_sort_order, $label, $array2_sort_order, $countryArray);
980 } else {
981 $countryArray = dol_sort_array($countryArray, 'label');
982 }
983
984 if ($showempty) {
985 if (is_numeric($showempty)) {
986 $out .= '<option value="">&nbsp;</option>' . "\n";
987 } else {
988 $out .= '<option value="-1">' . $langs->trans($showempty) . '</option>' . "\n";
989 }
990 }
991
992 if ($addspecialentries) { // Add dedicated entries for groups of countries
993 //if ($showempty) $out.= '<option value="" disabled class="selectoptiondisabledwhite">--------------</option>';
994 $out .= '<option value="special_allnotme"' . ($selected == 'special_allnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
995 $out .= '<option value="special_eec"' . ($selected == 'special_eec' ? ' selected' : '') . '>' . $langs->trans("CountriesInEEC") . '</option>';
996 if ($mysoc->isInEEC()) {
997 $out .= '<option value="special_eecnotme"' . ($selected == 'special_eecnotme' ? ' selected' : '') . '>' . $langs->trans("CountriesInEECExceptMe", $langs->transnoentitiesnoconv("Country" . $mysoc->country_code)) . '</option>';
998 }
999 $out .= '<option value="special_noteec"' . ($selected == 'special_noteec' ? ' selected' : '') . '>' . $langs->trans("CountriesNotInEEC") . '</option>';
1000 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1001 }
1002
1003 foreach ($countryArray as $row) {
1004 //if (empty($showempty) && empty($row['rowid'])) continue;
1005 if (empty($row['rowid'])) {
1006 continue;
1007 }
1008 if (is_array($exclude_country_code) && count($exclude_country_code) && in_array($row['code_iso'], $exclude_country_code)) {
1009 continue; // exclude some countries
1010 }
1011
1012 if (empty($disablefavorites) && $row['favorite'] && $row['code_iso']) {
1013 $atleastonefavorite++;
1014 }
1015 if (empty($row['favorite']) && $atleastonefavorite) {
1016 $atleastonefavorite = 0;
1017 $out .= '<option value="" disabled class="selectoptiondisabledwhite">------------</option>';
1018 }
1019
1020 $labeltoshow = '';
1021 if ($row['label']) {
1022 $labeltoshow .= dol_trunc($row['label'], $maxlength, 'middle');
1023 } else {
1024 $labeltoshow .= '&nbsp;';
1025 }
1026 if ($row['code_iso']) {
1027 $labeltoshow .= ' <span class="opacitymedium">(' . $row['code_iso'] . ')</span>';
1028 if (empty($hideflags)) {
1029 $tmpflag = picto_from_langcode($row['code_iso'], 'class="saturatemedium paddingrightonly"', 1);
1030 $labeltoshow = $tmpflag . ' ' . $labeltoshow;
1031 }
1032 }
1033
1034 if ($selected && $selected != '-1' && ($selected == $row['rowid'] || $selected == $row['code_iso'] || $selected == $row['code_iso3'] || $selected == $row['label'])) {
1035 $out .= '<option value="' . ($usecodeaskey ? ($usecodeaskey == 'code2' ? $row['code_iso'] : $row['code_iso3']) : $row['rowid']) . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '" data-eec="' . ((int) $row['eec']) . '">';
1036 } else {
1037 $out .= '<option value="' . ($usecodeaskey ? ($usecodeaskey == 'code2' ? $row['code_iso'] : $row['code_iso3']) : $row['rowid']) . '" data-html="' . dol_escape_htmltag($labeltoshow) . '" data-eec="' . ((int) $row['eec']) . '">';
1038 }
1039 $out .= $labeltoshow;
1040 $out .= '</option>' . "\n";
1041 }
1042 }
1043 $out .= '</select>';
1044 } else {
1045 dol_print_error($this->db);
1046 }
1047
1048 // Make select dynamic
1049 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1050 $out .= ajax_combobox('select' . $htmlname, array(), 0, 0, 'resolve');
1051
1052 return $out;
1053 }
1054
1055 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1056
1070 public function select_incoterms($selected = '', $location_incoterms = '', $page = '', $htmlname = 'incoterm_id', $htmloption = '', $forcecombo = 1, $events = array(), $disableautocomplete = 0)
1071 {
1072 // phpcs:enable
1073 global $conf, $langs;
1074
1075 $langs->load("dict");
1076
1077 $out = '';
1078 $moreattrib = '';
1079 $incotermArray = array();
1080
1081 $sql = "SELECT rowid, code";
1082 $sql .= " FROM " . $this->db->prefix() . "c_incoterms";
1083 $sql .= " WHERE active > 0";
1084 $sql .= " ORDER BY code ASC";
1085
1086 dol_syslog(get_class($this) . "::select_incoterm", LOG_DEBUG);
1087 $resql = $this->db->query($sql);
1088 if ($resql) {
1089 if ($conf->use_javascript_ajax && !$forcecombo) {
1090 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1091 $out .= ajax_combobox($htmlname, $events);
1092 }
1093
1094 if (!empty($page)) {
1095 $out .= '<form method="post" action="' . $page . '">';
1096 $out .= '<input type="hidden" name="action" value="set_incoterms">';
1097 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
1098 }
1099
1100 $out .= '<select id="' . $htmlname . '" class="flat selectincoterm width75" name="' . $htmlname . '" ' . $htmloption . '>';
1101 $out .= '<option value="0">&nbsp;</option>';
1102 $num = $this->db->num_rows($resql);
1103 $i = 0;
1104 if ($num) {
1105 while ($i < $num) {
1106 $obj = $this->db->fetch_object($resql);
1107 $incotermArray[$i]['rowid'] = $obj->rowid;
1108 $incotermArray[$i]['code'] = $obj->code;
1109 $i++;
1110 }
1111
1112 foreach ($incotermArray as $row) {
1113 if ($selected && ($selected == $row['rowid'] || $selected == $row['code'])) {
1114 $out .= '<option value="' . $row['rowid'] . '" selected>';
1115 } else {
1116 $out .= '<option value="' . $row['rowid'] . '">';
1117 }
1118
1119 if ($row['code']) {
1120 $out .= $row['code'];
1121 }
1122
1123 $out .= '</option>';
1124 }
1125 }
1126 $out .= '</select>';
1127
1128 if ($conf->use_javascript_ajax && empty($disableautocomplete)) {
1129 $out .= ajax_multiautocompleter('location_incoterms', array(), DOL_URL_ROOT . '/core/ajax/locationincoterms.php') . "\n";
1130 $moreattrib .= ' autocomplete="off"';
1131 }
1132 $out .= '<input id="location_incoterms" class="maxwidthonsmartphone type="text" name="location_incoterms" value="' . $location_incoterms . '">' . "\n";
1133
1134 if (!empty($page)) {
1135 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp nomargintop nomarginbottom" value="' . $langs->trans("Modify") . '"></form>';
1136 }
1137 } else {
1138 dol_print_error($this->db);
1139 }
1140
1141 return $out;
1142 }
1143
1144 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1145
1157 public function select_type_of_lines($selected = '', $htmlname = 'type', $showempty = 0, $hidetext = 0, $forceall = 0)
1158 {
1159 // phpcs:enable
1160 global $langs;
1161
1162 // If product & services are enabled or both disabled.
1163 if ($forceall == 1 || (empty($forceall) && isModEnabled("product") && isModEnabled("service"))
1164 || (empty($forceall) && !isModEnabled('product') && !isModEnabled('service'))) {
1165 if (empty($hidetext)) {
1166 print $langs->trans("Type") . ': ';
1167 }
1168 print '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
1169 if ($showempty) {
1170 print '<option value="-1"';
1171 if ($selected == -1) {
1172 print ' selected';
1173 }
1174 print '>&nbsp;</option>';
1175 }
1176
1177 print '<option value="0"';
1178 if (0 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'product')) {
1179 print ' selected';
1180 }
1181 print '>' . $langs->trans("Product");
1182
1183 print '<option value="1"';
1184 if (1 == $selected || ($selected == -1 && getDolGlobalString('MAIN_FREE_PRODUCT_CHECKED_BY_DEFAULT') == 'service')) {
1185 print ' selected';
1186 }
1187 print '>' . $langs->trans("Service");
1188
1189 print '</select>';
1190 print ajax_combobox('select_' . $htmlname);
1191 //if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1192 }
1193 if ((empty($forceall) && !isModEnabled('product') && isModEnabled("service")) || $forceall == 3) {
1194 print $langs->trans("Service");
1195 print '<input type="hidden" name="' . $htmlname . '" value="1">';
1196 }
1197 if ((empty($forceall) && isModEnabled("product") && !isModEnabled('service')) || $forceall == 2) {
1198 print $langs->trans("Product");
1199 print '<input type="hidden" name="' . $htmlname . '" value="0">';
1200 }
1201 if ($forceall < 0) { // This should happened only for contracts when both predefined product and service are disabled.
1202 print '<input type="hidden" name="' . $htmlname . '" value="1">'; // By default we set on service for contract. If CONTRACT_SUPPORT_PRODUCTS is set, forceall should be 1 not -1
1203 }
1204 }
1205
1206 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1207
1213 public function load_cache_types_fees()
1214 {
1215 // phpcs:enable
1216 global $langs;
1217
1218 $num = count($this->cache_types_fees);
1219 if ($num > 0) {
1220 return 0; // Cache already loaded
1221 }
1222
1223 dol_syslog(__METHOD__, LOG_DEBUG);
1224
1225 $langs->load("trips");
1226
1227 $sql = "SELECT c.code, c.label";
1228 $sql .= " FROM " . $this->db->prefix() . "c_type_fees as c";
1229 $sql .= " WHERE active > 0";
1230
1231 $resql = $this->db->query($sql);
1232 if ($resql) {
1233 $num = $this->db->num_rows($resql);
1234 $i = 0;
1235
1236 while ($i < $num) {
1237 $obj = $this->db->fetch_object($resql);
1238
1239 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
1240 $label = ($obj->code != $langs->trans($obj->code) ? $langs->trans($obj->code) : $langs->trans($obj->label));
1241 $this->cache_types_fees[$obj->code] = $label;
1242 $i++;
1243 }
1244
1245 asort($this->cache_types_fees);
1246
1247 return $num;
1248 } else {
1249 dol_print_error($this->db);
1250 return -1;
1251 }
1252 }
1253
1254 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1255
1264 public function select_type_fees($selected = '', $htmlname = 'type', $showempty = 0)
1265 {
1266 // phpcs:enable
1267 global $user, $langs;
1268
1269 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
1270
1271 $this->load_cache_types_fees();
1272
1273 print '<select id="select_' . $htmlname . '" class="flat" name="' . $htmlname . '">';
1274 if ($showempty) {
1275 print '<option value="-1"';
1276 if ($selected == -1) {
1277 print ' selected';
1278 }
1279 print '>&nbsp;</option>';
1280 }
1281
1282 foreach ($this->cache_types_fees as $key => $value) {
1283 print '<option value="' . $key . '"';
1284 if ($key == $selected) {
1285 print ' selected';
1286 }
1287 print '>';
1288 print $value;
1289 print '</option>';
1290 }
1291
1292 print '</select>';
1293 if ($user->admin) {
1294 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1295 }
1296 }
1297
1298
1299 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1300
1322 public function select_company($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $limit = 0, $morecss = 'minwidth100', $moreparam = '', $selected_input_value = '', $hidelabel = 1, $ajaxoptions = array(), $multiple = false, $excludeids = array(), $showcode = 0)
1323 {
1324 // phpcs:enable
1325 global $conf, $user, $langs;
1326
1327 $out = '';
1328
1329 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT') && !$forcecombo) {
1330 if (is_null($ajaxoptions)) {
1331 $ajaxoptions = array();
1332 }
1333
1334 require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1335
1336 // No immediate load of all database
1337 $placeholder = '';
1338 if ($selected && empty($selected_input_value)) {
1339 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1340 $societetmp = new Societe($this->db);
1341 $societetmp->fetch($selected);
1342 $selected_input_value = $societetmp->name;
1343 unset($societetmp);
1344 }
1345
1346 // mode 1
1347 $urloption = 'htmlname=' . urlencode(str_replace('.', '_', $htmlname)) . '&outjson=1&filter=' . urlencode($filter) . (empty($excludeids) ? '' : '&excludeids=' . join(',', $excludeids)) . ($showtype ? '&showtype=' . urlencode($showtype) : '') . ($showcode ? '&showcode=' . urlencode($showcode) : '');
1348
1349 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
1350 if (empty($hidelabel)) {
1351 print $langs->trans("RefOrLabel") . ' : ';
1352 } elseif ($hidelabel > 1) {
1353 $placeholder = $langs->trans("RefOrLabel");
1354 if ($hidelabel == 2) {
1355 $out .= img_picto($langs->trans("Search"), 'search');
1356 }
1357 }
1358 $out .= '<input type="text" class="' . $morecss . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '') . ' ' . (getDolGlobalString('THIRDPARTY_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
1359 if ($hidelabel == 3) {
1360 $out .= img_picto($langs->trans("Search"), 'search');
1361 }
1362
1363 $out .= ajax_event($htmlname, $events);
1364
1365 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/societe/ajax/company.php', $urloption, $conf->global->COMPANY_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
1366 } else {
1367 // Immediate load of all database
1368 $out .= $this->select_thirdparty_list($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, '', 0, $limit, $morecss, $moreparam, $multiple, $excludeids, $showcode);
1369 }
1370
1371 return $out;
1372 }
1373
1374 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1375
1399 public function select_thirdparty_list($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $filterkey = '', $outputmode = 0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $multiple = false, $excludeids = array(), $showcode = 0)
1400 {
1401 // phpcs:enable
1402 global $conf, $user, $langs;
1403 global $hookmanager;
1404
1405 $out = '';
1406 $num = 0;
1407 $outarray = array();
1408
1409 if ($selected === '') {
1410 $selected = array();
1411 } elseif (!is_array($selected)) {
1412 $selected = array($selected);
1413 }
1414
1415 // Clean $filter that may contains sql conditions so sql code
1416 if (function_exists('testSqlAndScriptInject')) {
1417 if (testSqlAndScriptInject($filter, 3) > 0) {
1418 $filter = '';
1419 return 'SQLInjectionTryDetected';
1420 }
1421 }
1422
1423 if ($filter != '') { // If a filter was provided
1424 if (preg_match('/[\‍(\‍)]/', $filter)) {
1425 // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax.
1426 $errormsg = '';
1427 $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1);
1428
1429 // Redo clean $filter that may contains sql conditions so sql code
1430 if (function_exists('testSqlAndScriptInject')) {
1431 if (testSqlAndScriptInject($filter, 3) > 0) {
1432 $filter = '';
1433 return 'SQLInjectionTryDetected';
1434 }
1435 }
1436 } else {
1437 // If not, we do nothing. We already know that there is no parenthesis
1438 // TODO Disallow this case in a future.
1439 dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Syntax.", LOG_WARNING);
1440 }
1441 }
1442
1443 // We search companies
1444 $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.tva_intra, s.client, s.fournisseur, s.code_client, s.code_fournisseur";
1445 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1446 $sql .= ", s.address, s.zip, s.town";
1447 $sql .= ", dictp.code as country_code";
1448 }
1449 $sql .= " FROM " . $this->db->prefix() . "societe as s";
1450 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1451 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_country as dictp ON dictp.rowid = s.fk_pays";
1452 }
1453 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
1454 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
1455 }
1456 $sql .= " WHERE s.entity IN (" . getEntity('societe') . ")";
1457 if (!empty($user->socid)) {
1458 $sql .= " AND s.rowid = " . ((int) $user->socid);
1459 }
1460 if ($filter) {
1461 // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria()
1462 // if not, by testSqlAndScriptInject() only.
1463 $sql .= " AND (" . $filter . ")";
1464 }
1465 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
1466 $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
1467 }
1468 if (getDolGlobalString('COMPANY_HIDE_INACTIVE_IN_COMBOBOX')) {
1469 $sql .= " AND s.status <> 0";
1470 }
1471 if (!empty($excludeids)) {
1472 $sql .= " AND s.rowid NOT IN (" . $this->db->sanitize(join(',', $excludeids)) . ")";
1473 }
1474 // Add where from hooks
1475 $parameters = array();
1476 $reshook = $hookmanager->executeHooks('selectThirdpartyListWhere', $parameters); // Note that $action and $object may have been modified by hook
1477 $sql .= $hookmanager->resPrint;
1478 // Add criteria
1479 if ($filterkey && $filterkey != '') {
1480 $sql .= " AND (";
1481 $prefix = !getDolGlobalString('COMPANY_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if COMPANY_DONOTSEARCH_ANYWHERE is on
1482 // For natural search
1483 $scrit = explode(' ', $filterkey);
1484 $i = 0;
1485 if (count($scrit) > 1) {
1486 $sql .= "(";
1487 }
1488 foreach ($scrit as $crit) {
1489 if ($i > 0) {
1490 $sql .= " AND ";
1491 }
1492 $sql .= "(s.nom LIKE '" . $this->db->escape($prefix . $crit) . "%')";
1493 $i++;
1494 }
1495 if (count($scrit) > 1) {
1496 $sql .= ")";
1497 }
1498 if (isModEnabled('barcode')) {
1499 $sql .= " OR s.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1500 }
1501 $sql .= " OR s.code_client LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.code_fournisseur LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1502 $sql .= " OR s.name_alias LIKE '" . $this->db->escape($prefix . $filterkey) . "%' OR s.tva_intra LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
1503 $sql .= ")";
1504 }
1505 $sql .= $this->db->order("nom", "ASC");
1506 $sql .= $this->db->plimit($limit, 0);
1507
1508 // Build output string
1509 dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
1510 $resql = $this->db->query($sql);
1511 if ($resql) {
1512 if (!$forcecombo) {
1513 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1514 $out .= ajax_combobox($htmlname, $events, getDolGlobalString("COMPANY_USE_SEARCH_TO_SELECT"));
1515 }
1516
1517 // Construct $out and $outarray
1518 $out .= '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($moreparam ? ' ' . $moreparam : '') . ' name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . '>' . "\n";
1519
1520 $textifempty = (($showempty && !is_numeric($showempty)) ? $langs->trans($showempty) : '');
1521 if (getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
1522 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
1523 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
1524 if ($showempty && !is_numeric($showempty)) {
1525 $textifempty = $langs->trans($showempty);
1526 } else {
1527 $textifempty .= $langs->trans("All");
1528 }
1529 }
1530 if ($showempty) {
1531 $out .= '<option value="-1" data-html="' . dol_escape_htmltag('<span class="opacitymedium">' . ($textifempty ? $textifempty : '&nbsp;') . '</span>') . '">' . $textifempty . '</option>' . "\n";
1532 }
1533
1534 $companytemp = new Societe($this->db);
1535
1536 $num = $this->db->num_rows($resql);
1537 $i = 0;
1538 if ($num) {
1539 while ($i < $num) {
1540 $obj = $this->db->fetch_object($resql);
1541 $label = '';
1542 if ($showcode || getDolGlobalString('SOCIETE_ADD_REF_IN_LIST')) {
1543 if (($obj->client) && (!empty($obj->code_client))) {
1544 $label = $obj->code_client . ' - ';
1545 }
1546 if (($obj->fournisseur) && (!empty($obj->code_fournisseur))) {
1547 $label .= $obj->code_fournisseur . ' - ';
1548 }
1549 $label .= ' ' . $obj->name;
1550 } else {
1551 $label = $obj->name;
1552 }
1553
1554 if (!empty($obj->name_alias)) {
1555 $label .= ' (' . $obj->name_alias . ')';
1556 }
1557
1558 if (getDolGlobalString('SOCIETE_SHOW_VAT_IN_LIST') && !empty($obj->tva_intra)) {
1559 $label .= ' - '.$obj->tva_intra;
1560 }
1561
1562 $labelhtml = $label;
1563
1564 if ($showtype) {
1565 $companytemp->id = $obj->rowid;
1566 $companytemp->client = $obj->client;
1567 $companytemp->fournisseur = $obj->fournisseur;
1568 $tmptype = $companytemp->getTypeUrl(1, '', 0, 'span');
1569 if ($tmptype) {
1570 $labelhtml .= ' ' . $tmptype;
1571 }
1572
1573 if ($obj->client || $obj->fournisseur) {
1574 $label .= ' (';
1575 }
1576 if ($obj->client == 1 || $obj->client == 3) {
1577 $label .= $langs->trans("Customer");
1578 }
1579 if ($obj->client == 2 || $obj->client == 3) {
1580 $label .= ($obj->client == 3 ? ', ' : '') . $langs->trans("Prospect");
1581 }
1582 if ($obj->fournisseur) {
1583 $label .= ($obj->client ? ', ' : '') . $langs->trans("Supplier");
1584 }
1585 if ($obj->client || $obj->fournisseur) {
1586 $label .= ')';
1587 }
1588 }
1589
1590 if (getDolGlobalString('COMPANY_SHOW_ADDRESS_SELECTLIST')) {
1591 $s = ($obj->address ? ' - ' . $obj->address : '') . ($obj->zip ? ' - ' . $obj->zip : '') . ($obj->town ? ' ' . $obj->town : '');
1592 if (!empty($obj->country_code)) {
1593 $s .= ', ' . $langs->trans('Country' . $obj->country_code);
1594 }
1595 $label .= $s;
1596 $labelhtml .= $s;
1597 }
1598
1599 if (empty($outputmode)) {
1600 if (in_array($obj->rowid, $selected)) {
1601 $out .= '<option value="' . $obj->rowid . '" selected data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1602 } else {
1603 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
1604 }
1605 } else {
1606 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label, 'labelhtml' => $labelhtml));
1607 }
1608
1609 $i++;
1610 if (($i % 10) == 0) {
1611 $out .= "\n";
1612 }
1613 }
1614 }
1615 $out .= '</select>' . "\n";
1616 } else {
1617 dol_print_error($this->db);
1618 }
1619
1620 $this->result = array('nbofthirdparties' => $num);
1621
1622 if ($outputmode) {
1623 return $outarray;
1624 }
1625 return $out;
1626 }
1627
1628
1629 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1630
1641 public function select_remises($selected, $htmlname, $filter, $socid, $maxvalue = 0)
1642 {
1643 // phpcs:enable
1644 global $langs, $conf;
1645
1646 // On recherche les remises
1647 $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
1648 $sql .= " re.description, re.fk_facture_source";
1649 $sql .= " FROM " . $this->db->prefix() . "societe_remise_except as re";
1650 $sql .= " WHERE re.fk_soc = " . (int) $socid;
1651 $sql .= " AND re.entity = " . $conf->entity;
1652 if ($filter) {
1653 $sql .= " AND " . $filter;
1654 }
1655 $sql .= " ORDER BY re.description ASC";
1656
1657 dol_syslog(get_class($this) . "::select_remises", LOG_DEBUG);
1658 $resql = $this->db->query($sql);
1659 if ($resql) {
1660 print '<select id="select_' . $htmlname . '" class="flat maxwidthonsmartphone" name="' . $htmlname . '">';
1661 $num = $this->db->num_rows($resql);
1662
1663 $qualifiedlines = $num;
1664
1665 $i = 0;
1666 if ($num) {
1667 print '<option value="0">&nbsp;</option>';
1668 while ($i < $num) {
1669 $obj = $this->db->fetch_object($resql);
1670 $desc = dol_trunc($obj->description, 40);
1671 if (preg_match('/\‍(CREDIT_NOTE\‍)/', $desc)) {
1672 $desc = preg_replace('/\‍(CREDIT_NOTE\‍)/', $langs->trans("CreditNote"), $desc);
1673 }
1674 if (preg_match('/\‍(DEPOSIT\‍)/', $desc)) {
1675 $desc = preg_replace('/\‍(DEPOSIT\‍)/', $langs->trans("Deposit"), $desc);
1676 }
1677 if (preg_match('/\‍(EXCESS RECEIVED\‍)/', $desc)) {
1678 $desc = preg_replace('/\‍(EXCESS RECEIVED\‍)/', $langs->trans("ExcessReceived"), $desc);
1679 }
1680 if (preg_match('/\‍(EXCESS PAID\‍)/', $desc)) {
1681 $desc = preg_replace('/\‍(EXCESS PAID\‍)/', $langs->trans("ExcessPaid"), $desc);
1682 }
1683
1684 $selectstring = '';
1685 if ($selected > 0 && $selected == $obj->rowid) {
1686 $selectstring = ' selected';
1687 }
1688
1689 $disabled = '';
1690 if ($maxvalue > 0 && $obj->amount_ttc > $maxvalue) {
1691 $qualifiedlines--;
1692 $disabled = ' disabled';
1693 }
1694
1695 if (getDolGlobalString('MAIN_SHOW_FACNUMBER_IN_DISCOUNT_LIST') && !empty($obj->fk_facture_source)) {
1696 $tmpfac = new Facture($this->db);
1697 if ($tmpfac->fetch($obj->fk_facture_source) > 0) {
1698 $desc = $desc . ' - ' . $tmpfac->ref;
1699 }
1700 }
1701
1702 print '<option value="' . $obj->rowid . '"' . $selectstring . $disabled . '>' . $desc . ' (' . price($obj->amount_ht) . ' ' . $langs->trans("HT") . ' - ' . price($obj->amount_ttc) . ' ' . $langs->trans("TTC") . ')</option>';
1703 $i++;
1704 }
1705 }
1706 print '</select>';
1707 print ajax_combobox('select_' . $htmlname);
1708
1709 return $qualifiedlines;
1710 } else {
1711 dol_print_error($this->db);
1712 return -1;
1713 }
1714 }
1715
1716 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1717
1738 public function select_contacts($socid, $selected = '', $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $showsoc = 0, $forcecombo = 0, $events = array(), $options_only = false, $moreparam = '', $htmlid = '')
1739 {
1740 // phpcs:enable
1741 print $this->selectcontacts($socid, $selected, $htmlname, $showempty, $exclude, $limitto, $showfunction, $morecss, $options_only, $showsoc, $forcecombo, $events, $moreparam, $htmlid);
1742 return $this->num;
1743 }
1744
1769 public function selectcontacts($socid, $selected = array(), $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $morecss = '', $options_only = false, $showsoc = 0, $forcecombo = 0, $events = array(), $moreparam = '', $htmlid = '', $multiple = false, $disableifempty = 0)
1770 {
1771 global $conf, $langs, $hookmanager, $action;
1772
1773 $langs->load('companies');
1774
1775 if (empty($htmlid)) {
1776 $htmlid = $htmlname;
1777 }
1778 $num = 0;
1779
1780 if ($selected === '') {
1781 $selected = array();
1782 } elseif (!is_array($selected)) {
1783 $selected = array($selected);
1784 }
1785 $out = '';
1786
1787 if (!is_object($hookmanager)) {
1788 include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
1789 $hookmanager = new HookManager($this->db);
1790 }
1791
1792 // We search third parties
1793 $sql = "SELECT sp.rowid, sp.lastname, sp.statut, sp.firstname, sp.poste, sp.email, sp.phone, sp.phone_perso, sp.phone_mobile, sp.town AS contact_town";
1794 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1795 $sql .= ", s.nom as company, s.town AS company_town";
1796 }
1797 $sql .= " FROM " . $this->db->prefix() . "socpeople as sp";
1798 if ($showsoc > 0 || getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1799 $sql .= " LEFT OUTER JOIN " . $this->db->prefix() . "societe as s ON s.rowid=sp.fk_soc";
1800 }
1801 $sql .= " WHERE sp.entity IN (" . getEntity('contact') . ")";
1802 if ($socid > 0 || $socid == -1) {
1803 $sql .= " AND sp.fk_soc = " . ((int) $socid);
1804 }
1805 if (getDolGlobalString('CONTACT_HIDE_INACTIVE_IN_COMBOBOX')) {
1806 $sql .= " AND sp.statut <> 0";
1807 }
1808 // Add where from hooks
1809 $parameters = array();
1810 $reshook = $hookmanager->executeHooks('selectContactListWhere', $parameters); // Note that $action and $object may have been modified by hook
1811 $sql .= $hookmanager->resPrint;
1812 $sql .= " ORDER BY sp.lastname ASC";
1813
1814 dol_syslog(get_class($this) . "::selectcontacts", LOG_DEBUG);
1815 $resql = $this->db->query($sql);
1816 if ($resql) {
1817 $num = $this->db->num_rows($resql);
1818
1819 if ($htmlname != 'none' && !$options_only) {
1820 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlid . '" name="' . $htmlname . (($num || empty($disableifempty)) ? '' : ' disabled') . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . (!empty($moreparam) ? $moreparam : '') . '>';
1821 }
1822
1823 if ($showempty && !is_numeric($showempty)) {
1824 $textforempty = $showempty;
1825 $out .= '<option class="optiongrey" value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>' . $textforempty . '</option>';
1826 } else {
1827 if (($showempty == 1 || ($showempty == 3 && $num > 1)) && !$multiple) {
1828 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>&nbsp;</option>';
1829 }
1830 if ($showempty == 2) {
1831 $out .= '<option value="0"' . (in_array(0, $selected) ? ' selected' : '') . '>-- ' . $langs->trans("Internal") . ' --</option>';
1832 }
1833 }
1834
1835 $i = 0;
1836 if ($num) {
1837 include_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1838 $contactstatic = new Contact($this->db);
1839
1840 while ($i < $num) {
1841 $obj = $this->db->fetch_object($resql);
1842
1843 // Set email (or phones) and town extended infos
1844 $extendedInfos = '';
1845 if (getDolGlobalString('CONTACT_SHOW_EMAIL_PHONE_TOWN_SELECTLIST')) {
1846 $extendedInfos = array();
1847 $email = trim($obj->email);
1848 if (!empty($email)) {
1849 $extendedInfos[] = $email;
1850 } else {
1851 $phone = trim($obj->phone);
1852 $phone_perso = trim($obj->phone_perso);
1853 $phone_mobile = trim($obj->phone_mobile);
1854 if (!empty($phone)) {
1855 $extendedInfos[] = $phone;
1856 }
1857 if (!empty($phone_perso)) {
1858 $extendedInfos[] = $phone_perso;
1859 }
1860 if (!empty($phone_mobile)) {
1861 $extendedInfos[] = $phone_mobile;
1862 }
1863 }
1864 $contact_town = trim($obj->contact_town);
1865 $company_town = trim($obj->company_town);
1866 if (!empty($contact_town)) {
1867 $extendedInfos[] = $contact_town;
1868 } elseif (!empty($company_town)) {
1869 $extendedInfos[] = $company_town;
1870 }
1871 $extendedInfos = implode(' - ', $extendedInfos);
1872 if (!empty($extendedInfos)) {
1873 $extendedInfos = ' - ' . $extendedInfos;
1874 }
1875 }
1876
1877 $contactstatic->id = $obj->rowid;
1878 $contactstatic->lastname = $obj->lastname;
1879 $contactstatic->firstname = $obj->firstname;
1880 if ($obj->statut == 1) {
1881 if ($htmlname != 'none') {
1882 $disabled = 0;
1883 if (is_array($exclude) && count($exclude) && in_array($obj->rowid, $exclude)) {
1884 $disabled = 1;
1885 }
1886 if (is_array($limitto) && count($limitto) && !in_array($obj->rowid, $limitto)) {
1887 $disabled = 1;
1888 }
1889 if (!empty($selected) && in_array($obj->rowid, $selected)) {
1890 $out .= '<option value="' . $obj->rowid . '"';
1891 if ($disabled) {
1892 $out .= ' disabled';
1893 }
1894 $out .= ' selected>';
1895 $out .= $contactstatic->getFullName($langs) . $extendedInfos;
1896 if ($showfunction && $obj->poste) {
1897 $out .= ' (' . $obj->poste . ')';
1898 }
1899 if (($showsoc > 0) && $obj->company) {
1900 $out .= ' - (' . $obj->company . ')';
1901 }
1902 $out .= '</option>';
1903 } else {
1904 $out .= '<option value="' . $obj->rowid . '"';
1905 if ($disabled) {
1906 $out .= ' disabled';
1907 }
1908 $out .= '>';
1909 $out .= $contactstatic->getFullName($langs) . $extendedInfos;
1910 if ($showfunction && $obj->poste) {
1911 $out .= ' (' . $obj->poste . ')';
1912 }
1913 if (($showsoc > 0) && $obj->company) {
1914 $out .= ' - (' . $obj->company . ')';
1915 }
1916 $out .= '</option>';
1917 }
1918 } else {
1919 if (in_array($obj->rowid, $selected)) {
1920 $out .= $contactstatic->getFullName($langs) . $extendedInfos;
1921 if ($showfunction && $obj->poste) {
1922 $out .= ' (' . $obj->poste . ')';
1923 }
1924 if (($showsoc > 0) && $obj->company) {
1925 $out .= ' - (' . $obj->company . ')';
1926 }
1927 }
1928 }
1929 }
1930 $i++;
1931 }
1932 } else {
1933 $labeltoshow = ($socid != -1) ? ($langs->trans($socid ? "NoContactDefinedForThirdParty" : "NoContactDefined")) : $langs->trans('SelectAThirdPartyFirst');
1934 $out .= '<option class="disabled" value="-1"' . (($showempty == 2 || $multiple) ? '' : ' selected') . ' disabled="disabled">';
1935 $out .= $labeltoshow;
1936 $out .= '</option>';
1937 }
1938
1939 $parameters = array(
1940 'socid' => $socid,
1941 'htmlname' => $htmlname,
1942 'resql' => $resql,
1943 'out' => &$out,
1944 'showfunction' => $showfunction,
1945 'showsoc' => $showsoc,
1946 );
1947
1948 $reshook = $hookmanager->executeHooks('afterSelectContactOptions', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1949
1950 if ($htmlname != 'none' && !$options_only) {
1951 $out .= '</select>';
1952 }
1953
1954 if ($conf->use_javascript_ajax && !$forcecombo && !$options_only) {
1955 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1956 $out .= ajax_combobox($htmlid, $events, getDolGlobalString("CONTACT_USE_SEARCH_TO_SELECT"));
1957 }
1958
1959 $this->num = $num;
1960 return $out;
1961 } else {
1962 dol_print_error($this->db);
1963 return -1;
1964 }
1965 }
1966
1967 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1968
1984 public function select_users($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0')
1985 {
1986 // phpcs:enable
1987 print $this->select_dolusers($selected, $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity);
1988 }
1989
1990 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1991
2016 public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '', $maxlength = 0, $showstatus = 0, $morefilter = '', $show_every = 0, $enableonlytext = '', $morecss = '', $notdisabled = 0, $outputmode = 0, $multiple = false, $forcecombo = 0)
2017 {
2018 // phpcs:enable
2019 global $conf, $user, $langs, $hookmanager;
2020 global $action;
2021
2022 // If no preselected user defined, we take current user
2023 if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && !getDolGlobalString('SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE')) {
2024 $selected = $user->id;
2025 }
2026
2027 if ($selected === '') {
2028 $selected = array();
2029 } elseif (!is_array($selected)) {
2030 $selected = array($selected);
2031 }
2032
2033 $excludeUsers = null;
2034 $includeUsers = null;
2035
2036 // Exclude some users
2037 if (is_array($exclude)) {
2038 $excludeUsers = implode(",", $exclude);
2039 }
2040 // Include some uses
2041 if (is_array($include)) {
2042 $includeUsers = implode(",", $include);
2043 } elseif ($include == 'hierarchy') {
2044 // Build list includeUsers to have only hierarchy
2045 $includeUsers = implode(",", $user->getAllChildIds(0));
2046 } elseif ($include == 'hierarchyme') {
2047 // Build list includeUsers to have only hierarchy and current user
2048 $includeUsers = implode(",", $user->getAllChildIds(1));
2049 }
2050
2051 $out = '';
2052 $outarray = array();
2053 $outarray2 = array();
2054
2055 // Forge request to select users
2056 $sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut as status, u.login, u.admin, u.entity, u.photo";
2057 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
2058 $sql .= ", e.label";
2059 }
2060 $sql .= " FROM " . $this->db->prefix() . "user as u";
2061 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
2062 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid = u.entity";
2063 if (!empty($force_entity)) {
2064 $sql .= " WHERE u.entity IN (0, " . $this->db->sanitize($force_entity) . ")";
2065 } else {
2066 $sql .= " WHERE u.entity IS NOT NULL";
2067 }
2068 } else {
2069 if (isModEnabled('multicompany') && getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE')) {
2070 $sql .= " WHERE u.rowid IN (SELECT ug.fk_user FROM ".$this->db->prefix()."usergroup_user as ug WHERE ug.entity IN (".getEntity('usergroup')."))";
2071 } else {
2072 $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
2073 }
2074 }
2075 if (!empty($user->socid)) {
2076 $sql .= " AND u.fk_soc = " . ((int) $user->socid);
2077 }
2078 if (is_array($exclude) && $excludeUsers) {
2079 $sql .= " AND u.rowid NOT IN (" . $this->db->sanitize($excludeUsers) . ")";
2080 }
2081 if ($includeUsers) {
2082 $sql .= " AND u.rowid IN (" . $this->db->sanitize($includeUsers) . ")";
2083 }
2084 if (getDolGlobalString('USER_HIDE_INACTIVE_IN_COMBOBOX') || $notdisabled) {
2085 $sql .= " AND u.statut <> 0";
2086 }
2087 if (!empty($morefilter)) {
2088 $sql .= " " . $morefilter;
2089 }
2090
2091 //Add hook to filter on user (for exemple on usergroup define in custom modules)
2092 $reshook = $hookmanager->executeHooks('addSQLWhereFilterOnSelectUsers', array(), $this, $action);
2093 if (!empty($reshook)) {
2094 $sql .= $hookmanager->resPrint;
2095 }
2096
2097 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) { // MAIN_FIRSTNAME_NAME_POSITION is 0 means firstname+lastname
2098 $sql .= " ORDER BY u.statut DESC, u.firstname ASC, u.lastname ASC";
2099 } else {
2100 $sql .= " ORDER BY u.statut DESC, u.lastname ASC, u.firstname ASC";
2101 }
2102
2103 dol_syslog(get_class($this) . "::select_dolusers", LOG_DEBUG);
2104
2105 $resql = $this->db->query($sql);
2106 if ($resql) {
2107 $num = $this->db->num_rows($resql);
2108 $i = 0;
2109 if ($num) {
2110 // do not use maxwidthonsmartphone by default. Set it by caller so auto size to 100% will work when not defined
2111 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : ' minwidth200') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
2112 if ($show_empty && !$multiple) {
2113 $textforempty = ' ';
2114 if (!empty($conf->use_javascript_ajax)) {
2115 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
2116 }
2117 if (!is_numeric($show_empty)) {
2118 $textforempty = $show_empty;
2119 }
2120 $out .= '<option class="optiongrey" value="' . ($show_empty < 0 ? $show_empty : -1) . '"' . ((empty($selected) || in_array(-1, $selected)) ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
2121 }
2122 if ($show_every) {
2123 $out .= '<option value="-2"' . ((in_array(-2, $selected)) ? ' selected' : '') . '>-- ' . $langs->trans("Everybody") . ' --</option>' . "\n";
2124 }
2125
2126 $userstatic = new User($this->db);
2127
2128 while ($i < $num) {
2129 $obj = $this->db->fetch_object($resql);
2130
2131 $userstatic->id = $obj->rowid;
2132 $userstatic->lastname = $obj->lastname;
2133 $userstatic->firstname = $obj->firstname;
2134 $userstatic->photo = $obj->photo;
2135 $userstatic->statut = $obj->status;
2136 $userstatic->entity = $obj->entity;
2137 $userstatic->admin = $obj->admin;
2138
2139 $disableline = '';
2140 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
2141 $disableline = ($enableonlytext ? $enableonlytext : '1');
2142 }
2143
2144 $labeltoshow = '';
2145 $labeltoshowhtml = '';
2146
2147 // $fullNameMode is 0=Lastname+Firstname (MAIN_FIRSTNAME_NAME_POSITION=1), 1=Firstname+Lastname (MAIN_FIRSTNAME_NAME_POSITION=0)
2148 $fullNameMode = 0;
2149 if (!getDolGlobalString('MAIN_FIRSTNAME_NAME_POSITION')) {
2150 $fullNameMode = 1; //Firstname+lastname
2151 }
2152 $labeltoshow .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2153 $labeltoshowhtml .= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
2154 if (empty($obj->firstname) && empty($obj->lastname)) {
2155 $labeltoshow .= $obj->login;
2156 $labeltoshowhtml .= $obj->login;
2157 }
2158
2159 // Complete name with a more info string like: ' (info1 - info2 - ...)'
2160 $moreinfo = '';
2161 $moreinfohtml = '';
2162 if (getDolGlobalString('MAIN_SHOW_LOGIN')) {
2163 $moreinfo .= ($moreinfo ? ' - ' : ' (');
2164 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(');
2165 $moreinfo .= $obj->login;
2166 $moreinfohtml .= $obj->login;
2167 }
2168 if ($showstatus >= 0) {
2169 if ($obj->status == 1 && $showstatus == 1) {
2170 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Enabled');
2171 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Enabled');
2172 }
2173 if ($obj->status == 0 && $showstatus == 1) {
2174 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans('Disabled');
2175 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans('Disabled');
2176 }
2177 }
2178 if (isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1 && !empty($user->admin) && empty($user->entity)) {
2179 if (empty($obj->entity)) {
2180 $moreinfo .= ($moreinfo ? ' - ' : ' (') . $langs->trans("AllEntities");
2181 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . $langs->trans("AllEntities");
2182 } else {
2183 if ($obj->entity != $conf->entity) {
2184 $moreinfo .= ($moreinfo ? ' - ' : ' (') . ($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2185 $moreinfohtml .= ($moreinfohtml ? ' - ' : ' <span class="opacitymedium">(') . ($obj->label ? $obj->label : $langs->trans("EntityNameNotDefined"));
2186 }
2187 }
2188 }
2189 $moreinfo .= (!empty($moreinfo) ? ')' : '');
2190 $moreinfohtml .= (!empty($moreinfohtml) ? ')</span>' : '');
2191 if (!empty($disableline) && $disableline != '1') {
2192 // Add text from $enableonlytext parameter
2193 $moreinfo .= ' - ' . $disableline;
2194 $moreinfohtml .= ' - ' . $disableline;
2195 }
2196 $labeltoshow .= $moreinfo;
2197 $labeltoshowhtml .= $moreinfohtml;
2198
2199 $out .= '<option value="' . $obj->rowid . '"';
2200 if (!empty($disableline)) {
2201 $out .= ' disabled';
2202 }
2203 if ((is_object($selected) && $selected->id == $obj->rowid) || (!is_object($selected) && in_array($obj->rowid, $selected))) {
2204 $out .= ' selected';
2205 }
2206 $out .= ' data-html="';
2207 $outhtml = $userstatic->getNomUrl(-3, '', 0, 1, 24, 1, 'login', '', 1) . ' ';
2208 if ($showstatus >= 0 && $obj->status == 0) {
2209 $outhtml .= '<strike class="opacitymediumxxx">';
2210 }
2211 $outhtml .= $labeltoshowhtml;
2212 if ($showstatus >= 0 && $obj->status == 0) {
2213 $outhtml .= '</strike>';
2214 }
2215 $out .= dol_escape_htmltag($outhtml);
2216 $out .= '">';
2217 $out .= $labeltoshow;
2218 $out .= '</option>';
2219
2220 $outarray[$userstatic->id] = $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength) . $moreinfo;
2221 $outarray2[$userstatic->id] = array(
2222 'id'=>$userstatic->id,
2223 'label'=>$labeltoshow,
2224 'labelhtml'=>$labeltoshowhtml,
2225 'color'=>'',
2226 'picto'=>''
2227 );
2228
2229 $i++;
2230 }
2231 } else {
2232 $out .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '" disabled>';
2233 $out .= '<option value="">' . $langs->trans("None") . '</option>';
2234 }
2235 $out .= '</select>';
2236
2237 if ($num && !$forcecombo) {
2238 // Enhance with select2
2239 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2240 $out .= ajax_combobox($htmlname);
2241 }
2242 } else {
2243 dol_print_error($this->db);
2244 }
2245
2246 if ($outputmode == 2) {
2247 return $outarray2;
2248 } elseif ($outputmode) {
2249 return $outarray;
2250 }
2251
2252 return $out;
2253 }
2254
2255
2256 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2279 public function select_dolusers_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = array(), $enableonly = array(), $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofuserid = array(), $listofcontactid = array(), $listofotherid = array())
2280 {
2281 // phpcs:enable
2282 global $langs;
2283
2284 $userstatic = new User($this->db);
2285 $out = '';
2286
2287 $assignedtouser = array();
2288 if (!empty($_SESSION['assignedtouser'])) {
2289 $assignedtouser = json_decode($_SESSION['assignedtouser'], true);
2290 }
2291 $nbassignetouser = count($assignedtouser);
2292
2293 //if ($nbassignetouser && $action != 'view') $out .= '<br>';
2294 if ($nbassignetouser) {
2295 $out .= '<ul class="attendees">';
2296 }
2297 $i = 0;
2298 $ownerid = 0;
2299 foreach ($assignedtouser as $key => $value) {
2300 if ($value['id'] == $ownerid) {
2301 continue;
2302 }
2303
2304 $out .= '<li>';
2305 $userstatic->fetch($value['id']);
2306 $out .= $userstatic->getNomUrl(-1);
2307 if ($i == 0) {
2308 $ownerid = $value['id'];
2309 $out .= ' (' . $langs->trans("Owner") . ')';
2310 }
2311 if ($nbassignetouser > 1 && $action != 'view') {
2312 $out .= ' <input type="image" style="border: 0px;" src="' . img_picto($langs->trans("Remove"), 'delete', '', 0, 1) . '" value="' . $userstatic->id . '" class="removedassigned reposition" id="removedassigned_' . $userstatic->id . '" name="removedassigned_' . $userstatic->id . '">';
2313 }
2314 // Show my availability
2315 if ($showproperties) {
2316 if ($ownerid == $value['id'] && is_array($listofuserid) && count($listofuserid) && in_array($ownerid, array_keys($listofuserid))) {
2317 $out .= '<div class="myavailability inline-block">';
2318 $out .= '<span class="hideonsmartphone">&nbsp;-&nbsp;<span class="opacitymedium">' . $langs->trans("Availability") . ':</span> </span><input id="transparency" class="paddingrightonly" ' . ($action == 'view' ? 'disabled' : '') . ' type="checkbox" name="transparency"' . ($listofuserid[$ownerid]['transparency'] ? ' checked' : '') . '><label for="transparency">' . $langs->trans("Busy") . '</label>';
2319 $out .= '</div>';
2320 }
2321 }
2322 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2323 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2324
2325 $out .= '</li>';
2326 $i++;
2327 }
2328 if ($nbassignetouser) {
2329 $out .= '</ul>';
2330 }
2331
2332 // Method with no ajax
2333 if ($action != 'view') {
2334 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassigned" value="">';
2335 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2336 $out .= 'jQuery(".removedassigned").click(function() { jQuery(".removedassignedhidden").val(jQuery(this).val()); });';
2337 $out .= 'jQuery(".assignedtouser").change(function() { console.log(jQuery(".assignedtouser option:selected").val());';
2338 $out .= ' if (jQuery(".assignedtouser option:selected").val() > 0) { jQuery("#' . $action . 'assignedtouser").attr("disabled", false); }';
2339 $out .= ' else { jQuery("#' . $action . 'assignedtouser").attr("disabled", true); }';
2340 $out .= '});';
2341 $out .= '})</script>';
2342 $out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2343 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtouser" name="' . $action . 'assignedtouser" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2344 $out .= '<br>';
2345 }
2346
2347 return $out;
2348 }
2349
2350 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2370 public function select_dolresources_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = array(), $enableonly = array(), $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofresourceid = array())
2371 {
2372 // phpcs:enable
2373 global $langs;
2374
2375 require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php';
2376 require_once DOL_DOCUMENT_ROOT.'/resource/class/dolresource.class.php';
2377 $formresources = new FormResource($this->db);
2378 $resourcestatic = new Dolresource($this->db);
2379
2380 $out = '';
2381 $assignedtoresource = array();
2382 if (!empty($_SESSION['assignedtoresource'])) {
2383 $assignedtoresource = json_decode($_SESSION['assignedtoresource'], true);
2384 }
2385 $nbassignetoresource = count($assignedtoresource);
2386
2387 //if ($nbassignetoresource && $action != 'view') $out .= '<br>';
2388 if ($nbassignetoresource) {
2389 $out .= '<ul class="attendees">';
2390 }
2391 $i = 0;
2392
2393 foreach ($assignedtoresource as $key => $value) {
2394 $out .= '<li>';
2395 $resourcestatic->fetch($value['id']);
2396 $out .= $resourcestatic->getNomUrl(-1);
2397 if ($nbassignetoresource > 1 && $action != 'view') {
2398 $out .= ' <input type="image" style="border: 0px;" src="' . img_picto($langs->trans("Remove"), 'delete', '', 0, 1) . '" value="' . $resourcestatic->id . '" class="removedassigned reposition" id="removedassignedresource_' . $resourcestatic->id . '" name="removedassignedresource_' . $resourcestatic->id . '">';
2399 }
2400 // Show my availability
2401 if ($showproperties) {
2402 if (is_array($listofresourceid) && count($listofresourceid)) {
2403 $out .= '<div class="myavailability inline-block">';
2404 $out .= '<span class="hideonsmartphone">&nbsp;-&nbsp;<span class="opacitymedium">' . $langs->trans("Availability") . ':</span> </span><input id="transparencyresource" class="paddingrightonly" ' . ($action == 'view' ? 'disabled' : '') . ' type="checkbox" name="transparency"' . ($listofresourceid[$value['id']]['transparency'] ? ' checked' : '') . '><label for="transparency">' . $langs->trans("Busy") . '</label>';
2405 $out .= '</div>';
2406 }
2407 }
2408 //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
2409 //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
2410
2411 $out .= '</li>';
2412 $i++;
2413 }
2414 if ($nbassignetoresource) {
2415 $out .= '</ul>';
2416 }
2417
2418 // Method with no ajax
2419 if ($action != 'view') {
2420 $out .= '<input type="hidden" class="removedassignedhidden" name="removedassignedresource" value="">';
2421 $out .= '<script nonce="' . getNonce() . '" type="text/javascript">jQuery(document).ready(function () {';
2422 $out .= 'jQuery(".removedassignedresource").click(function() { jQuery(".removedassignedresourcehidden").val(jQuery(this).val()); });';
2423 $out .= 'jQuery(".assignedtoresource").change(function() { console.log(jQuery(".assignedtoresource option:selected").val());';
2424 $out .= ' if (jQuery(".assignedtoresource option:selected").val() > 0) { jQuery("#' . $action . 'assignedtoresource").attr("disabled", false); }';
2425 $out .= ' else { jQuery("#' . $action . 'assignedtoresource").attr("disabled", true); }';
2426 $out .= '});';
2427 $out .= '})</script>';
2428
2429 $events = array();
2430 $out .= img_picto('', 'resource', 'class="pictofixedwidth"');
2431 $out .= $formresources->select_resource_list('', $htmlname, '', 1, 1, 0, $events, '', 2, null);
2432 //$out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
2433 $out .= ' <input type="submit" disabled class="button valignmiddle smallpaddingimp reposition" id="' . $action . 'assignedtoresource" name="' . $action . 'assignedtoresource" value="' . dol_escape_htmltag($langs->trans("Add")) . '">';
2434 $out .= '<br>';
2435 }
2436
2437 return $out;
2438 }
2439
2440 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2441
2469 public function select_produits($selected = 0, $htmlname = 'productid', $filtertype = '', $limit = 0, $price_level = 0, $status = 1, $finished = 2, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $selected_combinations = null, $nooutput = 0, $status_purchase = -1)
2470 {
2471 // phpcs:enable
2472 global $langs, $conf;
2473
2474 $out = '';
2475
2476 // check parameters
2477 $price_level = (!empty($price_level) ? $price_level : 0);
2478 if (is_null($ajaxoptions)) {
2479 $ajaxoptions = array();
2480 }
2481
2482 if (strval($filtertype) === '' && (isModEnabled("product") || isModEnabled("service"))) {
2483 if (isModEnabled("product") && !isModEnabled('service')) {
2484 $filtertype = '0';
2485 } elseif (!isModEnabled('product') && isModEnabled("service")) {
2486 $filtertype = '1';
2487 }
2488 }
2489
2490 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
2491 $placeholder = '';
2492
2493 if ($selected && empty($selected_input_value)) {
2494 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2495 $producttmpselect = new Product($this->db);
2496 $producttmpselect->fetch($selected);
2497 $selected_input_value = $producttmpselect->ref;
2498 unset($producttmpselect);
2499 }
2500 // handle case where product or service module is disabled + no filter specified
2501 if ($filtertype == '') {
2502 if (!isModEnabled('product')) { // when product module is disabled, show services only
2503 $filtertype = 1;
2504 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
2505 $filtertype = 0;
2506 }
2507 }
2508 // mode=1 means customers products
2509 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=1&status=' . $status . '&status_purchase=' . $status_purchase . '&finished=' . $finished . '&hidepriceinlabel=' . $hidepriceinlabel . '&warehousestatus=' . $warehouseStatus;
2510 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
2511
2512 if (isModEnabled('variants') && is_array($selected_combinations)) {
2513 // Code to automatically insert with javascript the select of attributes under the select of product
2514 // when a parent of variant has been selected.
2515 $out .= '
2516 <!-- script to auto show attributes select tags if a variant was selected -->
2517 <script nonce="' . getNonce() . '">
2518 // auto show attributes fields
2519 selected = ' . json_encode($selected_combinations) . ';
2520 combvalues = {};
2521
2522 jQuery(document).ready(function () {
2523
2524 jQuery("input[name=\'prod_entry_mode\']").change(function () {
2525 if (jQuery(this).val() == \'free\') {
2526 jQuery(\'div#attributes_box\').empty();
2527 }
2528 });
2529
2530 jQuery("input#' . $htmlname . '").change(function () {
2531
2532 if (!jQuery(this).val()) {
2533 jQuery(\'div#attributes_box\').empty();
2534 return;
2535 }
2536
2537 console.log("A change has started. We get variants fields to inject html select");
2538
2539 jQuery.getJSON("' . DOL_URL_ROOT . '/variants/ajax/getCombinations.php", {
2540 id: jQuery(this).val()
2541 }, function (data) {
2542 jQuery(\'div#attributes_box\').empty();
2543
2544 jQuery.each(data, function (key, val) {
2545
2546 combvalues[val.id] = val.values;
2547
2548 var span = jQuery(document.createElement(\'div\')).css({
2549 \'display\': \'table-row\'
2550 });
2551
2552 span.append(
2553 jQuery(document.createElement(\'div\')).text(val.label).css({
2554 \'font-weight\': \'bold\',
2555 \'display\': \'table-cell\'
2556 })
2557 );
2558
2559 var html = jQuery(document.createElement(\'select\')).attr(\'name\', \'combinations[\' + val.id + \']\').css({
2560 \'margin-left\': \'15px\',
2561 \'white-space\': \'pre\'
2562 }).append(
2563 jQuery(document.createElement(\'option\')).val(\'\')
2564 );
2565
2566 jQuery.each(combvalues[val.id], function (key, val) {
2567 var tag = jQuery(document.createElement(\'option\')).val(val.id).html(val.value);
2568
2569 if (selected[val.fk_product_attribute] == val.id) {
2570 tag.attr(\'selected\', \'selected\');
2571 }
2572
2573 html.append(tag);
2574 });
2575
2576 span.append(html);
2577 jQuery(\'div#attributes_box\').append(span);
2578 });
2579 })
2580 });
2581
2582 ' . ($selected ? 'jQuery("input#' . $htmlname . '").change();' : '') . '
2583 });
2584 </script>
2585 ';
2586 }
2587
2588 if (empty($hidelabel)) {
2589 $out .= $langs->trans("RefOrLabel") . ' : ';
2590 } elseif ($hidelabel > 1) {
2591 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
2592 if ($hidelabel == 2) {
2593 $out .= img_picto($langs->trans("Search"), 'search');
2594 }
2595 }
2596 $out .= '<input type="text" class="minwidth100' . ($morecss ? ' ' . $morecss : '') . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
2597 if ($hidelabel == 3) {
2598 $out .= img_picto($langs->trans("Search"), 'search');
2599 }
2600 } else {
2601 $out .= $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus, $status_purchase);
2602 }
2603
2604 if (empty($nooutput)) {
2605 print $out;
2606 } else {
2607 return $out;
2608 }
2609 }
2610
2611 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2612
2628 public function select_bom($selected = '', $htmlname = 'bom_id', $limit = 0, $status = 1, $type = 0, $showempty = '1', $morecss = '', $nooutput = '', $forcecombo = 0, $TProducts = [])
2629 {
2630 // phpcs:enable
2631 global $conf, $user, $langs, $db;
2632
2633 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2634
2635 $error = 0;
2636 $out = '';
2637
2638 if (!$forcecombo) {
2639 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2640 $events = array();
2641 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
2642 }
2643
2644 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
2645
2646 $sql = 'SELECT b.rowid, b.ref, b.label, b.fk_product';
2647 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'bom_bom as b';
2648 $sql .= ' WHERE b.entity IN (' . getEntity('bom') . ')';
2649 if (!empty($status)) {
2650 $sql .= ' AND status = ' . (int) $status;
2651 }
2652 if (!empty($type)) {
2653 $sql .= ' AND bomtype = ' . (int) $type;
2654 }
2655 if (!empty($TProducts)) {
2656 $sql .= ' AND fk_product IN (' . $this->db->sanitize(implode(',', $TProducts)) . ')';
2657 }
2658 if (!empty($limit)) {
2659 $sql .= ' LIMIT ' . (int) $limit;
2660 }
2661 $resql = $db->query($sql);
2662 if ($resql) {
2663 if ($showempty) {
2664 $out .= '<option value="-1"';
2665 if (empty($selected)) {
2666 $out .= ' selected';
2667 }
2668 $out .= '>&nbsp;</option>';
2669 }
2670 while ($obj = $db->fetch_object($resql)) {
2671 $product = new Product($db);
2672 $res = $product->fetch($obj->fk_product);
2673 $out .= '<option value="' . $obj->rowid . '"';
2674 if ($obj->rowid == $selected) {
2675 $out .= 'selected';
2676 }
2677 $out .= '>' . $obj->ref . ' - ' . $product->label . ' - ' . $obj->label . '</option>';
2678 }
2679 } else {
2680 $error++;
2681 dol_print_error($db);
2682 }
2683 $out .= '</select>';
2684 if (empty($nooutput)) {
2685 print $out;
2686 } else {
2687 return $out;
2688 }
2689 }
2690
2691 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2692
2718 public function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $status_purchase = -1)
2719 {
2720 // phpcs:enable
2721 global $langs, $conf;
2722 global $hookmanager;
2723
2724 $out = '';
2725 $outarray = array();
2726
2727 // Units
2728 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2729 $langs->load('other');
2730 }
2731
2732 $warehouseStatusArray = array();
2733 if (!empty($warehouseStatus)) {
2734 require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
2735 if (preg_match('/warehouseclosed/', $warehouseStatus)) {
2736 $warehouseStatusArray[] = Entrepot::STATUS_CLOSED;
2737 }
2738 if (preg_match('/warehouseopen/', $warehouseStatus)) {
2739 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL;
2740 }
2741 if (preg_match('/warehouseinternal/', $warehouseStatus)) {
2742 $warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL;
2743 }
2744 }
2745
2746 $selectFields = " p.rowid, p.ref, p.label, p.description, p.barcode, p.fk_country, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.default_vat_code, p.duration, p.fk_price_expression";
2747 if (count($warehouseStatusArray)) {
2748 $selectFieldsGrouped = ", sum(" . $this->db->ifsql("e.statut IS NULL", "0", "ps.reel") . ") as stock"; // e.statut is null if there is no record in stock
2749 } else {
2750 $selectFieldsGrouped = ", " . $this->db->ifsql("p.stock IS NULL", 0, "p.stock") . " AS stock";
2751 }
2752
2753 $sql = "SELECT ";
2754
2755 // Add select from hooks
2756 $parameters = array();
2757 $reshook = $hookmanager->executeHooks('selectProductsListSelect', $parameters); // Note that $action and $object may have been modified by hook
2758 if (empty($reshook)) {
2759 $sql .= $selectFields.$selectFieldsGrouped.$hookmanager->resPrint;
2760 } else {
2761 $sql .= $hookmanager->resPrint;
2762 }
2763
2764 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
2765 //Product category
2766 $sql .= ", (SELECT " . $this->db->prefix() . "categorie_product.fk_categorie
2767 FROM " . $this->db->prefix() . "categorie_product
2768 WHERE " . $this->db->prefix() . "categorie_product.fk_product=p.rowid
2769 LIMIT 1
2770 ) AS categorie_product_id ";
2771 }
2772
2773 //Price by customer
2774 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2775 $sql .= ', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
2776 $sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx, pcp.default_vat_code as custdefault_vat_code, pcp.ref_customer as custref';
2777 $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custdefault_vat_code, custref";
2778 }
2779 // Units
2780 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2781 $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units";
2782 $selectFields .= ', unit_long, unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units';
2783 }
2784
2785 // Multilang : we add translation
2786 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2787 $sql .= ", pl.label as label_translated";
2788 $sql .= ", pl.description as description_translated";
2789 $selectFields .= ", label_translated";
2790 $selectFields .= ", description_translated";
2791 }
2792 // Price by quantity
2793 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2794 $sql .= ", (SELECT pp.rowid FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid";
2795 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2796 $sql .= " AND price_level = " . ((int) $price_level);
2797 }
2798 $sql .= " ORDER BY date_price";
2799 $sql .= " DESC LIMIT 1) as price_rowid";
2800 $sql .= ", (SELECT pp.price_by_qty FROM " . $this->db->prefix() . "product_price as pp WHERE pp.fk_product = p.rowid"; // price_by_qty is 1 if some prices by qty exists in subtable
2801 if ($price_level >= 1 && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2802 $sql .= " AND price_level = " . ((int) $price_level);
2803 }
2804 $sql .= " ORDER BY date_price";
2805 $sql .= " DESC LIMIT 1) as price_by_qty";
2806 $selectFields .= ", price_rowid, price_by_qty";
2807 }
2808
2809 $sql .= " FROM ".$this->db->prefix()."product as p";
2810 // Add from (left join) from hooks
2811 $parameters = array();
2812 $reshook = $hookmanager->executeHooks('selectProductsListFrom', $parameters); // Note that $action and $object may have been modified by hook
2813 $sql .= $hookmanager->resPrint;
2814
2815 if (count($warehouseStatusArray)) {
2816 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_stock as ps on ps.fk_product = p.rowid";
2817 $sql .= " LEFT JOIN " . $this->db->prefix() . "entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (" . getEntity('stock') . ")";
2818 $sql .= ' AND e.statut IN (' . $this->db->sanitize($this->db->escape(implode(',', $warehouseStatusArray))) . ')'; // Return line if product is inside the selected stock. If not, an empty line will be returned so we will count 0.
2819 }
2820
2821 // include search in supplier ref
2822 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
2823 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
2824 }
2825
2826 //Price by customer
2827 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2828 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_customer_price as pcp ON pcp.fk_soc=" . ((int) $socid) . " AND pcp.fk_product=p.rowid";
2829 }
2830 // Units
2831 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
2832 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
2833 }
2834 // Multilang : we add translation
2835 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2836 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_lang as pl ON pl.fk_product = p.rowid ";
2837 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE') && !empty($socid)) {
2838 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
2839 $soc = new Societe($this->db);
2840 $result = $soc->fetch($socid);
2841 if ($result > 0 && !empty($soc->default_lang)) {
2842 $sql .= " AND pl.lang = '" . $this->db->escape($soc->default_lang) . "'";
2843 } else {
2844 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
2845 }
2846 } else {
2847 $sql .= " AND pl.lang = '" . $this->db->escape($langs->getDefaultLang()) . "'";
2848 }
2849 }
2850
2851 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
2852 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_attribute_combination pac ON pac.fk_product_child = p.rowid";
2853 }
2854
2855 $sql .= ' WHERE p.entity IN (' . getEntity('product') . ')';
2856
2857 if (getDolGlobalString('PRODUIT_ATTRIBUTES_HIDECHILD')) {
2858 $sql .= " AND pac.rowid IS NULL";
2859 }
2860
2861 if ($finished == 0) {
2862 $sql .= " AND p.finished = " . ((int) $finished);
2863 } elseif ($finished == 1) {
2864 $sql .= " AND p.finished = ".((int) $finished);
2865 }
2866 if ($status >= 0) {
2867 $sql .= " AND p.tosell = ".((int) $status);
2868 }
2869 if ($status_purchase >= 0) {
2870 $sql .= " AND p.tobuy = " . ((int) $status_purchase);
2871 }
2872 // Filter by product type
2873 if (strval($filtertype) != '') {
2874 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
2875 } elseif (!isModEnabled('product')) { // when product module is disabled, show services only
2876 $sql .= " AND p.fk_product_type = 1";
2877 } elseif (!isModEnabled('service')) { // when service module is disabled, show products only
2878 $sql .= " AND p.fk_product_type = 0";
2879 }
2880 // Add where from hooks
2881 $parameters = array();
2882 $reshook = $hookmanager->executeHooks('selectProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
2883 $sql .= $hookmanager->resPrint;
2884 // Add criteria on ref/label
2885 if ($filterkey != '') {
2886 $sql .= ' AND (';
2887 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
2888 // For natural search
2889 $scrit = explode(' ', $filterkey);
2890 $i = 0;
2891 if (count($scrit) > 1) {
2892 $sql .= "(";
2893 }
2894 foreach ($scrit as $crit) {
2895 if ($i > 0) {
2896 $sql .= " AND ";
2897 }
2898 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2899 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2900 $sql .= " OR pl.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2901 }
2902 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) {
2903 $sql .= " OR pcp.ref_customer LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2904 }
2905 if (getDolGlobalString('PRODUCT_AJAX_SEARCH_ON_DESCRIPTION')) {
2906 $sql .= " OR p.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2907 if (getDolGlobalInt('MAIN_MULTILANGS')) {
2908 $sql .= " OR pl.description LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2909 }
2910 }
2911 if (getDolGlobalString('MAIN_SEARCH_PRODUCT_BY_FOURN_REF')) {
2912 $sql .= " OR pfp.ref_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
2913 }
2914 $sql .= ")";
2915 $i++;
2916 }
2917 if (count($scrit) > 1) {
2918 $sql .= ")";
2919 }
2920 if (isModEnabled('barcode')) {
2921 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
2922 }
2923 $sql .= ')';
2924 }
2925 if (count($warehouseStatusArray)) {
2926 $sql .= " GROUP BY " . $selectFields;
2927 }
2928
2929 //Sort by category
2930 if (getDolGlobalString('PRODUCT_SORT_BY_CATEGORY')) {
2931 $sql .= " ORDER BY categorie_product_id ";
2932 //ASC OR DESC order
2933 (getDolGlobalInt('PRODUCT_SORT_BY_CATEGORY') == 1) ? $sql .= "ASC" : $sql .= "DESC";
2934 } else {
2935 $sql .= $this->db->order("p.ref");
2936 }
2937
2938 $sql .= $this->db->plimit($limit, 0);
2939
2940 // Build output string
2941 dol_syslog(get_class($this) . "::select_produits_list search products", LOG_DEBUG);
2942 $result = $this->db->query($sql);
2943 if ($result) {
2944 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
2945 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
2946 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
2947
2948 $num = $this->db->num_rows($result);
2949
2950 $events = null;
2951
2952 if (!$forcecombo) {
2953 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2954 $out .= ajax_combobox($htmlname, $events, getDolGlobalInt("PRODUIT_USE_SEARCH_TO_SELECT"));
2955 }
2956
2957 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
2958
2959 $textifempty = '';
2960 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
2961 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
2962 if (getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
2963 if ($showempty && !is_numeric($showempty)) {
2964 $textifempty = $langs->trans($showempty);
2965 } else {
2966 $textifempty .= $langs->trans("All");
2967 }
2968 } else {
2969 if ($showempty && !is_numeric($showempty)) {
2970 $textifempty = $langs->trans($showempty);
2971 }
2972 }
2973 if ($showempty) {
2974 $out .= '<option value="-1" selected>' . ($textifempty ? $textifempty : '&nbsp;') . '</option>';
2975 }
2976
2977 $i = 0;
2978 while ($num && $i < $num) {
2979 $opt = '';
2980 $optJson = array();
2981 $objp = $this->db->fetch_object($result);
2982
2983 if ((getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) && !empty($objp->price_by_qty) && $objp->price_by_qty == 1) { // Price by quantity will return many prices for the same product
2984 $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type";
2985 $sql .= " FROM " . $this->db->prefix() . "product_price_by_qty";
2986 $sql .= " WHERE fk_product_price = " . ((int) $objp->price_rowid);
2987 $sql .= " ORDER BY quantity ASC";
2988
2989 dol_syslog(get_class($this) . "::select_produits_list search prices by qty", LOG_DEBUG);
2990 $result2 = $this->db->query($sql);
2991 if ($result2) {
2992 $nb_prices = $this->db->num_rows($result2);
2993 $j = 0;
2994 while ($nb_prices && $j < $nb_prices) {
2995 $objp2 = $this->db->fetch_object($result2);
2996
2997 $objp->price_by_qty_rowid = $objp2->rowid;
2998 $objp->price_by_qty_price_base_type = $objp2->price_base_type;
2999 $objp->price_by_qty_quantity = $objp2->quantity;
3000 $objp->price_by_qty_unitprice = $objp2->unitprice;
3001 $objp->price_by_qty_remise_percent = $objp2->remise_percent;
3002 // For backward compatibility
3003 $objp->quantity = $objp2->quantity;
3004 $objp->price = $objp2->price;
3005 $objp->unitprice = $objp2->unitprice;
3006 $objp->remise_percent = $objp2->remise_percent;
3007
3008 //$objp->tva_tx is not overwritten by $objp2 value
3009 //$objp->default_vat_code is not overwritten by $objp2 value
3010
3011 $this->constructProductListOption($objp, $opt, $optJson, 0, $selected, $hidepriceinlabel, $filterkey);
3012
3013 $j++;
3014
3015 // Add new entry
3016 // "key" value of json key array is used by jQuery automatically as selected value
3017 // "label" value of json key array is used by jQuery automatically as text for combo box
3018 $out .= $opt;
3019 array_push($outarray, $optJson);
3020 }
3021 }
3022 } else {
3023 if (isModEnabled('dynamicprices') && !empty($objp->fk_price_expression)) {
3024 $price_product = new Product($this->db);
3025 $price_product->fetch($objp->rowid, '', '', 1);
3026
3027 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3028 $priceparser = new PriceParser($this->db);
3029 $price_result = $priceparser->parseProduct($price_product);
3030 if ($price_result >= 0) {
3031 $objp->price = $price_result;
3032 $objp->unitprice = $price_result;
3033 //Calculate the VAT
3034 $objp->price_ttc = price2num($objp->price) * (1 + ($objp->tva_tx / 100));
3035 $objp->price_ttc = price2num($objp->price_ttc, 'MU');
3036 }
3037 }
3038
3039 $this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected, $hidepriceinlabel, $filterkey);
3040 // Add new entry
3041 // "key" value of json key array is used by jQuery automatically as selected value
3042 // "label" value of json key array is used by jQuery automatically as text for combo box
3043 $out .= $opt;
3044 array_push($outarray, $optJson);
3045 }
3046
3047 $i++;
3048 }
3049
3050 $out .= '</select>';
3051
3052 $this->db->free($result);
3053
3054 if (empty($outputmode)) {
3055 return $out;
3056 }
3057
3058 return $outarray;
3059 } else {
3060 dol_print_error($this->db);
3061 }
3062
3063 return '';
3064 }
3065
3081 protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0)
3082 {
3083 global $langs, $conf, $user;
3084 global $hookmanager;
3085
3086 $outkey = '';
3087 $outval = '';
3088 $outref = '';
3089 $outlabel = '';
3090 $outlabel_translated = '';
3091 $outdesc = '';
3092 $outdesc_translated = '';
3093 $outbarcode = '';
3094 $outorigin = '';
3095 $outtype = '';
3096 $outprice_ht = '';
3097 $outprice_ttc = '';
3098 $outpricebasetype = '';
3099 $outtva_tx = '';
3100 $outdefault_vat_code = '';
3101 $outqty = 1;
3102 $outdiscount = 0;
3103
3104 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3105
3106 $label = $objp->label;
3107 if (!empty($objp->label_translated)) {
3108 $label = $objp->label_translated;
3109 }
3110 if (!empty($filterkey) && $filterkey != '') {
3111 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3112 }
3113
3114 $outkey = $objp->rowid;
3115 $outref = $objp->ref;
3116 $outrefcust = empty($objp->custref) ? '' : $objp->custref;
3117 $outlabel = $objp->label;
3118 $outdesc = $objp->description;
3119 if (getDolGlobalInt('MAIN_MULTILANGS')) {
3120 $outlabel_translated = $objp->label_translated;
3121 $outdesc_translated = $objp->description_translated;
3122 }
3123 $outbarcode = $objp->barcode;
3124 $outorigin = $objp->fk_country;
3125 $outpbq = empty($objp->price_by_qty_rowid) ? '' : $objp->price_by_qty_rowid;
3126
3127 $outtype = $objp->fk_product_type;
3128 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3129 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3130
3131 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3132 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
3133 }
3134
3135 // Units
3136 $outvalUnits = '';
3137 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3138 if (!empty($objp->unit_short)) {
3139 $outvalUnits .= ' - ' . $objp->unit_short;
3140 }
3141 }
3142 if (getDolGlobalString('PRODUCT_SHOW_DIMENSIONS_IN_COMBO')) {
3143 if (!empty($objp->weight) && $objp->weight_units !== null) {
3144 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3145 $outvalUnits .= ' - ' . $unitToShow;
3146 }
3147 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3148 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3149 $outvalUnits .= ' - ' . $unitToShow;
3150 }
3151 if (!empty($objp->surface) && $objp->surface_units !== null) {
3152 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3153 $outvalUnits .= ' - ' . $unitToShow;
3154 }
3155 if (!empty($objp->volume) && $objp->volume_units !== null) {
3156 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3157 $outvalUnits .= ' - ' . $unitToShow;
3158 }
3159 }
3160 if ($outdurationvalue && $outdurationunit) {
3161 $da = array(
3162 'h' => $langs->trans('Hour'),
3163 'd' => $langs->trans('Day'),
3164 'w' => $langs->trans('Week'),
3165 'm' => $langs->trans('Month'),
3166 'y' => $langs->trans('Year')
3167 );
3168 if (isset($da[$outdurationunit])) {
3169 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3170 }
3171 }
3172
3173 $opt = '<option value="' . $objp->rowid . '"';
3174 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
3175 if (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0) {
3176 $opt .= ' pbq="' . $objp->price_by_qty_rowid . '" data-pbq="' . $objp->price_by_qty_rowid . '" data-pbqup="' . $objp->price_by_qty_unitprice . '" data-pbqbase="' . $objp->price_by_qty_price_base_type . '" data-pbqqty="' . $objp->price_by_qty_quantity . '" data-pbqpercent="' . $objp->price_by_qty_remise_percent . '"';
3177 }
3178 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3179 if ($user->hasRight('stock', 'lire')) {
3180 if ($objp->stock > 0) {
3181 $opt .= ' class="product_line_stock_ok"';
3182 } elseif ($objp->stock <= 0) {
3183 $opt .= ' class="product_line_stock_too_low"';
3184 }
3185 }
3186 }
3187 if (getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
3188 $opt .= ' data-labeltrans="' . $outlabel_translated . '"';
3189 $opt .= ' data-desctrans="' . dol_escape_htmltag($outdesc_translated) . '"';
3190 }
3191 $opt .= '>';
3192 $opt .= $objp->ref;
3193 if (!empty($objp->custref)) {
3194 $opt .= ' (' . $objp->custref . ')';
3195 }
3196 if ($outbarcode) {
3197 $opt .= ' (' . $outbarcode . ')';
3198 }
3199 $opt .= ' - ' . dol_trunc($label, $maxlengtharticle);
3200 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3201 $opt .= ' (' . getCountry($outorigin, 1) . ')';
3202 }
3203
3204 $objRef = $objp->ref;
3205 if (!empty($objp->custref)) {
3206 $objRef .= ' (' . $objp->custref . ')';
3207 }
3208 if (!empty($filterkey) && $filterkey != '') {
3209 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3210 }
3211 $outval .= $objRef;
3212 if ($outbarcode) {
3213 $outval .= ' (' . $outbarcode . ')';
3214 }
3215 $outval .= ' - ' . dol_trunc($label, $maxlengtharticle);
3216 if ($outorigin && getDolGlobalString('PRODUCT_SHOW_ORIGIN_IN_COMBO')) {
3217 $outval .= ' (' . getCountry($outorigin, 1) . ')';
3218 }
3219
3220 // Units
3221 $opt .= $outvalUnits;
3222 $outval .= $outvalUnits;
3223
3224 $found = 0;
3225
3226 // Multiprice
3227 // If we need a particular price level (from 1 to n)
3228 if (empty($hidepriceinlabel) && $price_level >= 1 && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3229 $sql = "SELECT price, price_ttc, price_base_type, tva_tx, default_vat_code";
3230 $sql .= " FROM " . $this->db->prefix() . "product_price";
3231 $sql .= " WHERE fk_product = " . ((int) $objp->rowid);
3232 $sql .= " AND entity IN (" . getEntity('productprice') . ")";
3233 $sql .= " AND price_level = " . ((int) $price_level);
3234 $sql .= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid.
3235 $sql .= " LIMIT 1";
3236
3237 dol_syslog(get_class($this) . '::constructProductListOption search price for product ' . $objp->rowid . ' AND level ' . $price_level, LOG_DEBUG);
3238 $result2 = $this->db->query($sql);
3239 if ($result2) {
3240 $objp2 = $this->db->fetch_object($result2);
3241 if ($objp2) {
3242 $found = 1;
3243 if ($objp2->price_base_type == 'HT') {
3244 $opt .= ' - ' . price($objp2->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3245 $outval .= ' - ' . price($objp2->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3246 } else {
3247 $opt .= ' - ' . price($objp2->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3248 $outval .= ' - ' . price($objp2->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3249 }
3250 $outprice_ht = price($objp2->price);
3251 $outprice_ttc = price($objp2->price_ttc);
3252 $outpricebasetype = $objp2->price_base_type;
3253 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
3254 $outtva_tx = $objp2->tva_tx; // We use the vat rate on line of multiprice
3255 $outdefault_vat_code = $objp2->default_vat_code; // We use the vat code on line of multiprice
3256 } else {
3257 $outtva_tx = $objp->tva_tx; // We use the vat rate of product, not the one on line of multiprice
3258 $outdefault_vat_code = $objp->default_vat_code; // We use the vat code or product, not the one on line of multiprice
3259 }
3260 }
3261 } else {
3262 dol_print_error($this->db);
3263 }
3264 }
3265
3266 // Price by quantity
3267 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1 && (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES'))) {
3268 $found = 1;
3269 $outqty = $objp->quantity;
3270 $outdiscount = $objp->remise_percent;
3271 if ($objp->quantity == 1) {
3272 $opt .= ' - ' . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/";
3273 $outval .= ' - ' . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/";
3274 $opt .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3275 $outval .= $langs->transnoentities("Unit");
3276 } else {
3277 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3278 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3279 $opt .= $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3280 $outval .= $langs->transnoentities("Units");
3281 }
3282
3283 $outprice_ht = price($objp->unitprice);
3284 $outprice_ttc = price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
3285 $outpricebasetype = $objp->price_base_type;
3286 $outtva_tx = $objp->tva_tx; // This value is the value on product when constructProductListOption is called by select_produits_list even if other field $objp-> are from table price_by_qty
3287 $outdefault_vat_code = $objp->default_vat_code; // This value is the value on product when constructProductListOption is called by select_produits_list even if other field $objp-> are from table price_by_qty
3288 }
3289 if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1) {
3290 $opt .= " (" . price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3291 $outval .= " (" . price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3292 }
3293 if (empty($hidepriceinlabel) && !empty($objp->remise_percent) && $objp->remise_percent >= 1) {
3294 $opt .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3295 $outval .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3296 }
3297
3298 // Price by customer
3299 if (empty($hidepriceinlabel) && getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
3300 if (!empty($objp->idprodcustprice)) {
3301 $found = 1;
3302
3303 if ($objp->custprice_base_type == 'HT') {
3304 $opt .= ' - ' . price($objp->custprice, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3305 $outval .= ' - ' . price($objp->custprice, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3306 } else {
3307 $opt .= ' - ' . price($objp->custprice_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3308 $outval .= ' - ' . price($objp->custprice_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3309 }
3310
3311 $outprice_ht = price($objp->custprice);
3312 $outprice_ttc = price($objp->custprice_ttc);
3313 $outpricebasetype = $objp->custprice_base_type;
3314 $outtva_tx = $objp->custtva_tx;
3315 $outdefault_vat_code = $objp->custdefault_vat_code;
3316 }
3317 }
3318
3319 // If level no defined or multiprice not found, we used the default price
3320 if (empty($hidepriceinlabel) && !$found) {
3321 if ($objp->price_base_type == 'HT') {
3322 $opt .= ' - ' . price($objp->price, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("HT");
3323 $outval .= ' - ' . price($objp->price, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("HT");
3324 } else {
3325 $opt .= ' - ' . price($objp->price_ttc, 1, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->trans("TTC");
3326 $outval .= ' - ' . price($objp->price_ttc, 0, $langs, 0, 0, -1, $conf->currency) . ' ' . $langs->transnoentities("TTC");
3327 }
3328 $outprice_ht = price($objp->price);
3329 $outprice_ttc = price($objp->price_ttc);
3330 $outpricebasetype = $objp->price_base_type;
3331 $outtva_tx = $objp->tva_tx;
3332 $outdefault_vat_code = $objp->default_vat_code;
3333 }
3334
3335 if (isModEnabled('stock') && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3336 if ($user->hasRight('stock', 'lire')) {
3337 $opt .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'), 0, $langs, 0, 0);
3338
3339 if ($objp->stock > 0) {
3340 $outval .= ' - <span class="product_line_stock_ok">';
3341 } elseif ($objp->stock <= 0) {
3342 $outval .= ' - <span class="product_line_stock_too_low">';
3343 }
3344 $outval .= $langs->transnoentities("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3345 $outval .= '</span>';
3346 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3347 $langs->load("stocks");
3348
3349 $tmpproduct = new Product($this->db);
3350 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3351 $tmpproduct->load_virtual_stock();
3352 $virtualstock = $tmpproduct->stock_theorique;
3353
3354 $opt .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3355
3356 $outval .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3357 if ($virtualstock > 0) {
3358 $outval .= '<span class="product_line_stock_ok">';
3359 } elseif ($virtualstock <= 0) {
3360 $outval .= '<span class="product_line_stock_too_low">';
3361 }
3362 $outval .= $virtualstock;
3363 $outval .= '</span>';
3364
3365 unset($tmpproduct);
3366 }
3367 }
3368 }
3369
3370 $parameters = array('objp'=>$objp);
3371 $reshook = $hookmanager->executeHooks('constructProductListOption', $parameters); // Note that $action and $object may have been modified by hook
3372 if (empty($reshook)) {
3373 $opt .= $hookmanager->resPrint;
3374 } else {
3375 $opt = $hookmanager->resPrint;
3376 }
3377
3378 $opt .= "</option>\n";
3379 $optJson = array(
3380 'key' => $outkey,
3381 'value' => $outref,
3382 'label' => $outval,
3383 'label2' => $outlabel,
3384 'desc' => $outdesc,
3385 'type' => $outtype,
3386 'price_ht' => price2num($outprice_ht),
3387 'price_ttc' => price2num($outprice_ttc),
3388 'price_ht_locale' => price(price2num($outprice_ht)),
3389 'price_ttc_locale' => price(price2num($outprice_ttc)),
3390 'pricebasetype' => $outpricebasetype,
3391 'tva_tx' => $outtva_tx,
3392 'default_vat_code' => $outdefault_vat_code,
3393 'qty' => $outqty,
3394 'discount' => $outdiscount,
3395 'duration_value' => $outdurationvalue,
3396 'duration_unit' => $outdurationunit,
3397 'pbq' => $outpbq,
3398 'labeltrans' => $outlabel_translated,
3399 'desctrans' => $outdesc_translated,
3400 'ref_customer' => $outrefcust
3401 );
3402 }
3403
3404 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3405
3421 public function select_produits_fournisseurs($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $ajaxoptions = array(), $hidelabel = 0, $alsoproductwithnosupplierprice = 0, $morecss = '', $placeholder = '')
3422 {
3423 // phpcs:enable
3424 global $langs, $conf;
3425 global $price_level, $status, $finished;
3426
3427 if (!isset($status)) {
3428 $status = 1;
3429 }
3430
3431 $selected_input_value = '';
3432 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT')) {
3433 if ($selected > 0) {
3434 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
3435 $producttmpselect = new Product($this->db);
3436 $producttmpselect->fetch($selected);
3437 $selected_input_value = $producttmpselect->ref;
3438 unset($producttmpselect);
3439 }
3440
3441 // mode=2 means suppliers products
3442 $urloption = ($socid > 0 ? 'socid=' . $socid . '&' : '') . 'htmlname=' . $htmlname . '&outjson=1&price_level=' . $price_level . '&type=' . $filtertype . '&mode=2&status=' . $status . '&finished=' . $finished . '&alsoproductwithnosupplierprice=' . $alsoproductwithnosupplierprice;
3443 print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
3444
3445 print($hidelabel ? '' : $langs->trans("RefOrLabel") . ' : ') . '<input type="text" class="minwidth300" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . ($placeholder ? ' placeholder="' . $placeholder . '"' : '') . '>';
3446 } else {
3447 print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', $status, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder);
3448 }
3449 }
3450
3451 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3452
3471 public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '', $showstockinlist = 0, $placeholder = '')
3472 {
3473 // phpcs:enable
3474 global $langs, $conf, $user;
3475 global $hookmanager;
3476
3477 $out = '';
3478 $outarray = array();
3479
3480 $maxlengtharticle = (!getDolGlobalString('PRODUCT_MAX_LENGTH_COMBO') ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO);
3481
3482 $langs->load('stocks');
3483 // Units
3484 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3485 $langs->load('other');
3486 }
3487
3488 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, p.fk_product_type, p.stock, p.tva_tx as tva_tx_sale, p.default_vat_code as default_vat_code_sale,";
3489 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice";
3490 $sql .= ", pfp.multicurrency_code, pfp.multicurrency_unitprice";
3491 $sql .= ", pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.default_vat_code, pfp.fk_soc, s.nom as name";
3492 $sql .= ", pfp.supplier_reputation";
3493 // if we use supplier description of the products
3494 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3495 $sql .= ", pfp.desc_fourn as description";
3496 } else {
3497 $sql .= ", p.description";
3498 }
3499 // Units
3500 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3501 $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units";
3502 }
3503 if (isModEnabled('barcode')) {
3504 $sql .= ", pfp.barcode";
3505 }
3506 $sql .= " FROM " . $this->db->prefix() . "product as p";
3507 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (" . getEntity('product') . ") )";
3508 if ($socid > 0) {
3509 $sql .= " AND pfp.fk_soc = " . ((int) $socid);
3510 }
3511 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3512 // Units
3513 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3514 $sql .= " LEFT JOIN " . $this->db->prefix() . "c_units u ON u.rowid = p.fk_unit";
3515 }
3516 $sql .= " WHERE p.entity IN (" . getEntity('product') . ")";
3517 if ($statut != -1) {
3518 $sql .= " AND p.tobuy = " . ((int) $statut);
3519 }
3520 if (strval($filtertype) != '') {
3521 $sql .= " AND p.fk_product_type = " . ((int) $filtertype);
3522 }
3523 if (!empty($filtre)) {
3524 $sql .= " " . $filtre;
3525 }
3526 // Add where from hooks
3527 $parameters = array();
3528 $reshook = $hookmanager->executeHooks('selectSuppliersProductsListWhere', $parameters); // Note that $action and $object may have been modified by hook
3529 $sql .= $hookmanager->resPrint;
3530 // Add criteria on ref/label
3531 if ($filterkey != '') {
3532 $sql .= ' AND (';
3533 $prefix = !getDolGlobalString('PRODUCT_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
3534 // For natural search
3535 $scrit = explode(' ', $filterkey);
3536 $i = 0;
3537 if (count($scrit) > 1) {
3538 $sql .= "(";
3539 }
3540 foreach ($scrit as $crit) {
3541 if ($i > 0) {
3542 $sql .= " AND ";
3543 }
3544 $sql .= "(pfp.ref_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.label LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3545 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
3546 $sql .= " OR pfp.desc_fourn LIKE '" . $this->db->escape($prefix . $crit) . "%'";
3547 }
3548 $sql .= ")";
3549 $i++;
3550 }
3551 if (count($scrit) > 1) {
3552 $sql .= ")";
3553 }
3554 if (isModEnabled('barcode')) {
3555 $sql .= " OR p.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3556 $sql .= " OR pfp.barcode LIKE '" . $this->db->escape($prefix . $filterkey) . "%'";
3557 }
3558 $sql .= ')';
3559 }
3560 $sql .= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC";
3561 $sql .= $this->db->plimit($limit, 0);
3562
3563 // Build output string
3564
3565 dol_syslog(get_class($this) . "::select_produits_fournisseurs_list", LOG_DEBUG);
3566 $result = $this->db->query($sql);
3567 if ($result) {
3568 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3569 require_once DOL_DOCUMENT_ROOT . '/core/lib/product.lib.php';
3570
3571 $num = $this->db->num_rows($result);
3572
3573 //$out.='<select class="flat" id="select'.$htmlname.'" name="'.$htmlname.'">'; // remove select to have id same with combo and ajax
3574 $out .= '<select class="flat ' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '">';
3575 if (!$selected) {
3576 $out .= '<option value="-1" selected>' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3577 } else {
3578 $out .= '<option value="-1">' . ($placeholder ? $placeholder : '&nbsp;') . '</option>';
3579 }
3580
3581 $i = 0;
3582 while ($i < $num) {
3583 $objp = $this->db->fetch_object($result);
3584
3585 if (is_null($objp->idprodfournprice)) {
3586 // There is no supplier price found, we will use the vat rate for sale
3587 $objp->tva_tx = $objp->tva_tx_sale;
3588 $objp->default_vat_code = $objp->default_vat_code_sale;
3589 }
3590
3591 $outkey = $objp->idprodfournprice; // id in table of price
3592 if (!$outkey && $alsoproductwithnosupplierprice) {
3593 $outkey = 'idprod_' . $objp->rowid; // id of product
3594 }
3595
3596 $outref = $objp->ref;
3597 $outbarcode = $objp->barcode;
3598 $outqty = 1;
3599 $outdiscount = 0;
3600 $outtype = $objp->fk_product_type;
3601 $outdurationvalue = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : '';
3602 $outdurationunit = $outtype == Product::TYPE_SERVICE ? substr($objp->duration, -1) : '';
3603
3604 // Units
3605 $outvalUnits = '';
3606 if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
3607 if (!empty($objp->unit_short)) {
3608 $outvalUnits .= ' - ' . $objp->unit_short;
3609 }
3610 if (!empty($objp->weight) && $objp->weight_units !== null) {
3611 $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs);
3612 $outvalUnits .= ' - ' . $unitToShow;
3613 }
3614 if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) {
3615 $unitToShow = $objp->length . ' x ' . $objp->width . ' x ' . $objp->height . ' ' . measuringUnitString(0, 'size', $objp->length_units);
3616 $outvalUnits .= ' - ' . $unitToShow;
3617 }
3618 if (!empty($objp->surface) && $objp->surface_units !== null) {
3619 $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs);
3620 $outvalUnits .= ' - ' . $unitToShow;
3621 }
3622 if (!empty($objp->volume) && $objp->volume_units !== null) {
3623 $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs);
3624 $outvalUnits .= ' - ' . $unitToShow;
3625 }
3626 if ($outdurationvalue && $outdurationunit) {
3627 $da = array(
3628 'h' => $langs->trans('Hour'),
3629 'd' => $langs->trans('Day'),
3630 'w' => $langs->trans('Week'),
3631 'm' => $langs->trans('Month'),
3632 'y' => $langs->trans('Year')
3633 );
3634 if (isset($da[$outdurationunit])) {
3635 $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit] . ($outdurationvalue > 1 ? 's' : ''));
3636 }
3637 }
3638 }
3639
3640 $objRef = $objp->ref;
3641 if ($filterkey && $filterkey != '') {
3642 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
3643 }
3644 $objRefFourn = $objp->ref_fourn;
3645 if ($filterkey && $filterkey != '') {
3646 $objRefFourn = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRefFourn, 1);
3647 }
3648 $label = $objp->label;
3649 if ($filterkey && $filterkey != '') {
3650 $label = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $label, 1);
3651 }
3652
3653 switch ($objp->fk_product_type) {
3655 $picto = 'product';
3656 break;
3658 $picto = 'service';
3659 break;
3660 default:
3661 $picto = '';
3662 break;
3663 }
3664
3665 if (empty($picto)) {
3666 $optlabel = '';
3667 } else {
3668 $optlabel = img_object('', $picto, 'class="paddingright classfortooltip"', 0, 0, 1);
3669 }
3670
3671 $optlabel .= $objp->ref;
3672 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3673 $optlabel .= ' <span class="opacitymedium">(' . $objp->ref_fourn . ')</span>';
3674 }
3675 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3676 $optlabel .= ' (' . $outbarcode . ')';
3677 }
3678 $optlabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3679
3680 $outvallabel = $objRef;
3681 if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) {
3682 $outvallabel .= ' (' . $objRefFourn . ')';
3683 }
3684 if (isModEnabled('barcode') && !empty($objp->barcode)) {
3685 $outvallabel .= ' (' . $outbarcode . ')';
3686 }
3687 $outvallabel .= ' - ' . dol_trunc($label, $maxlengtharticle);
3688
3689 // Units
3690 $optlabel .= $outvalUnits;
3691 $outvallabel .= $outvalUnits;
3692
3693 if (!empty($objp->idprodfournprice)) {
3694 $outqty = $objp->quantity;
3695 $outdiscount = $objp->remise_percent;
3696 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3697 $prod_supplier = new ProductFournisseur($this->db);
3698 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3699 $prod_supplier->id = $objp->fk_product;
3700 $prod_supplier->fourn_qty = $objp->quantity;
3701 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3702 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3703
3704 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3705 $priceparser = new PriceParser($this->db);
3706 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3707 if ($price_result >= 0) {
3708 $objp->fprice = $price_result;
3709 if ($objp->quantity >= 1) {
3710 $objp->unitprice = $objp->fprice / $objp->quantity; // Replace dynamically unitprice
3711 }
3712 }
3713 }
3714 if ($objp->quantity == 1) {
3715 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3716 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/";
3717 $optlabel .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
3718 $outvallabel .= $langs->transnoentities("Unit");
3719 } else {
3720 $optlabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3721 $outvallabel .= ' - ' . price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $objp->quantity;
3722 $optlabel .= ' ' . $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
3723 $outvallabel .= ' ' . $langs->transnoentities("Units");
3724 }
3725
3726 if ($objp->quantity > 1) {
3727 $optlabel .= " (" . price($objp->unitprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3728 $outvallabel .= " (" . price($objp->unitprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->transnoentities("Unit") . ")"; // Do not use strtolower because it breaks utf8 encoding
3729 }
3730 if ($objp->remise_percent >= 1) {
3731 $optlabel .= " - " . $langs->trans("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3732 $outvallabel .= " - " . $langs->transnoentities("Discount") . " : " . vatrate($objp->remise_percent) . ' %';
3733 }
3734 if ($objp->duration) {
3735 $optlabel .= " - " . $objp->duration;
3736 $outvallabel .= " - " . $objp->duration;
3737 }
3738 if (!$socid) {
3739 $optlabel .= " - " . dol_trunc($objp->name, 8);
3740 $outvallabel .= " - " . dol_trunc($objp->name, 8);
3741 }
3742 if ($objp->supplier_reputation) {
3743 //TODO dictionary
3744 $reputations = array('' => $langs->trans('Standard'), 'FAVORITE' => $langs->trans('Favorite'), 'NOTTHGOOD' => $langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER' => $langs->trans('DoNotOrderThisProductToThisSupplier'));
3745
3746 $optlabel .= " - " . $reputations[$objp->supplier_reputation];
3747 $outvallabel .= " - " . $reputations[$objp->supplier_reputation];
3748 }
3749 } else {
3750 if (empty($alsoproductwithnosupplierprice)) { // No supplier price defined for couple product/supplier
3751 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3752 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3753 } else { // No supplier price defined for product, even on other suppliers
3754 $optlabel .= " - <span class='opacitymedium'>" . $langs->trans("NoPriceDefinedForThisSupplier") . '</span>';
3755 $outvallabel .= ' - ' . $langs->transnoentities("NoPriceDefinedForThisSupplier");
3756 }
3757 }
3758
3759 if (isModEnabled('stock') && $showstockinlist && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
3760 $novirtualstock = ($showstockinlist == 2);
3761
3762 if ($user->hasRight('stock', 'lire')) {
3763 $outvallabel .= ' - ' . $langs->trans("Stock") . ': ' . price(price2num($objp->stock, 'MS'));
3764
3765 if ($objp->stock > 0) {
3766 $optlabel .= ' - <span class="product_line_stock_ok">';
3767 } elseif ($objp->stock <= 0) {
3768 $optlabel .= ' - <span class="product_line_stock_too_low">';
3769 }
3770 $optlabel .= $langs->transnoentities("Stock") . ':' . price(price2num($objp->stock, 'MS'));
3771 $optlabel .= '</span>';
3772 if (empty($novirtualstock) && getDolGlobalString('STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO')) { // Warning, this option may slow down combo list generation
3773 $langs->load("stocks");
3774
3775 $tmpproduct = new Product($this->db);
3776 $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after)
3777 $tmpproduct->load_virtual_stock();
3778 $virtualstock = $tmpproduct->stock_theorique;
3779
3780 $outvallabel .= ' - ' . $langs->trans("VirtualStock") . ':' . $virtualstock;
3781
3782 $optlabel .= ' - ' . $langs->transnoentities("VirtualStock") . ':';
3783 if ($virtualstock > 0) {
3784 $optlabel .= '<span class="product_line_stock_ok">';
3785 } elseif ($virtualstock <= 0) {
3786 $optlabel .= '<span class="product_line_stock_too_low">';
3787 }
3788 $optlabel .= $virtualstock;
3789 $optlabel .= '</span>';
3790
3791 unset($tmpproduct);
3792 }
3793 }
3794 }
3795
3796 $optstart = '<option value="' . $outkey . '"';
3797 if ($selected && $selected == $objp->idprodfournprice) {
3798 $optstart .= ' selected';
3799 }
3800 if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) {
3801 $optstart .= ' disabled';
3802 }
3803
3804 if (!empty($objp->idprodfournprice) && $objp->idprodfournprice > 0) {
3805 $optstart .= ' data-product-id="' . dol_escape_htmltag($objp->rowid) . '"';
3806 $optstart .= ' data-price-id="' . dol_escape_htmltag($objp->idprodfournprice) . '"';
3807 $optstart .= ' data-qty="' . dol_escape_htmltag($objp->quantity) . '"';
3808 $optstart .= ' data-up="' . dol_escape_htmltag(price2num($objp->unitprice)) . '"';
3809 $optstart .= ' data-up-locale="' . dol_escape_htmltag(price($objp->unitprice)) . '"';
3810 $optstart .= ' data-discount="' . dol_escape_htmltag($outdiscount) . '"';
3811 $optstart .= ' data-tvatx="' . dol_escape_htmltag(price2num($objp->tva_tx)) . '"';
3812 $optstart .= ' data-tvatx-formated="' . dol_escape_htmltag(price($objp->tva_tx, 0, $langs, 1, -1, 2)) . '"';
3813 $optstart .= ' data-default-vat-code="' . dol_escape_htmltag($objp->default_vat_code) . '"';
3814 $optstart .= ' data-supplier-ref="' . dol_escape_htmltag($objp->ref_fourn) . '"';
3815 if (isModEnabled('multicurrency')) {
3816 $optstart .= ' data-multicurrency-code="' . dol_escape_htmltag($objp->multicurrency_code) . '"';
3817 $optstart .= ' data-multicurrency-up="' . dol_escape_htmltag($objp->multicurrency_unitprice) . '"';
3818 }
3819 }
3820 $optstart .= ' data-description="' . dol_escape_htmltag($objp->description, 0, 1) . '"';
3821
3822 $outarrayentry = array(
3823 'key' => $outkey,
3824 'value' => $outref,
3825 'label' => $outvallabel,
3826 'qty' => $outqty,
3827 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
3828 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
3829 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
3830 'tva_tx_formated' => price($objp->tva_tx, 0, $langs, 1, -1, 2),
3831 'tva_tx' => price2num($objp->tva_tx),
3832 'default_vat_code' => $objp->default_vat_code,
3833 'discount' => $outdiscount,
3834 'type' => $outtype,
3835 'duration_value' => $outdurationvalue,
3836 'duration_unit' => $outdurationunit,
3837 'disabled' => (empty($objp->idprodfournprice) ? true : false),
3838 'description' => $objp->description
3839 );
3840 if (isModEnabled('multicurrency')) {
3841 $outarrayentry['multicurrency_code'] = $objp->multicurrency_code;
3842 $outarrayentry['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
3843 }
3844
3845 $parameters = array(
3846 'objp' => &$objp,
3847 'optstart' => &$optstart,
3848 'optlabel' => &$optlabel,
3849 'outvallabel' => &$outvallabel,
3850 'outarrayentry' => &$outarrayentry
3851 );
3852 $reshook = $hookmanager->executeHooks('selectProduitsFournisseurListOption', $parameters, $this);
3853
3854
3855 // Add new entry
3856 // "key" value of json key array is used by jQuery automatically as selected value. Example: 'type' = product or service, 'price_ht' = unit price without tax
3857 // "label" value of json key array is used by jQuery automatically as text for combo box
3858 $out .= $optstart . ' data-html="' . dol_escape_htmltag($optlabel) . '">' . $optlabel . "</option>\n";
3859 $outarraypush = array(
3860 'key' => $outkey,
3861 'value' => $outref,
3862 'label' => $outvallabel,
3863 'qty' => $outqty,
3864 'price_qty_ht' => price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty
3865 'price_qty_ht_locale' => price($objp->fprice),
3866 'price_unit_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price
3867 'price_unit_ht_locale' => price($objp->unitprice),
3868 'price_ht' => price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility)
3869 'tva_tx_formated' => price($objp->tva_tx),
3870 'tva_tx' => price2num($objp->tva_tx),
3871 'default_vat_code' => $objp->default_vat_code,
3872 'discount' => $outdiscount,
3873 'type' => $outtype,
3874 'duration_value' => $outdurationvalue,
3875 'duration_unit' => $outdurationunit,
3876 'disabled' => (empty($objp->idprodfournprice) ? true : false),
3877 'description' => $objp->description
3878 );
3879 if (isModEnabled('multicurrency')) {
3880 $outarraypush['multicurrency_code'] = $objp->multicurrency_code;
3881 $outarraypush['multicurrency_unitprice'] = price2num($objp->multicurrency_unitprice, 'MU');
3882 }
3883 array_push($outarray, $outarraypush);
3884
3885 // Example of var_dump $outarray
3886 // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
3887 // ["label"]=>string(76) "ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
3888 // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false)
3889 //}
3890 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
3891 //$outval=array('label'=>'ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)');
3892 //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
3893
3894 $i++;
3895 }
3896 $out .= '</select>';
3897
3898 $this->db->free($result);
3899
3900 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
3901 $out .= ajax_combobox($htmlname);
3902 } else {
3903 dol_print_error($this->db);
3904 }
3905
3906 if (empty($outputmode)) {
3907 return $out;
3908 }
3909 return $outarray;
3910 }
3911
3912 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3913
3922 public function select_product_fourn_price($productid, $htmlname = 'productfournpriceid', $selected_supplier = 0)
3923 {
3924 // phpcs:enable
3925 global $langs, $conf;
3926
3927 $langs->load('stocks');
3928
3929 $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, pfp.fk_soc,";
3930 $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,";
3931 $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name";
3932 $sql .= " FROM " . $this->db->prefix() . "product as p";
3933 $sql .= " LEFT JOIN " . $this->db->prefix() . "product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
3934 $sql .= " LEFT JOIN " . $this->db->prefix() . "societe as s ON pfp.fk_soc = s.rowid";
3935 $sql .= " WHERE pfp.entity IN (" . getEntity('productsupplierprice') . ")";
3936 $sql .= " AND p.tobuy = 1";
3937 $sql .= " AND s.fournisseur = 1";
3938 $sql .= " AND p.rowid = " . ((int) $productid);
3939 if (!getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED')) {
3940 $sql .= " ORDER BY s.nom, pfp.ref_fourn DESC";
3941 } else {
3942 $sql .= " ORDER BY pfp.unitprice ASC";
3943 }
3944
3945 dol_syslog(get_class($this) . "::select_product_fourn_price", LOG_DEBUG);
3946 $result = $this->db->query($sql);
3947
3948 if ($result) {
3949 $num = $this->db->num_rows($result);
3950
3951 $form = '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
3952
3953 if (!$num) {
3954 $form .= '<option value="0">-- ' . $langs->trans("NoSupplierPriceDefinedForThisProduct") . ' --</option>';
3955 } else {
3956 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3957 $form .= '<option value="0">&nbsp;</option>';
3958
3959 $i = 0;
3960 while ($i < $num) {
3961 $objp = $this->db->fetch_object($result);
3962
3963 $opt = '<option value="' . $objp->idprodfournprice . '"';
3964 //if there is only one supplier, preselect it
3965 if ($num == 1 || ($selected_supplier > 0 && $objp->fk_soc == $selected_supplier) || ($i == 0 && getDolGlobalString('PRODUCT_BEST_SUPPLIER_PRICE_PRESELECTED'))) {
3966 $opt .= ' selected';
3967 }
3968 $opt .= '>' . $objp->name . ' - ' . $objp->ref_fourn . ' - ';
3969
3970 if (isModEnabled('dynamicprices') && !empty($objp->fk_supplier_price_expression)) {
3971 $prod_supplier = new ProductFournisseur($this->db);
3972 $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
3973 $prod_supplier->id = $productid;
3974 $prod_supplier->fourn_qty = $objp->quantity;
3975 $prod_supplier->fourn_tva_tx = $objp->tva_tx;
3976 $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
3977
3978 require_once DOL_DOCUMENT_ROOT . '/product/dynamic_price/class/price_parser.class.php';
3979 $priceparser = new PriceParser($this->db);
3980 $price_result = $priceparser->parseProductSupplier($prod_supplier);
3981 if ($price_result >= 0) {
3982 $objp->fprice = $price_result;
3983 if ($objp->quantity >= 1) {
3984 $objp->unitprice = $objp->fprice / $objp->quantity;
3985 }
3986 }
3987 }
3988 if ($objp->quantity == 1) {
3989 $opt .= price($objp->fprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/";
3990 }
3991
3992 $opt .= $objp->quantity . ' ';
3993
3994 if ($objp->quantity == 1) {
3995 $opt .= $langs->trans("Unit");
3996 } else {
3997 $opt .= $langs->trans("Units");
3998 }
3999 if ($objp->quantity > 1) {
4000 $opt .= " - ";
4001 $opt .= price($objp->unitprice * (getDolGlobalString('DISPLAY_DISCOUNTED_SUPPLIER_PRICE') ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency) . "/" . $langs->trans("Unit");
4002 }
4003 if ($objp->duration) {
4004 $opt .= " - " . $objp->duration;
4005 }
4006 $opt .= "</option>\n";
4007
4008 $form .= $opt;
4009 $i++;
4010 }
4011 }
4012
4013 $form .= '</select>';
4014 $this->db->free($result);
4015 return $form;
4016 } else {
4017 dol_print_error($this->db);
4018 return '';
4019 }
4020 }
4021
4022
4023 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4030 {
4031 // phpcs:enable
4032 global $langs;
4033
4034 $num = count($this->cache_conditions_paiements);
4035 if ($num > 0) {
4036 return 0; // Cache already loaded
4037 }
4038
4039 dol_syslog(__METHOD__, LOG_DEBUG);
4040
4041 $sql = "SELECT rowid, code, libelle as label, deposit_percent";
4042 $sql .= " FROM " . $this->db->prefix() . 'c_payment_term';
4043 $sql .= " WHERE entity IN (" . getEntity('c_payment_term') . ")";
4044 $sql .= " AND active > 0";
4045 $sql .= " ORDER BY sortorder";
4046
4047 $resql = $this->db->query($sql);
4048 if ($resql) {
4049 $num = $this->db->num_rows($resql);
4050 $i = 0;
4051 while ($i < $num) {
4052 $obj = $this->db->fetch_object($resql);
4053
4054 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4055 $label = ($langs->trans("PaymentConditionShort" . $obj->code) != "PaymentConditionShort" . $obj->code ? $langs->trans("PaymentConditionShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4056 $this->cache_conditions_paiements[$obj->rowid]['code'] = $obj->code;
4057 $this->cache_conditions_paiements[$obj->rowid]['label'] = $label;
4058 $this->cache_conditions_paiements[$obj->rowid]['deposit_percent'] = $obj->deposit_percent;
4059 $i++;
4060 }
4061
4062 //$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1); // We use the field sortorder of table
4063
4064 return $num;
4065 } else {
4066 dol_print_error($this->db);
4067 return -1;
4068 }
4069 }
4070
4071 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4072
4078 public function load_cache_availability()
4079 {
4080 // phpcs:enable
4081 global $langs;
4082
4083 $num = count($this->cache_availability); // TODO Use $conf->cache['availability'] instead of $this->cache_availability
4084 if ($num > 0) {
4085 return 0; // Cache already loaded
4086 }
4087
4088 dol_syslog(__METHOD__, LOG_DEBUG);
4089
4090 $langs->load('propal');
4091
4092 $sql = "SELECT rowid, code, label, position";
4093 $sql .= " FROM " . $this->db->prefix() . 'c_availability';
4094 $sql .= " WHERE active > 0";
4095
4096 $resql = $this->db->query($sql);
4097 if ($resql) {
4098 $num = $this->db->num_rows($resql);
4099 $i = 0;
4100 while ($i < $num) {
4101 $obj = $this->db->fetch_object($resql);
4102
4103 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4104 $label = ($langs->trans("AvailabilityType" . $obj->code) != "AvailabilityType" . $obj->code ? $langs->trans("AvailabilityType" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4105 $this->cache_availability[$obj->rowid]['code'] = $obj->code;
4106 $this->cache_availability[$obj->rowid]['label'] = $label;
4107 $this->cache_availability[$obj->rowid]['position'] = $obj->position;
4108 $i++;
4109 }
4110
4111 $this->cache_availability = dol_sort_array($this->cache_availability, 'position', 'asc', 0, 0, 1);
4112
4113 return $num;
4114 } else {
4115 dol_print_error($this->db);
4116 return -1;
4117 }
4118 }
4119
4130 public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0, $morecss = '')
4131 {
4132 global $langs, $user;
4133
4134 $this->load_cache_availability();
4135
4136 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4137
4138 print '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4139 if ($addempty) {
4140 print '<option value="0">&nbsp;</option>';
4141 }
4142 foreach ($this->cache_availability as $id => $arrayavailability) {
4143 if ($selected == $id) {
4144 print '<option value="' . $id . '" selected>';
4145 } else {
4146 print '<option value="' . $id . '">';
4147 }
4148 print dol_escape_htmltag($arrayavailability['label']);
4149 print '</option>';
4150 }
4151 print '</select>';
4152 if ($user->admin) {
4153 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4154 }
4155 print ajax_combobox($htmlname);
4156 }
4157
4163 public function loadCacheInputReason()
4164 {
4165 global $langs;
4166
4167 $num = count($this->cache_demand_reason); // TODO Use $conf->cache['input_reason'] instead of $this->cache_demand_reason
4168 if ($num > 0) {
4169 return 0; // Cache already loaded
4170 }
4171
4172 $sql = "SELECT rowid, code, label";
4173 $sql .= " FROM " . $this->db->prefix() . 'c_input_reason';
4174 $sql .= " WHERE active > 0";
4175
4176 $resql = $this->db->query($sql);
4177 if ($resql) {
4178 $num = $this->db->num_rows($resql);
4179 $i = 0;
4180 $tmparray = array();
4181 while ($i < $num) {
4182 $obj = $this->db->fetch_object($resql);
4183
4184 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4185 $label = ($obj->label != '-' ? $obj->label : '');
4186 if ($langs->trans("DemandReasonType" . $obj->code) != "DemandReasonType" . $obj->code) {
4187 $label = $langs->trans("DemandReasonType" . $obj->code); // So translation key DemandReasonTypeSRC_XXX will work
4188 }
4189 if ($langs->trans($obj->code) != $obj->code) {
4190 $label = $langs->trans($obj->code); // So translation key SRC_XXX will work
4191 }
4192
4193 $tmparray[$obj->rowid]['id'] = $obj->rowid;
4194 $tmparray[$obj->rowid]['code'] = $obj->code;
4195 $tmparray[$obj->rowid]['label'] = $label;
4196 $i++;
4197 }
4198
4199 $this->cache_demand_reason = dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1);
4200
4201 unset($tmparray);
4202 return $num;
4203 } else {
4204 dol_print_error($this->db);
4205 return -1;
4206 }
4207 }
4208
4221 public function selectInputReason($selected = '', $htmlname = 'demandreasonid', $exclude = '', $addempty = 0, $morecss = '', $notooltip = 0)
4222 {
4223 global $langs, $user;
4224
4225 $this->loadCacheInputReason();
4226
4227 print '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4228 if ($addempty) {
4229 print '<option value="0"' . (empty($selected) ? ' selected' : '') . '>&nbsp;</option>';
4230 }
4231 foreach ($this->cache_demand_reason as $id => $arraydemandreason) {
4232 if ($arraydemandreason['code'] == $exclude) {
4233 continue;
4234 }
4235
4236 if ($selected && ($selected == $arraydemandreason['id'] || $selected == $arraydemandreason['code'])) {
4237 print '<option value="' . $arraydemandreason['id'] . '" selected>';
4238 } else {
4239 print '<option value="' . $arraydemandreason['id'] . '">';
4240 }
4241 $label = $arraydemandreason['label']; // Translation of label was already done into the ->loadCacheInputReason
4242 print $langs->trans($label);
4243 print '</option>';
4244 }
4245 print '</select>';
4246 if ($user->admin && empty($notooltip)) {
4247 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4248 }
4249 print ajax_combobox('select_' . $htmlname);
4250 }
4251
4252 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4253
4260 {
4261 // phpcs:enable
4262 global $langs;
4263
4264 $num = count($this->cache_types_paiements); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_types_paiements
4265 if ($num > 0) {
4266 return $num; // Cache already loaded
4267 }
4268
4269 dol_syslog(__METHOD__, LOG_DEBUG);
4270
4271 $this->cache_types_paiements = array();
4272
4273 $sql = "SELECT id, code, libelle as label, type, active";
4274 $sql .= " FROM " . $this->db->prefix() . "c_paiement";
4275 $sql .= " WHERE entity IN (" . getEntity('c_paiement') . ")";
4276
4277 $resql = $this->db->query($sql);
4278 if ($resql) {
4279 $num = $this->db->num_rows($resql);
4280 $i = 0;
4281 while ($i < $num) {
4282 $obj = $this->db->fetch_object($resql);
4283
4284 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
4285 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4286 $this->cache_types_paiements[$obj->id]['id'] = $obj->id;
4287 $this->cache_types_paiements[$obj->id]['code'] = $obj->code;
4288 $this->cache_types_paiements[$obj->id]['label'] = $label;
4289 $this->cache_types_paiements[$obj->id]['type'] = $obj->type;
4290 $this->cache_types_paiements[$obj->id]['active'] = $obj->active;
4291 $i++;
4292 }
4293
4294 $this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1);
4295
4296 return $num;
4297 } else {
4298 dol_print_error($this->db);
4299 return -1;
4300 }
4301 }
4302
4303
4304 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4305
4323 public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4324 {
4325 // phpcs:enable
4326 print $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, $noinfoadmin, $morecss, $deposit_percent);
4327 }
4328
4329
4346 public function getSelectConditionsPaiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '', $deposit_percent = -1)
4347 {
4348 global $langs, $user, $conf;
4349
4350 $out = '';
4351 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
4352
4354
4355 // Set default value if not already set by caller
4356 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID')) {
4357 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TERM_ID", LOG_NOTICE);
4358 $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID;
4359 }
4360
4361 $out .= '<select id="' . $htmlname . '" class="flat selectpaymentterms' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4362 if ($addempty) {
4363 $out .= '<option value="0">&nbsp;</option>';
4364 }
4365
4366 $selectedDepositPercent = null;
4367
4368 foreach ($this->cache_conditions_paiements as $id => $arrayconditions) {
4369 if ($filtertype <= 0 && !empty($arrayconditions['deposit_percent'])) {
4370 continue;
4371 }
4372
4373 if ($selected == $id) {
4374 $selectedDepositPercent = $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'];
4375 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '" selected>';
4376 } else {
4377 $out .= '<option value="' . $id . '" data-deposit_percent="' . $arrayconditions['deposit_percent'] . '">';
4378 }
4379 $label = $arrayconditions['label'];
4380
4381 if (!empty($arrayconditions['deposit_percent'])) {
4382 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $arrayconditions['deposit_percent'], $label);
4383 }
4384
4385 $out .= $label;
4386 $out .= '</option>';
4387 }
4388 $out .= '</select>';
4389 if ($user->admin && empty($noinfoadmin)) {
4390 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4391 }
4392 $out .= ajax_combobox($htmlname);
4393
4394 if ($deposit_percent >= 0) {
4395 $out .= ' <span id="' . $htmlname . '_deposit_percent_container"' . (empty($selectedDepositPercent) ? ' style="display: none"' : '') . '>';
4396 $out .= $langs->trans('DepositPercent') . ' : ';
4397 $out .= '<input id="' . $htmlname . '_deposit_percent" name="' . $htmlname . '_deposit_percent" class="maxwidth50" value="' . $deposit_percent . '" />';
4398 $out .= '</span>';
4399 $out .= '
4400 <script nonce="' . getNonce() . '">
4401 $(document).ready(function () {
4402 $("#' . $htmlname . '").change(function () {
4403 let $selected = $(this).find("option:selected");
4404 let depositPercent = $selected.attr("data-deposit_percent");
4405
4406 if (depositPercent.length > 0) {
4407 $("#' . $htmlname . '_deposit_percent_container").show().find("#' . $htmlname . '_deposit_percent").val(depositPercent);
4408 } else {
4409 $("#' . $htmlname . '_deposit_percent_container").hide();
4410 }
4411
4412 return true;
4413 });
4414 });
4415 </script>';
4416 }
4417
4418 return $out;
4419 }
4420
4421
4422 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4423
4440 public function select_types_paiements($selected = '', $htmlname = 'paiementtype', $filtertype = '', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '', $nooutput = 0)
4441 {
4442 // phpcs:enable
4443 global $langs, $user, $conf;
4444
4445 $out = '';
4446
4447 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
4448
4449 $filterarray = array();
4450 if ($filtertype == 'CRDT') {
4451 $filterarray = array(0, 2, 3);
4452 } elseif ($filtertype == 'DBIT') {
4453 $filterarray = array(1, 2, 3);
4454 } elseif ($filtertype != '' && $filtertype != '-1') {
4455 $filterarray = explode(',', $filtertype);
4456 }
4457
4459
4460 // Set default value if not already set by caller
4461 if (empty($selected) && getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID')) {
4462 dol_syslog(__METHOD__ . "Using deprecated option MAIN_DEFAULT_PAYMENT_TYPE_ID", LOG_NOTICE);
4463 $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TYPE_ID;
4464 }
4465
4466 $out .= '<select id="select' . $htmlname . '" class="flat selectpaymenttypes' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4467 if ($empty) {
4468 $out .= '<option value="">&nbsp;</option>';
4469 }
4470 foreach ($this->cache_types_paiements as $id => $arraytypes) {
4471 // If not good status
4472 if ($active >= 0 && $arraytypes['active'] != $active) {
4473 continue;
4474 }
4475
4476 // On passe si on a demande de filtrer sur des modes de paiments particuliers
4477 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
4478 continue;
4479 }
4480
4481 // We discard empty line if showempty is on because an empty line has already been output.
4482 if ($empty && empty($arraytypes['code'])) {
4483 continue;
4484 }
4485
4486 if ($format == 0) {
4487 $out .= '<option value="' . $id . '"';
4488 } elseif ($format == 1) {
4489 $out .= '<option value="' . $arraytypes['code'] . '"';
4490 } elseif ($format == 2) {
4491 $out .= '<option value="' . $arraytypes['code'] . '"';
4492 } elseif ($format == 3) {
4493 $out .= '<option value="' . $id . '"';
4494 }
4495 // Print attribute selected or not
4496 if ($format == 1 || $format == 2) {
4497 if ($selected == $arraytypes['code']) {
4498 $out .= ' selected';
4499 }
4500 } else {
4501 if ($selected == $id) {
4502 $out .= ' selected';
4503 }
4504 }
4505 $out .= '>';
4506 $value = '';
4507 if ($format == 0) {
4508 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4509 } elseif ($format == 1) {
4510 $value = $arraytypes['code'];
4511 } elseif ($format == 2) {
4512 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4513 } elseif ($format == 3) {
4514 $value = $arraytypes['code'];
4515 }
4516 $out .= $value ? $value : '&nbsp;';
4517 $out .= '</option>';
4518 }
4519 $out .= '</select>';
4520 if ($user->admin && !$noadmininfo) {
4521 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4522 }
4523 $out .= ajax_combobox('select' . $htmlname);
4524
4525 if (empty($nooutput)) {
4526 print $out;
4527 } else {
4528 return $out;
4529 }
4530 }
4531
4532
4541 public function selectPriceBaseType($selected = '', $htmlname = 'price_base_type', $addjscombo = 0)
4542 {
4543 global $langs;
4544
4545 $return = '<select class="flat maxwidth100" id="select_' . $htmlname . '" name="' . $htmlname . '">';
4546 $options = array(
4547 'HT' => $langs->trans("HT"),
4548 'TTC' => $langs->trans("TTC")
4549 );
4550 foreach ($options as $id => $value) {
4551 if ($selected == $id) {
4552 $return .= '<option value="' . $id . '" selected>' . $value;
4553 } else {
4554 $return .= '<option value="' . $id . '">' . $value;
4555 }
4556 $return .= '</option>';
4557 }
4558 $return .= '</select>';
4559 if ($addjscombo) {
4560 $return .= ajax_combobox('select_' . $htmlname);
4561 }
4562
4563 return $return;
4564 }
4565
4566 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4567
4574 {
4575 // phpcs:enable
4576 global $langs;
4577
4578 $num = count($this->cache_transport_mode); // TODO Use $conf->cache['payment_mode'] instead of $this->cache_transport_mode
4579 if ($num > 0) {
4580 return $num; // Cache already loaded
4581 }
4582
4583 dol_syslog(__METHOD__, LOG_DEBUG);
4584
4585 $this->cache_transport_mode = array();
4586
4587 $sql = "SELECT rowid, code, label, active";
4588 $sql .= " FROM " . $this->db->prefix() . "c_transport_mode";
4589 $sql .= " WHERE entity IN (" . getEntity('c_transport_mode') . ")";
4590
4591 $resql = $this->db->query($sql);
4592 if ($resql) {
4593 $num = $this->db->num_rows($resql);
4594 $i = 0;
4595 while ($i < $num) {
4596 $obj = $this->db->fetch_object($resql);
4597
4598 // If traduction exist, we use it else we take the default label
4599 $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : ''));
4600 $this->cache_transport_mode[$obj->rowid]['rowid'] = $obj->rowid;
4601 $this->cache_transport_mode[$obj->rowid]['code'] = $obj->code;
4602 $this->cache_transport_mode[$obj->rowid]['label'] = $label;
4603 $this->cache_transport_mode[$obj->rowid]['active'] = $obj->active;
4604 $i++;
4605 }
4606
4607 $this->cache_transport_mode = dol_sort_array($this->cache_transport_mode, 'label', 'asc', 0, 0, 1);
4608
4609 return $num;
4610 } else {
4611 dol_print_error($this->db);
4612 return -1;
4613 }
4614 }
4615
4629 public function selectTransportMode($selected = '', $htmlname = 'transportmode', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '')
4630 {
4631 global $langs, $user;
4632
4633 dol_syslog(__METHOD__ . " " . $selected . ", " . $htmlname . ", " . $format, LOG_DEBUG);
4634
4636
4637 print '<select id="select' . $htmlname . '" class="flat selectmodetransport' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
4638 if ($empty) {
4639 print '<option value="">&nbsp;</option>';
4640 }
4641 foreach ($this->cache_transport_mode as $id => $arraytypes) {
4642 // If not good status
4643 if ($active >= 0 && $arraytypes['active'] != $active) {
4644 continue;
4645 }
4646
4647 // We discard empty line if showempty is on because an empty line has already been output.
4648 if ($empty && empty($arraytypes['code'])) {
4649 continue;
4650 }
4651
4652 if ($format == 0) {
4653 print '<option value="' . $id . '"';
4654 } elseif ($format == 1) {
4655 print '<option value="' . $arraytypes['code'] . '"';
4656 } elseif ($format == 2) {
4657 print '<option value="' . $arraytypes['code'] . '"';
4658 } elseif ($format == 3) {
4659 print '<option value="' . $id . '"';
4660 }
4661 // If text is selected, we compare with code, else with id
4662 if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) {
4663 print ' selected';
4664 } elseif ($selected == $id) {
4665 print ' selected';
4666 }
4667 print '>';
4668 $value = '';
4669 if ($format == 0) {
4670 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4671 } elseif ($format == 1) {
4672 $value = $arraytypes['code'];
4673 } elseif ($format == 2) {
4674 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
4675 } elseif ($format == 3) {
4676 $value = $arraytypes['code'];
4677 }
4678 print $value ? $value : '&nbsp;';
4679 print '</option>';
4680 }
4681 print '</select>';
4682 if ($user->admin && !$noadmininfo) {
4683 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4684 }
4685 }
4686
4699 public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '', $noinfoadmin = 0, $morecss = '')
4700 {
4701 global $langs, $user;
4702
4703 $langs->load("admin");
4704 $langs->load("deliveries");
4705
4706 $sql = "SELECT rowid, code, libelle as label";
4707 $sql .= " FROM " . $this->db->prefix() . "c_shipment_mode";
4708 $sql .= " WHERE active > 0";
4709 if ($filtre) {
4710 $sql .= " AND " . $filtre;
4711 }
4712 $sql .= " ORDER BY libelle ASC";
4713
4714 dol_syslog(get_class($this) . "::selectShippingMode", LOG_DEBUG);
4715 $result = $this->db->query($sql);
4716 if ($result) {
4717 $num = $this->db->num_rows($result);
4718 $i = 0;
4719 if ($num) {
4720 print '<select id="select' . $htmlname . '" class="flat selectshippingmethod' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4721 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4722 print '<option value="-1">&nbsp;</option>';
4723 }
4724 while ($i < $num) {
4725 $obj = $this->db->fetch_object($result);
4726 if ($selected == $obj->rowid) {
4727 print '<option value="' . $obj->rowid . '" selected>';
4728 } else {
4729 print '<option value="' . $obj->rowid . '">';
4730 }
4731 print ($langs->trans("SendingMethod" . strtoupper($obj->code)) != "SendingMethod" . strtoupper($obj->code)) ? $langs->trans("SendingMethod" . strtoupper($obj->code)) : $obj->label;
4732 print '</option>';
4733 $i++;
4734 }
4735 print "</select>";
4736 if ($user->admin && empty($noinfoadmin)) {
4737 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4738 }
4739
4740 print ajax_combobox('select' . $htmlname);
4741 } else {
4742 print $langs->trans("NoShippingMethodDefined");
4743 }
4744 } else {
4745 dol_print_error($this->db);
4746 }
4747 }
4748
4758 public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0)
4759 {
4760 global $langs;
4761
4762 $langs->load("deliveries");
4763
4764 if ($htmlname != "none") {
4765 print '<form method="POST" action="' . $page . '">';
4766 print '<input type="hidden" name="action" value="setshippingmethod">';
4767 print '<input type="hidden" name="token" value="' . newToken() . '">';
4768 $this->selectShippingMethod($selected, $htmlname, '', $addempty);
4769 print '<input type="submit" class="button valignmiddle" value="' . $langs->trans("Modify") . '">';
4770 print '</form>';
4771 } else {
4772 if ($selected) {
4773 $code = $langs->getLabelFromKey($this->db, $selected, 'c_shipment_mode', 'rowid', 'code');
4774 print $langs->trans("SendingMethod" . strtoupper($code));
4775 } else {
4776 print "&nbsp;";
4777 }
4778 }
4779 }
4780
4789 public function selectSituationInvoices($selected = '', $socid = 0)
4790 {
4791 global $langs;
4792
4793 $langs->load('bills');
4794
4795 $opt = '<option value="" selected></option>';
4796 $sql = "SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc";
4797 $sql .= ' FROM ' . $this->db->prefix() . 'facture';
4798 $sql .= ' WHERE entity IN (' . getEntity('invoice') . ')';
4799 $sql .= ' AND situation_counter >= 1';
4800 $sql .= ' AND fk_soc = ' . (int) $socid;
4801 $sql .= ' AND type <> 2';
4802 $sql .= ' ORDER by situation_cycle_ref, situation_counter desc';
4803 $resql = $this->db->query($sql);
4804
4805 if ($resql && $this->db->num_rows($resql) > 0) {
4806 // Last seen cycle
4807 $ref = 0;
4808 while ($obj = $this->db->fetch_object($resql)) {
4809 //Same cycle ?
4810 if ($obj->situation_cycle_ref != $ref) {
4811 // Just seen this cycle
4812 $ref = $obj->situation_cycle_ref;
4813 //not final ?
4814 if ($obj->situation_final != 1) {
4815 //Not prov?
4816 if (substr($obj->ref, 1, 4) != 'PROV') {
4817 if ($selected == $obj->rowid) {
4818 $opt .= '<option value="' . $obj->rowid . '" selected>' . $obj->ref . '</option>';
4819 } else {
4820 $opt .= '<option value="' . $obj->rowid . '">' . $obj->ref . '</option>';
4821 }
4822 }
4823 }
4824 }
4825 }
4826 } else {
4827 dol_syslog("Error sql=" . $sql . ", error=" . $this->error, LOG_ERR);
4828 }
4829 if ($opt == '<option value ="" selected></option>') {
4830 $opt = '<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>';
4831 }
4832 return $opt;
4833 }
4834
4844 public function selectUnits($selected = '', $htmlname = 'units', $showempty = 0, $unit_type = '')
4845 {
4846 global $langs;
4847
4848 $langs->load('products');
4849
4850 $return = '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
4851
4852 $sql = "SELECT rowid, label, code FROM " . $this->db->prefix() . "c_units";
4853 $sql .= ' WHERE active > 0';
4854 if (!empty($unit_type)) {
4855 $sql .= " AND unit_type = '" . $this->db->escape($unit_type) . "'";
4856 }
4857 $sql .= " ORDER BY sortorder";
4858
4859 $resql = $this->db->query($sql);
4860 if ($resql && $this->db->num_rows($resql) > 0) {
4861 if ($showempty) {
4862 $return .= '<option value="none"></option>';
4863 }
4864
4865 while ($res = $this->db->fetch_object($resql)) {
4866 $unitLabel = $res->label;
4867 if (!empty($langs->tab_translate['unit' . $res->code])) { // check if Translation is available before
4868 $unitLabel = $langs->trans('unit' . $res->code) != $res->label ? $langs->trans('unit' . $res->code) : $res->label;
4869 }
4870
4871 if ($selected == $res->rowid) {
4872 $return .= '<option value="' . $res->rowid . '" selected>' . $unitLabel . '</option>';
4873 } else {
4874 $return .= '<option value="' . $res->rowid . '">' . $unitLabel . '</option>';
4875 }
4876 }
4877 $return .= '</select>';
4878 }
4879 return $return;
4880 }
4881
4882 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4883
4898 public function select_comptes($selected = '', $htmlname = 'accountid', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '', $showcurrency = 0, $morecss = '', $nooutput = 0)
4899 {
4900 // phpcs:enable
4901 global $langs, $conf;
4902
4903 $out = '';
4904
4905 $langs->load("admin");
4906 $num = 0;
4907
4908 $sql = "SELECT rowid, label, bank, clos as status, currency_code";
4909 $sql .= " FROM " . $this->db->prefix() . "bank_account";
4910 $sql .= " WHERE entity IN (" . getEntity('bank_account') . ")";
4911 if ($status != 2) {
4912 $sql .= " AND clos = " . (int) $status;
4913 }
4914 if ($filtre) {
4915 $sql .= " AND " . $filtre;
4916 }
4917 $sql .= " ORDER BY label";
4918
4919 dol_syslog(get_class($this) . "::select_comptes", LOG_DEBUG);
4920 $result = $this->db->query($sql);
4921 if ($result) {
4922 $num = $this->db->num_rows($result);
4923 $i = 0;
4924 if ($num) {
4925 $out .= '<select id="select' . $htmlname . '" class="flat selectbankaccount' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
4926 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
4927 $out .= '<option value="-1">&nbsp;</option>';
4928 }
4929
4930 while ($i < $num) {
4931 $obj = $this->db->fetch_object($result);
4932 if ($selected == $obj->rowid || ($useempty == 2 && $num == 1 && empty($selected))) {
4933 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '" selected>';
4934 } else {
4935 $out .= '<option value="' . $obj->rowid . '" data-currency-code="' . $obj->currency_code . '">';
4936 }
4937 $out .= trim($obj->label);
4938 if ($showcurrency) {
4939 $out .= ' (' . $obj->currency_code . ')';
4940 }
4941 if ($status == 2 && $obj->status == 1) {
4942 $out .= ' (' . $langs->trans("Closed") . ')';
4943 }
4944 $out .= '</option>';
4945 $i++;
4946 }
4947 $out .= "</select>";
4948 $out .= ajax_combobox('select' . $htmlname);
4949 } else {
4950 if ($status == 0) {
4951 $out .= '<span class="opacitymedium">' . $langs->trans("NoActiveBankAccountDefined") . '</span>';
4952 } else {
4953 $out .= '<span class="opacitymedium">' . $langs->trans("NoBankAccountFound") . '</span>';
4954 }
4955 }
4956 } else {
4957 dol_print_error($this->db);
4958 }
4959
4960 // Output or return
4961 if (empty($nooutput)) {
4962 print $out;
4963 } else {
4964 return $out;
4965 }
4966
4967 return $num;
4968 }
4969
4981 public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '')
4982 {
4983 global $langs, $conf;
4984
4985 $langs->load("admin");
4986 $num = 0;
4987
4988 $sql = "SELECT rowid, name, fk_country, status, entity";
4989 $sql .= " FROM " . $this->db->prefix() . "establishment";
4990 $sql .= " WHERE 1=1";
4991 if ($status != 2) {
4992 $sql .= " AND status = " . (int) $status;
4993 }
4994 if ($filtre) {
4995 $sql .= " AND " . $filtre;
4996 }
4997 $sql .= " ORDER BY name";
4998
4999 dol_syslog(get_class($this) . "::select_establishment", LOG_DEBUG);
5000 $result = $this->db->query($sql);
5001 if ($result) {
5002 $num = $this->db->num_rows($result);
5003 $i = 0;
5004 if ($num) {
5005 print '<select id="select' . $htmlname . '" class="flat selectestablishment" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
5006 if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
5007 print '<option value="-1">&nbsp;</option>';
5008 }
5009
5010 while ($i < $num) {
5011 $obj = $this->db->fetch_object($result);
5012 if ($selected == $obj->rowid) {
5013 print '<option value="' . $obj->rowid . '" selected>';
5014 } else {
5015 print '<option value="' . $obj->rowid . '">';
5016 }
5017 print trim($obj->name);
5018 if ($status == 2 && $obj->status == 1) {
5019 print ' (' . $langs->trans("Closed") . ')';
5020 }
5021 print '</option>';
5022 $i++;
5023 }
5024 print "</select>";
5025 } else {
5026 if ($status == 0) {
5027 print '<span class="opacitymedium">' . $langs->trans("NoActiveEstablishmentDefined") . '</span>';
5028 } else {
5029 print '<span class="opacitymedium">' . $langs->trans("NoEstablishmentFound") . '</span>';
5030 }
5031 }
5032
5033 return $num;
5034 } else {
5035 dol_print_error($this->db);
5036 return -1;
5037 }
5038 }
5039
5049 public function formSelectAccount($page, $selected = '', $htmlname = 'fk_account', $addempty = 0)
5050 {
5051 global $langs;
5052 if ($htmlname != "none") {
5053 print '<form method="POST" action="' . $page . '">';
5054 print '<input type="hidden" name="action" value="setbankaccount">';
5055 print '<input type="hidden" name="token" value="' . newToken() . '">';
5056 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
5057 $nbaccountfound = $this->select_comptes($selected, $htmlname, 0, '', $addempty);
5058 if ($nbaccountfound > 0) {
5059 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5060 }
5061 print '</form>';
5062 } else {
5063 $langs->load('banks');
5064
5065 if ($selected) {
5066 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
5067 $bankstatic = new Account($this->db);
5068 $result = $bankstatic->fetch($selected);
5069 if ($result) {
5070 print $bankstatic->getNomUrl(1);
5071 }
5072 } else {
5073 print "&nbsp;";
5074 }
5075 }
5076 }
5077
5078 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5079
5098 public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $markafterid = 0, $outputmode = 0, $include = 0, $morecss = '')
5099 {
5100 // phpcs:enable
5101 global $conf, $langs;
5102 $langs->load("categories");
5103
5104 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
5105
5106 // For backward compatibility
5107 if (is_numeric($type)) {
5108 dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING);
5109 }
5110
5111 if ($type === Categorie::TYPE_BANK_LINE) {
5112 // TODO Move this into common category feature
5113 $cate_arbo = array();
5114 $sql = "SELECT c.label, c.rowid";
5115 $sql .= " FROM " . $this->db->prefix() . "bank_categ as c";
5116 $sql .= " WHERE entity = " . $conf->entity;
5117 $sql .= " ORDER BY c.label";
5118 $result = $this->db->query($sql);
5119 if ($result) {
5120 $num = $this->db->num_rows($result);
5121 $i = 0;
5122 while ($i < $num) {
5123 $objp = $this->db->fetch_object($result);
5124 if ($objp) {
5125 $cate_arbo[$objp->rowid] = array('id' => $objp->rowid, 'fulllabel' => $objp->label, 'color' => '', 'picto' => 'category');
5126 }
5127 $i++;
5128 }
5129 $this->db->free($result);
5130 } else {
5131 dol_print_error($this->db);
5132 }
5133 } else {
5134 $cat = new Categorie($this->db);
5135 $cate_arbo = $cat->get_full_arbo($type, $markafterid, $include);
5136 }
5137
5138 $outarray = array();
5139 $outarrayrichhtml = array();
5140
5141 $output = '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
5142 if (is_array($cate_arbo)) {
5143 if (!count($cate_arbo)) {
5144 $output .= '<option value="-1" disabled>' . $langs->trans("NoCategoriesDefined") . '</option>';
5145 } else {
5146 $output .= '<option value="-1">&nbsp;</option>';
5147 foreach ($cate_arbo as $key => $value) {
5148 if ($cate_arbo[$key]['id'] == $selected || ($selected === 'auto' && count($cate_arbo) == 1)) {
5149 $add = 'selected ';
5150 } else {
5151 $add = '';
5152 }
5153
5154 $labeltoshow = img_picto('', 'category', 'class="pictofixedwidth" style="color: #' . $cate_arbo[$key]['color'] . '"');
5155 $labeltoshow .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5156
5157 $outarray[$cate_arbo[$key]['id']] = $cate_arbo[$key]['fulllabel'];
5158
5159 $outarrayrichhtml[$cate_arbo[$key]['id']] = $labeltoshow;
5160
5161 $output .= '<option ' . $add . 'value="' . $cate_arbo[$key]['id'] . '"';
5162 $output .= ' data-html="' . dol_escape_htmltag($labeltoshow) . '"';
5163 $output .= '>';
5164 $output .= dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle');
5165 $output .= '</option>';
5166 }
5167 }
5168 }
5169 $output .= '</select>';
5170 $output .= "\n";
5171
5172 if ($outputmode == 2) {
5173 return $cate_arbo;
5174 } elseif ($outputmode == 1) {
5175 return $outarray;
5176 } elseif ($outputmode == 3) {
5177 return $outarrayrichhtml;
5178 }
5179 return $output;
5180 }
5181
5182 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5183
5200 public function form_confirm($page, $title, $question, $action, $formquestion = array(), $selectedchoice = "", $useajax = 0, $height = 170, $width = 500)
5201 {
5202 // phpcs:enable
5203 dol_syslog(__METHOD__ . ': using form_confirm is deprecated. Use formconfim instead.', LOG_WARNING);
5204 print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width);
5205 }
5206
5234 public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No')
5235 {
5236 global $langs, $conf;
5237
5238 $more = '<!-- formconfirm - before call, page=' . dol_escape_htmltag($page) . ' -->';
5239 $formconfirm = '';
5240 $inputok = array();
5241 $inputko = array();
5242
5243 // Clean parameters
5244 $newselectedchoice = empty($selectedchoice) ? "no" : $selectedchoice;
5245 if ($conf->browser->layout == 'phone') {
5246 $width = '95%';
5247 }
5248
5249 // Set height automatically if not defined
5250 if (empty($height)) {
5251 $height = 220;
5252 if (is_array($formquestion) && count($formquestion) > 2) {
5253 $height += ((count($formquestion) - 2) * 24);
5254 }
5255 }
5256
5257 if (is_array($formquestion) && !empty($formquestion)) {
5258 // First add hidden fields and value
5259 foreach ($formquestion as $key => $input) {
5260 if (is_array($input) && !empty($input)) {
5261 if ($input['type'] == 'hidden') {
5262 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5263 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5264
5265 $more .= '<input type="hidden" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '" value="' . dol_escape_htmltag($input['value']) . '" class="' . $morecss . '"' . $moreattr . '>' . "\n";
5266 }
5267 }
5268 }
5269
5270 // Now add questions
5271 $moreonecolumn = '';
5272 $more .= '<div class="tagtable paddingtopbottomonly centpercent noborderspacing">' . "\n";
5273 foreach ($formquestion as $key => $input) {
5274 if (is_array($input) && !empty($input)) {
5275 $size = (!empty($input['size']) ? ' size="' . $input['size'] . '"' : ''); // deprecated. Use morecss instead.
5276 $moreattr = (!empty($input['moreattr']) ? ' ' . $input['moreattr'] : '');
5277 $morecss = (!empty($input['morecss']) ? ' ' . $input['morecss'] : '');
5278
5279 if ($input['type'] == 'text') {
5280 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div><div class="tagtd"><input type="text" class="flat' . $morecss . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $size . ' value="' . (empty($input['value']) ? '' : $input['value']) . '"' . $moreattr . ' /></div></div>' . "\n";
5281 } elseif ($input['type'] == 'password') {
5282 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div><div class="tagtd"><input type="password" class="flat' . $morecss . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $size . ' value="' . (empty($input['value']) ? '' : $input['value']) . '"' . $moreattr . ' /></div></div>' . "\n";
5283 } elseif ($input['type'] == 'textarea') {
5284 /*$more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">'.$input['label'].'</div><div class="tagtd">';
5285 $more .= '<textarea name="'.$input['name'].'" class="'.$morecss.'"'.$moreattr.'>';
5286 $more .= $input['value'];
5287 $more .= '</textarea>';
5288 $more .= '</div></div>'."\n";*/
5289 $moreonecolumn .= '<div class="margintoponly">';
5290 $moreonecolumn .= $input['label'] . '<br>';
5291 $moreonecolumn .= '<textarea name="' . dol_escape_htmltag($input['name']) . '" id="' . dol_escape_htmltag($input['name']) . '" class="' . $morecss . '"' . $moreattr . '>';
5292 $moreonecolumn .= $input['value'];
5293 $moreonecolumn .= '</textarea>';
5294 $moreonecolumn .= '</div>';
5295 } elseif (in_array($input['type'], ['select', 'multiselect'])) {
5296 if (empty($morecss)) {
5297 $morecss = 'minwidth100';
5298 }
5299
5300 $show_empty = isset($input['select_show_empty']) ? $input['select_show_empty'] : 1;
5301 $key_in_label = isset($input['select_key_in_label']) ? $input['select_key_in_label'] : 0;
5302 $value_as_key = isset($input['select_value_as_key']) ? $input['select_value_as_key'] : 0;
5303 $translate = isset($input['select_translate']) ? $input['select_translate'] : 0;
5304 $maxlen = isset($input['select_maxlen']) ? $input['select_maxlen'] : 0;
5305 $disabled = isset($input['select_disabled']) ? $input['select_disabled'] : 0;
5306 $sort = isset($input['select_sort']) ? $input['select_sort'] : '';
5307
5308 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">';
5309 if (!empty($input['label'])) {
5310 $more .= $input['label'] . '</div><div class="tagtd left">';
5311 }
5312 if ($input['type'] == 'select') {
5313 $more .= $this->selectarray($input['name'], $input['values'], isset($input['default']) ? $input['default'] : '-1', $show_empty, $key_in_label, $value_as_key, $moreattr, $translate, $maxlen, $disabled, $sort, $morecss);
5314 } else {
5315 $more .= $this->multiselectarray($input['name'], $input['values'], is_array($input['default']) ? $input['default'] : [$input['default']], $key_in_label, $value_as_key, $morecss, $translate, $maxlen, $moreattr);
5316 }
5317 $more .= '</div></div>' . "\n";
5318 } elseif ($input['type'] == 'checkbox') {
5319 $more .= '<div class="tagtr">';
5320 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '"><label for="' . dol_escape_htmltag($input['name']) . '">' . $input['label'] . '</label></div><div class="tagtd">';
5321 $more .= '<input type="checkbox" class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . dol_escape_htmltag($input['name']) . '" name="' . dol_escape_htmltag($input['name']) . '"' . $moreattr;
5322 if (!is_bool($input['value']) && $input['value'] != 'false' && $input['value'] != '0' && $input['value'] != '') {
5323 $more .= ' checked';
5324 }
5325 if (is_bool($input['value']) && $input['value']) {
5326 $more .= ' checked';
5327 }
5328 if (isset($input['disabled'])) {
5329 $more .= ' disabled';
5330 }
5331 $more .= ' /></div>';
5332 $more .= '</div>' . "\n";
5333 } elseif ($input['type'] == 'radio') {
5334 $i = 0;
5335 foreach ($input['values'] as $selkey => $selval) {
5336 $more .= '<div class="tagtr">';
5337 if (isset($input['label'])) {
5338 if ($i == 0) {
5339 $more .= '<div class="tagtd' . (empty($input['tdclass']) ? ' tdtop' : (' tdtop ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5340 } else {
5341 $more .= '<div clas="tagtd' . (empty($input['tdclass']) ? '' : (' "' . $input['tdclass'])) . '">&nbsp;</div>';
5342 }
5343 }
5344 $more .= '<div class="tagtd' . ($i == 0 ? ' tdtop' : '') . '"><input type="radio" class="flat' . $morecss . '" id="' . dol_escape_htmltag($input['name'] . $selkey) . '" name="' . dol_escape_htmltag($input['name']) . '" value="' . $selkey . '"' . $moreattr;
5345 if (!empty($input['disabled'])) {
5346 $more .= ' disabled';
5347 }
5348 if (isset($input['default']) && $input['default'] === $selkey) {
5349 $more .= ' checked="checked"';
5350 }
5351 $more .= ' /> ';
5352 $more .= '<label for="' . dol_escape_htmltag($input['name'] . $selkey) . '" class="valignmiddle">' . $selval . '</label>';
5353 $more .= '</div></div>' . "\n";
5354 $i++;
5355 }
5356 } elseif ($input['type'] == 'date' || $input['type'] == 'datetime') {
5357 $more .= '<div class="tagtr"><div class="tagtd' . (empty($input['tdclass']) ? '' : (' ' . $input['tdclass'])) . '">' . $input['label'] . '</div>';
5358 $more .= '<div class="tagtd">';
5359 $addnowlink = (empty($input['datenow']) ? 0 : 1);
5360 $h = $m = 0;
5361 if ($input['type'] == 'datetime') {
5362 $h = isset($input['hours']) ? $input['hours'] : 1;
5363 $m = isset($input['minutes']) ? $input['minutes'] : 1;
5364 }
5365 $more .= $this->selectDate($input['value'], $input['name'], $h, $m, 0, '', 1, $addnowlink);
5366 $more .= '</div></div>'."\n";
5367 $formquestion[] = array('name'=>$input['name'].'day');
5368 $formquestion[] = array('name'=>$input['name'].'month');
5369 $formquestion[] = array('name'=>$input['name'].'year');
5370 $formquestion[] = array('name'=>$input['name'].'hour');
5371 $formquestion[] = array('name'=>$input['name'].'min');
5372 } elseif ($input['type'] == 'other') { // can be 1 column or 2 depending if label is set or not
5373 $more .= '<div class="tagtr"><div class="tagtd'.(empty($input['tdclass']) ? '' : (' '.$input['tdclass'])).'">';
5374 if (!empty($input['label'])) {
5375 $more .= $input['label'] . '</div><div class="tagtd">';
5376 }
5377 $more .= $input['value'];
5378 $more .= '</div></div>' . "\n";
5379 } elseif ($input['type'] == 'onecolumn') {
5380 $moreonecolumn .= '<div class="margintoponly">';
5381 $moreonecolumn .= $input['value'];
5382 $moreonecolumn .= '</div>' . "\n";
5383 } elseif ($input['type'] == 'hidden') {
5384 // Do nothing more, already added by a previous loop
5385 } elseif ($input['type'] == 'separator') {
5386 $more .= '<br>';
5387 } else {
5388 $more .= 'Error type ' . $input['type'] . ' for the confirm box is not a supported type';
5389 }
5390 }
5391 }
5392 $more .= '</div>' . "\n";
5393 $more .= $moreonecolumn;
5394 }
5395
5396 // JQUERY method dialog is broken with smartphone, we use standard HTML.
5397 // Note: When using dol_use_jmobile or no js, you must also check code for button use a GET url with action=xxx and check that you also output the confirm code when action=xxx
5398 // See page product/card.php for example
5399 if (!empty($conf->dol_use_jmobile)) {
5400 $useajax = 0;
5401 }
5402 if (empty($conf->use_javascript_ajax)) {
5403 $useajax = 0;
5404 }
5405
5406 if ($useajax) {
5407 $autoOpen = true;
5408 $dialogconfirm = 'dialog-confirm';
5409 $button = '';
5410 if (!is_numeric($useajax)) {
5411 $button = $useajax;
5412 $useajax = 1;
5413 $autoOpen = false;
5414 $dialogconfirm .= '-' . $button;
5415 }
5416 $pageyes = $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=yes';
5417 $pageno = ($useajax == 2 ? $page . (preg_match('/\?/', $page) ? '&' : '?') . 'action=' . urlencode($action) . '&confirm=no' : '');
5418
5419 // Add input fields into list of fields to read during submit (inputok and inputko)
5420 if (is_array($formquestion)) {
5421 foreach ($formquestion as $key => $input) {
5422 //print "xx ".$key." rr ".is_array($input)."<br>\n";
5423 // Add name of fields to propagate with the GET when submitting the form with button OK.
5424 if (is_array($input) && isset($input['name'])) {
5425 if (strpos($input['name'], ',') > 0) {
5426 $inputok = array_merge($inputok, explode(',', $input['name']));
5427 } else {
5428 array_push($inputok, $input['name']);
5429 }
5430 }
5431 // Add name of fields to propagate with the GET when submitting the form with button KO.
5432 if (isset($input['inputko']) && $input['inputko'] == 1) {
5433 array_push($inputko, $input['name']);
5434 }
5435 }
5436 }
5437
5438 // Show JQuery confirm box.
5439 $formconfirm .= '<div id="' . $dialogconfirm . '" title="' . dol_escape_htmltag($title) . '" style="display: none;">';
5440 if (is_array($formquestion) && !empty($formquestion['text'])) {
5441 $formconfirm .= '<div class="confirmtext">' . $formquestion['text'] . '</div>' . "\n";
5442 }
5443 if (!empty($more)) {
5444 $formconfirm .= '<div class="confirmquestions">' . $more . '</div>' . "\n";
5445 }
5446 $formconfirm .= ($question ? '<div class="confirmmessage">' . img_help('', '') . ' ' . $question . '</div>' : '');
5447 $formconfirm .= '</div>' . "\n";
5448
5449 $formconfirm .= "\n<!-- begin code of popup for formconfirm page=" . $page . " -->\n";
5450 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5451 $formconfirm .= "/* Code for the jQuery('#dialogforpopup').dialog() */\n";
5452 $formconfirm .= 'jQuery(document).ready(function() {
5453 $(function() {
5454 $( "#' . $dialogconfirm . '" ).dialog(
5455 {
5456 autoOpen: ' . ($autoOpen ? "true" : "false") . ',';
5457 if ($newselectedchoice == 'no') {
5458 $formconfirm .= '
5459 open: function() {
5460 $(this).parent().find("button.ui-button:eq(2)").focus();
5461 },';
5462 }
5463
5464 $jsforcursor = '';
5465 if ($useajax == 1) {
5466 $jsforcursor = '// The call to urljump can be slow, so we set the wait cursor' . "\n";
5467 $jsforcursor .= 'jQuery("html,body,#id-container").addClass("cursorwait");' . "\n";
5468 }
5469
5470 $postconfirmas = 'GET';
5471
5472 $formconfirm .= '
5473 resizable: false,
5474 height: "' . $height . '",
5475 width: "' . $width . '",
5476 modal: true,
5477 closeOnEscape: false,
5478 buttons: {
5479 "' . dol_escape_js($langs->transnoentities($labelbuttonyes)) . '": function() {
5480 var options = "token=' . urlencode(newToken()) . '";
5481 var inputok = ' . json_encode($inputok) . '; /* List of fields into form */
5482 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5483 var pageyes = "' . dol_escape_js(!empty($pageyes) ? $pageyes : '') . '";
5484
5485 if (inputok.length > 0) {
5486 $.each(inputok, function(i, inputname) {
5487 var more = "";
5488 var inputvalue;
5489 if ($("input[name=\'" + inputname + "\']").attr("type") == "radio") {
5490 inputvalue = $("input[name=\'" + inputname + "\']:checked").val();
5491 } else {
5492 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5493 inputvalue = $("#" + inputname + more).val();
5494 }
5495 if (typeof inputvalue == "undefined") { inputvalue=""; }
5496 console.log("formconfirm check inputname="+inputname+" inputvalue="+inputvalue);
5497 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5498 });
5499 }
5500 var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "&") + options;
5501 if (pageyes.length > 0) {';
5502 if ($postconfirmas == 'GET') {
5503 $formconfirm .= 'location.href = urljump;';
5504 } else {
5505 $formconfirm .= $jsforcursor;
5506 $formconfirm .= 'var post = $.post(
5507 pageyes,
5508 options,
5509 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5510 );';
5511 }
5512 $formconfirm .= '
5513 console.log("after post ok");
5514 }
5515 $(this).dialog("close");
5516 },
5517 "' . dol_escape_js($langs->transnoentities($labelbuttonno)) . '": function() {
5518 var options = "token=' . urlencode(newToken()) . '";
5519 var inputko = ' . json_encode($inputko) . '; /* List of fields into form */
5520 var page = "' . dol_escape_js(!empty($page) ? $page : '') . '";
5521 var pageno="' . dol_escape_js(!empty($pageno) ? $pageno : '') . '";
5522 if (inputko.length > 0) {
5523 $.each(inputko, function(i, inputname) {
5524 var more = "";
5525 if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
5526 var inputvalue = $("#" + inputname + more).val();
5527 if (typeof inputvalue == "undefined") { inputvalue=""; }
5528 options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
5529 });
5530 }
5531 var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "&") + options;
5532 //alert(urljump);
5533 if (pageno.length > 0) {';
5534 if ($postconfirmas == 'GET') {
5535 $formconfirm .= 'location.href = urljump;';
5536 } else {
5537 $formconfirm .= $jsforcursor;
5538 $formconfirm .= 'var post = $.post(
5539 pageno,
5540 options,
5541 function(data) { $("body").html(data); jQuery("html,body,#id-container").removeClass("cursorwait"); }
5542 );';
5543 }
5544 $formconfirm .= '
5545 console.log("after post ko");
5546 }
5547 $(this).dialog("close");
5548 }
5549 }
5550 }
5551 );
5552
5553 var button = "' . $button . '";
5554 if (button.length > 0) {
5555 $( "#" + button ).click(function() {
5556 $("#' . $dialogconfirm . '").dialog("open");
5557 });
5558 }
5559 });
5560 });
5561 </script>';
5562 $formconfirm .= "<!-- end ajax formconfirm -->\n";
5563 } else {
5564 $formconfirm .= "\n<!-- begin formconfirm page=" . dol_escape_htmltag($page) . " -->\n";
5565
5566 if (empty($disableformtag)) {
5567 $formconfirm .= '<form method="POST" action="' . $page . '" class="notoptoleftroright">' . "\n";
5568 }
5569
5570 $formconfirm .= '<input type="hidden" name="action" value="' . $action . '">' . "\n";
5571 $formconfirm .= '<input type="hidden" name="token" value="' . newToken() . '">' . "\n";
5572
5573 $formconfirm .= '<table class="valid centpercent">' . "\n";
5574
5575 // Line title
5576 $formconfirm .= '<tr class="validtitre"><td class="validtitre" colspan="2">';
5577 $formconfirm .= img_picto('', 'pictoconfirm') . ' ' . $title;
5578 $formconfirm .= '</td></tr>' . "\n";
5579
5580 // Line text
5581 if (is_array($formquestion) && !empty($formquestion['text'])) {
5582 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . $formquestion['text'] . '</td></tr>' . "\n";
5583 }
5584
5585 // Line form fields
5586 if ($more) {
5587 $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . "\n";
5588 $formconfirm .= $more;
5589 $formconfirm .= '</td></tr>' . "\n";
5590 }
5591
5592 // Line with question
5593 $formconfirm .= '<tr class="valid">';
5594 $formconfirm .= '<td class="valid">' . $question . '</td>';
5595 $formconfirm .= '<td class="valid center">';
5596 $formconfirm .= $this->selectyesno("confirm", $newselectedchoice, 0, false, 0, 0, 'marginleftonly marginrightonly', $labelbuttonyes, $labelbuttonno);
5597 $formconfirm .= '<input class="button valignmiddle confirmvalidatebutton small" type="submit" value="' . $langs->trans("Validate") . '">';
5598 $formconfirm .= '</td>';
5599 $formconfirm .= '</tr>' . "\n";
5600
5601 $formconfirm .= '</table>' . "\n";
5602
5603 if (empty($disableformtag)) {
5604 $formconfirm .= "</form>\n";
5605 }
5606 $formconfirm .= '<br>';
5607
5608 if (!empty($conf->use_javascript_ajax)) {
5609 $formconfirm .= '<!-- code to disable button to avoid double clic -->';
5610 $formconfirm .= '<script nonce="' . getNonce() . '" type="text/javascript">' . "\n";
5611 $formconfirm .= '
5612 $(document).ready(function () {
5613 $(".confirmvalidatebutton").on("click", function() {
5614 console.log("We click on button confirmvalidatebutton");
5615 $(this).attr("disabled", "disabled");
5616 setTimeout(\'$(".confirmvalidatebutton").removeAttr("disabled")\', 3000);
5617 //console.log($(this).closest("form"));
5618 $(this).closest("form").submit();
5619 });
5620 });
5621 ';
5622 $formconfirm .= '</script>' . "\n";
5623 }
5624
5625 $formconfirm .= "<!-- end formconfirm -->\n";
5626 }
5627
5628 return $formconfirm;
5629 }
5630
5631
5632 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5633
5649 public function form_project($page, $socid, $selected = '', $htmlname = 'projectid', $discard_closed = 0, $maxlength = 20, $forcefocus = 0, $nooutput = 0, $textifnoproject = '', $morecss = '')
5650 {
5651 // phpcs:enable
5652 global $langs;
5653
5654 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
5655 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
5656
5657 $out = '';
5658
5659 $formproject = new FormProjets($this->db);
5660
5661 $langs->load("project");
5662 if ($htmlname != "none") {
5663 $out .= '<form method="post" action="' . $page . '">';
5664 $out .= '<input type="hidden" name="action" value="classin">';
5665 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5666 $out .= $formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1, 0, $morecss);
5667 $out .= '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5668 $out .= '</form>';
5669 } else {
5670 $out .= '<span class="project_head_block">';
5671 if ($selected) {
5672 $projet = new Project($this->db);
5673 $projet->fetch($selected);
5674 $out .= $projet->getNomUrl(0, '', 1);
5675 } else {
5676 $out .= '<span class="opacitymedium">' . $textifnoproject . '</span>';
5677 }
5678 $out .= '</span>';
5679 }
5680
5681 if (empty($nooutput)) {
5682 print $out;
5683 return '';
5684 }
5685 return $out;
5686 }
5687
5688 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5689
5705 public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0, $type = '', $filtertype = -1, $deposit_percent = -1, $nooutput = 0)
5706 {
5707 // phpcs:enable
5708 global $langs;
5709
5710 $out = '';
5711
5712 if ($htmlname != "none") {
5713 $out .= '<form method="POST" action="' . $page . '">';
5714 $out .= '<input type="hidden" name="action" value="setconditions">';
5715 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5716 if ($type) {
5717 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5718 }
5719 $out .= $this->getSelectConditionsPaiements($selected, $htmlname, $filtertype, $addempty, 0, '', $deposit_percent);
5720 $out .= '<input type="submit" class="button valignmiddle smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5721 $out .= '</form>';
5722 } else {
5723 if ($selected) {
5725 if (isset($this->cache_conditions_paiements[$selected])) {
5726 $label = $this->cache_conditions_paiements[$selected]['label'];
5727
5728 if (!empty($this->cache_conditions_paiements[$selected]['deposit_percent'])) {
5729 $label = str_replace('__DEPOSIT_PERCENT__', $deposit_percent > 0 ? $deposit_percent : $this->cache_conditions_paiements[$selected]['deposit_percent'], $label);
5730 }
5731
5732 $out .= $label;
5733 } else {
5734 $langs->load('errors');
5735 $out .= $langs->trans('ErrorNotInDictionaryPaymentConditions');
5736 }
5737 } else {
5738 $out .= '&nbsp;';
5739 }
5740 }
5741
5742 if (empty($nooutput)) {
5743 print $out;
5744 return '';
5745 }
5746 return $out;
5747 }
5748
5749 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5750
5760 public function form_availability($page, $selected = '', $htmlname = 'availability', $addempty = 0)
5761 {
5762 // phpcs:enable
5763 global $langs;
5764 if ($htmlname != "none") {
5765 print '<form method="post" action="' . $page . '">';
5766 print '<input type="hidden" name="action" value="setavailability">';
5767 print '<input type="hidden" name="token" value="' . newToken() . '">';
5768 $this->selectAvailabilityDelay($selected, $htmlname, -1, $addempty);
5769 print '<input type="submit" name="modify" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5770 print '<input type="submit" name="cancel" class="button smallpaddingimp" value="' . $langs->trans("Cancel") . '">';
5771 print '</form>';
5772 } else {
5773 if ($selected) {
5774 $this->load_cache_availability();
5775 print $this->cache_availability[$selected]['label'];
5776 } else {
5777 print "&nbsp;";
5778 }
5779 }
5780 }
5781
5792 public function formInputReason($page, $selected = '', $htmlname = 'demandreason', $addempty = 0)
5793 {
5794 global $langs;
5795 if ($htmlname != "none") {
5796 print '<form method="post" action="' . $page . '">';
5797 print '<input type="hidden" name="action" value="setdemandreason">';
5798 print '<input type="hidden" name="token" value="' . newToken() . '">';
5799 $this->selectInputReason($selected, $htmlname, -1, $addempty);
5800 print '<input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '">';
5801 print '</form>';
5802 } else {
5803 if ($selected) {
5804 $this->loadCacheInputReason();
5805 foreach ($this->cache_demand_reason as $key => $val) {
5806 if ($val['id'] == $selected) {
5807 print $val['label'];
5808 break;
5809 }
5810 }
5811 } else {
5812 print "&nbsp;";
5813 }
5814 }
5815 }
5816
5817 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5818
5832 public function form_date($page, $selected, $htmlname, $displayhour = 0, $displaymin = 0, $nooutput = 0, $type = '')
5833 {
5834 // phpcs:enable
5835 global $langs;
5836
5837 $ret = '';
5838
5839 if ($htmlname != "none") {
5840 $ret .= '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
5841 $ret .= '<input type="hidden" name="action" value="set' . $htmlname . '">';
5842 $ret .= '<input type="hidden" name="token" value="' . newToken() . '">';
5843 if ($type) {
5844 $ret .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5845 }
5846 $ret .= '<table class="nobordernopadding">';
5847 $ret .= '<tr><td>';
5848 $ret .= $this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form' . $htmlname, 1, 0);
5849 $ret .= '</td>';
5850 $ret .= '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
5851 $ret .= '</tr></table></form>';
5852 } else {
5853 if ($displayhour) {
5854 $ret .= dol_print_date($selected, 'dayhour');
5855 } else {
5856 $ret .= dol_print_date($selected, 'day');
5857 }
5858 }
5859
5860 if (empty($nooutput)) {
5861 print $ret;
5862 }
5863 return $ret;
5864 }
5865
5866
5867 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5868
5879 public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = array(), $include = array())
5880 {
5881 // phpcs:enable
5882 global $langs;
5883
5884 if ($htmlname != "none") {
5885 print '<form method="POST" action="' . $page . '" name="form' . $htmlname . '">';
5886 print '<input type="hidden" name="action" value="set' . $htmlname . '">';
5887 print '<input type="hidden" name="token" value="' . newToken() . '">';
5888 print $this->select_dolusers($selected, $htmlname, 1, $exclude, 0, $include);
5889 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5890 print '</form>';
5891 } else {
5892 if ($selected) {
5893 require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
5894 $theuser = new User($this->db);
5895 $theuser->fetch($selected);
5896 print $theuser->getNomUrl(1);
5897 } else {
5898 print "&nbsp;";
5899 }
5900 }
5901 }
5902
5903
5904 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5905
5919 public function form_modes_reglement($page, $selected = '', $htmlname = 'mode_reglement_id', $filtertype = '', $active = 1, $addempty = 0, $type = '', $nooutput = 0)
5920 {
5921 // phpcs:enable
5922 global $langs;
5923
5924 $out = '';
5925 if ($htmlname != "none") {
5926 $out .= '<form method="POST" action="' . $page . '">';
5927 $out .= '<input type="hidden" name="action" value="setmode">';
5928 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
5929 if ($type) {
5930 $out .= '<input type="hidden" name="type" value="' . dol_escape_htmltag($type) . '">';
5931 }
5932 $out .= $this->select_types_paiements($selected, $htmlname, $filtertype, 0, $addempty, 0, 0, $active, '', 1);
5933 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5934 $out .= '</form>';
5935 } else {
5936 if ($selected) {
5938 $out .= $this->cache_types_paiements[$selected]['label'];
5939 } else {
5940 $out .= "&nbsp;";
5941 }
5942 }
5943
5944 if ($nooutput) {
5945 return $out;
5946 } else {
5947 print $out;
5948 }
5949 return '';
5950 }
5951
5962 public function formSelectTransportMode($page, $selected = '', $htmlname = 'transport_mode_id', $active = 1, $addempty = 0)
5963 {
5964 global $langs;
5965 if ($htmlname != "none") {
5966 print '<form method="POST" action="' . $page . '">';
5967 print '<input type="hidden" name="action" value="settransportmode">';
5968 print '<input type="hidden" name="token" value="' . newToken() . '">';
5969 $this->selectTransportMode($selected, $htmlname, 0, $addempty, 0, 0, $active);
5970 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
5971 print '</form>';
5972 } else {
5973 if ($selected) {
5975 print $this->cache_transport_mode[$selected]['label'];
5976 } else {
5977 print "&nbsp;";
5978 }
5979 }
5980 }
5981
5982 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5983
5992 public function form_multicurrency_code($page, $selected = '', $htmlname = 'multicurrency_code')
5993 {
5994 // phpcs:enable
5995 global $langs;
5996 if ($htmlname != "none") {
5997 print '<form method="POST" action="' . $page . '">';
5998 print '<input type="hidden" name="action" value="setmulticurrencycode">';
5999 print '<input type="hidden" name="token" value="' . newToken() . '">';
6000 print $this->selectMultiCurrency($selected, $htmlname, 0);
6001 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6002 print '</form>';
6003 } else {
6004 dol_include_once('/core/lib/company.lib.php');
6005 print !empty($selected) ? currency_name($selected, 1) : '&nbsp;';
6006 }
6007 }
6008
6009 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6010
6020 public function form_multicurrency_rate($page, $rate = 0.0, $htmlname = 'multicurrency_tx', $currency = '')
6021 {
6022 // phpcs:enable
6023 global $langs, $mysoc, $conf;
6024
6025 if ($htmlname != "none") {
6026 print '<form method="POST" action="' . $page . '">';
6027 print '<input type="hidden" name="action" value="setmulticurrencyrate">';
6028 print '<input type="hidden" name="token" value="' . newToken() . '">';
6029 print '<input type="text" class="maxwidth100" name="' . $htmlname . '" value="' . (!empty($rate) ? price(price2num($rate, 'CU')) : 1) . '" /> ';
6030 print '<select name="calculation_mode">';
6031 print '<option value="1">Change ' . $langs->trans("PriceUHT") . ' of lines</option>';
6032 print '<option value="2">Change ' . $langs->trans("PriceUHTCurrency") . ' of lines</option>';
6033 print '</select> ';
6034 print '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6035 print '</form>';
6036 } else {
6037 if (!empty($rate)) {
6038 print price($rate, 1, $langs, 0, 0);
6039 if ($currency && $rate != 1) {
6040 print ' &nbsp; (' . price($rate, 1, $langs, 0, 0) . ' ' . $currency . ' = 1 ' . $conf->currency . ')';
6041 }
6042 } else {
6043 print 1;
6044 }
6045 }
6046 }
6047
6048
6049 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6050
6066 public function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter = '', $maxvalue = 0, $more = '', $hidelist = 0, $discount_type = 0)
6067 {
6068 // phpcs:enable
6069 global $conf, $langs;
6070 if ($htmlname != "none") {
6071 print '<form method="post" action="' . $page . '">';
6072 print '<input type="hidden" name="action" value="setabsolutediscount">';
6073 print '<input type="hidden" name="token" value="' . newToken() . '">';
6074 print '<div class="inline-block">';
6075 if (!empty($discount_type)) {
6076 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
6077 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL") {
6078 $translationKey = 'HasAbsoluteDiscountFromSupplier'; // If we want deposit to be substracted to payments only and not to total of final invoice
6079 } else {
6080 $translationKey = 'HasCreditNoteFromSupplier';
6081 }
6082 } else {
6083 if (!$filter || $filter == "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6084 $translationKey = 'HasAbsoluteDiscountFromSupplier';
6085 } else {
6086 $translationKey = 'HasCreditNoteFromSupplier';
6087 }
6088 }
6089 } else {
6090 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
6091 if (!$filter || $filter == "fk_facture_source IS NULL") {
6092 $translationKey = 'CompanyHasAbsoluteDiscount'; // If we want deposit to be substracted to payments only and not to total of final invoice
6093 } else {
6094 $translationKey = 'CompanyHasCreditNote';
6095 }
6096 } else {
6097 if (!$filter || $filter == "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6098 $translationKey = 'CompanyHasAbsoluteDiscount';
6099 } else {
6100 $translationKey = 'CompanyHasCreditNote';
6101 }
6102 }
6103 }
6104 print $langs->trans($translationKey, price($amount, 0, $langs, 0, 0, -1, $conf->currency));
6105 if (empty($hidelist)) {
6106 print ' ';
6107 }
6108 print '</div>';
6109 if (empty($hidelist)) {
6110 print '<div class="inline-block" style="padding-right: 10px">';
6111 $newfilter = 'discount_type=' . intval($discount_type);
6112 if (!empty($discount_type)) {
6113 $newfilter .= ' AND fk_invoice_supplier IS NULL AND fk_invoice_supplier_line IS NULL'; // Supplier discounts available
6114 } else {
6115 $newfilter .= ' AND fk_facture IS NULL AND fk_facture_line IS NULL'; // Customer discounts available
6116 }
6117 if ($filter) {
6118 $newfilter .= ' AND (' . $filter . ')';
6119 }
6120 // output the combo of discounts
6121 $nbqualifiedlines = $this->select_remises($selected, $htmlname, $newfilter, $socid, $maxvalue);
6122 if ($nbqualifiedlines > 0) {
6123 print ' &nbsp; <input type="submit" class="button smallpaddingimp" value="' . dol_escape_htmltag($langs->trans("UseLine")) . '"';
6124 if (!empty($discount_type) && $filter && $filter != "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") {
6125 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6126 }
6127 if (empty($discount_type) && $filter && $filter != "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") {
6128 print ' title="' . $langs->trans("UseCreditNoteInInvoicePayment") . '"';
6129 }
6130
6131 print '>';
6132 }
6133 print '</div>';
6134 }
6135 if ($more) {
6136 print '<div class="inline-block">';
6137 print $more;
6138 print '</div>';
6139 }
6140 print '</form>';
6141 } else {
6142 if ($selected) {
6143 print $selected;
6144 } else {
6145 print "0";
6146 }
6147 }
6148 }
6149
6150
6151 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6152
6162 public function form_contacts($page, $societe, $selected = '', $htmlname = 'contactid')
6163 {
6164 // phpcs:enable
6165 global $langs, $conf;
6166
6167 if ($htmlname != "none") {
6168 print '<form method="post" action="' . $page . '">';
6169 print '<input type="hidden" name="action" value="set_contact">';
6170 print '<input type="hidden" name="token" value="' . newToken() . '">';
6171 print '<table class="nobordernopadding">';
6172 print '<tr><td>';
6173 print $this->selectcontacts($societe->id, $selected, $htmlname);
6174 $num = $this->num;
6175 if ($num == 0) {
6176 $addcontact = (getDolGlobalString('SOCIETE_ADDRESSES_MANAGEMENT') ? $langs->trans("AddContact") : $langs->trans("AddContactAddress"));
6177 print '<a href="' . DOL_URL_ROOT . '/contact/card.php?socid=' . $societe->id . '&amp;action=create&amp;backtoreferer=1">' . $addcontact . '</a>';
6178 }
6179 print '</td>';
6180 print '<td class="left"><input type="submit" class="button smallpaddingimp" value="' . $langs->trans("Modify") . '"></td>';
6181 print '</tr></table></form>';
6182 } else {
6183 if ($selected) {
6184 require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
6185 $contact = new Contact($this->db);
6186 $contact->fetch($selected);
6187 print $contact->getFullName($langs);
6188 } else {
6189 print "&nbsp;";
6190 }
6191 }
6192 }
6193
6194 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6195
6212 public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0, $excludeids = array(), $textifnothirdparty = '')
6213 {
6214 // phpcs:enable
6215 global $langs;
6216
6217 $out = '';
6218 if ($htmlname != "none") {
6219 $out .= '<form method="post" action="' . $page . '">';
6220 $out .= '<input type="hidden" name="action" value="set_thirdparty">';
6221 $out .= '<input type="hidden" name="token" value="' . newToken() . '">';
6222 $out .= $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, 0, 'minwidth100', '', '', 1, array(), false, $excludeids);
6223 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="' . $langs->trans("Modify") . '">';
6224 $out .= '</form>';
6225 } else {
6226 if ($selected) {
6227 require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
6228 $soc = new Societe($this->db);
6229 $soc->fetch($selected);
6230 $out .= $soc->getNomUrl(0, '');
6231 } else {
6232 $out .= '<span class="opacitymedium">' . $textifnothirdparty . '</span>';
6233 }
6234 }
6235
6236 if ($nooutput) {
6237 return $out;
6238 } else {
6239 print $out;
6240 }
6241
6242 return '';
6243 }
6244
6245 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6246
6255 public function select_currency($selected = '', $htmlname = 'currency_id')
6256 {
6257 // phpcs:enable
6258 print $this->selectCurrency($selected, $htmlname);
6259 }
6260
6270 public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0, $useempty = '')
6271 {
6272 global $conf, $langs, $user;
6273
6274 $langs->loadCacheCurrencies('');
6275
6276 $out = '';
6277
6278 if ($selected == 'euro' || $selected == 'euros') {
6279 $selected = 'EUR'; // Pour compatibilite
6280 }
6281
6282 $out .= '<select class="flat maxwidth200onsmartphone minwidth300" name="' . $htmlname . '" id="' . $htmlname . '">';
6283 if ($useempty) {
6284 $out .= '<option value="-1" selected></option>';
6285 }
6286 foreach ($langs->cache_currencies as $code_iso => $currency) {
6287 $labeltoshow = $currency['label'];
6288 if ($mode == 1) {
6289 $labeltoshow .= ' <span class="opacitymedium">(' . $code_iso . ')</span>';
6290 } else {
6291 $labeltoshow .= ' <span class="opacitymedium">(' . $langs->getCurrencySymbol($code_iso) . ')</span>';
6292 }
6293
6294 if ($selected && $selected == $code_iso) {
6295 $out .= '<option value="' . $code_iso . '" selected data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6296 } else {
6297 $out .= '<option value="' . $code_iso . '" data-html="' . dol_escape_htmltag($labeltoshow) . '">';
6298 }
6299 $out .= $labeltoshow;
6300 $out .= '</option>';
6301 }
6302 $out .= '</select>';
6303 if ($user->admin) {
6304 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
6305 }
6306
6307 // Make select dynamic
6308 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6309 $out .= ajax_combobox($htmlname);
6310
6311 return $out;
6312 }
6313
6326 public function selectMultiCurrency($selected = '', $htmlname = 'multicurrency_code', $useempty = 0, $filter = '', $excludeConfCurrency = false, $morecss = '')
6327 {
6328 global $conf, $langs;
6329
6330 $langs->loadCacheCurrencies(''); // Load ->cache_currencies
6331
6332 $TCurrency = array();
6333
6334 $sql = "SELECT code FROM " . $this->db->prefix() . "multicurrency";
6335 $sql .= " WHERE entity IN ('" . getEntity('mutlicurrency') . "')";
6336 if ($filter) {
6337 $sql .= " AND " . $filter;
6338 }
6339 $resql = $this->db->query($sql);
6340 if ($resql) {
6341 while ($obj = $this->db->fetch_object($resql)) {
6342 $TCurrency[$obj->code] = $obj->code;
6343 }
6344 }
6345
6346 $out = '';
6347 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
6348 if ($useempty) {
6349 $out .= '<option value="">&nbsp;</option>';
6350 }
6351 // If company current currency not in table, we add it into list. Should always be available.
6352 if (!in_array($conf->currency, $TCurrency) && !$excludeConfCurrency) {
6353 $TCurrency[$conf->currency] = $conf->currency;
6354 }
6355 if (count($TCurrency) > 0) {
6356 foreach ($langs->cache_currencies as $code_iso => $currency) {
6357 if (isset($TCurrency[$code_iso])) {
6358 if (!empty($selected) && $selected == $code_iso) {
6359 $out .= '<option value="' . $code_iso . '" selected="selected">';
6360 } else {
6361 $out .= '<option value="' . $code_iso . '">';
6362 }
6363
6364 $out .= $currency['label'];
6365 $out .= ' (' . $langs->getCurrencySymbol($code_iso) . ')';
6366 $out .= '</option>';
6367 }
6368 }
6369 }
6370
6371 $out .= '</select>';
6372
6373 // Make select dynamic
6374 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6375 $out .= ajax_combobox($htmlname);
6376
6377 return $out;
6378 }
6379
6380 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6381
6388 public function load_cache_vatrates($country_code)
6389 {
6390 // phpcs:enable
6391 global $langs, $user;
6392
6393 $num = count($this->cache_vatrates);
6394 if ($num > 0) {
6395 return $num; // Cache already loaded
6396 }
6397
6398 dol_syslog(__METHOD__, LOG_DEBUG);
6399
6400 $sql = "SELECT DISTINCT t.rowid, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
6401 $sql .= " FROM " . $this->db->prefix() . "c_tva as t, " . $this->db->prefix() . "c_country as c";
6402 $sql .= " WHERE t.fk_pays = c.rowid";
6403 $sql .= " AND t.active > 0";
6404 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
6405 $sql .= " AND c.code IN (" . $this->db->sanitize($country_code, 1) . ")";
6406 $sql .= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC";
6407
6408 $resql = $this->db->query($sql);
6409 if ($resql) {
6410 $num = $this->db->num_rows($resql);
6411 if ($num) {
6412 for ($i = 0; $i < $num; $i++) {
6413 $obj = $this->db->fetch_object($resql);
6414 $this->cache_vatrates[$i]['rowid'] = $obj->rowid;
6415 $this->cache_vatrates[$i]['code'] = $obj->code;
6416 $this->cache_vatrates[$i]['txtva'] = $obj->taux;
6417 $this->cache_vatrates[$i]['nprtva'] = $obj->recuperableonly;
6418 $this->cache_vatrates[$i]['localtax1'] = $obj->localtax1;
6419 $this->cache_vatrates[$i]['localtax1_type'] = $obj->localtax1_type;
6420 $this->cache_vatrates[$i]['localtax2'] = $obj->localtax2;
6421 $this->cache_vatrates[$i]['localtax2_type'] = $obj->localtax1_type;
6422
6423 $this->cache_vatrates[$i]['label'] = $obj->taux . '%' . ($obj->code ? ' (' . $obj->code . ')' : ''); // Label must contains only 0-9 , . % or *
6424 $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
6425 $positiverates = '';
6426 if ($obj->taux) {
6427 $positiverates .= ($positiverates ? '/' : '') . $obj->taux;
6428 }
6429 if ($obj->localtax1) {
6430 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax1;
6431 }
6432 if ($obj->localtax2) {
6433 $positiverates .= ($positiverates ? '/' : '') . $obj->localtax2;
6434 }
6435 if (empty($positiverates)) {
6436 $positiverates = '0';
6437 }
6438 $this->cache_vatrates[$i]['labelpositiverates'] = $positiverates . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
6439 }
6440
6441 return $num;
6442 } else {
6443 $this->error = '<span class="error">';
6444 $this->error .= $langs->trans("ErrorNoVATRateDefinedForSellerCountry", $country_code);
6445 $reg = array();
6446 if (!empty($user) && $user->admin && preg_match('/\'(..)\'/', $country_code, $reg)) {
6447 $langs->load("errors");
6448 $new_country_code = $reg[1];
6449 $country_id = dol_getIdFromCode($this->db, $new_country_code, 'c_pays', 'code', 'rowid');
6450 $this->error .= '<br>'.$langs->trans("ErrorFixThisHere", DOL_URL_ROOT.'/admin/dict.php?id=10'.($country_id > 0 ? '&countryidforinsert='.$country_id : ''));
6451 }
6452 $this->error .= '</span>';
6453 return -1;
6454 }
6455 } else {
6456 $this->error = '<span class="error">' . $this->db->error() . '</span>';
6457 return -2;
6458 }
6459 }
6460
6461 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6462
6484 public function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = null, $societe_acheteuse = null, $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0)
6485 {
6486 // phpcs:enable
6487 global $langs, $conf, $mysoc;
6488
6489 $langs->load('errors');
6490
6491 $return = '';
6492
6493 // Define defaultnpr, defaultttx and defaultcode
6494 $defaultnpr = ($info_bits & 0x01);
6495 $defaultnpr = (preg_match('/\*/', $selectedrate) ? 1 : $defaultnpr);
6496 $defaulttx = str_replace('*', '', $selectedrate);
6497 $defaultcode = '';
6498 $reg = array();
6499 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6500 $defaultcode = $reg[1];
6501 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6502 }
6503 //var_dump($selectedrate.'-'.$defaulttx.'-'.$defaultnpr.'-'.$defaultcode);
6504
6505 // Check parameters
6506 if (is_object($societe_vendeuse) && !$societe_vendeuse->country_code) {
6507 if ($societe_vendeuse->id == $mysoc->id) {
6508 $return .= '<span class="error">' . $langs->trans("ErrorYourCountryIsNotDefined") . '</span>';
6509 } else {
6510 $return .= '<span class="error">' . $langs->trans("ErrorSupplierCountryIsNotDefined") . '</span>';
6511 }
6512 return $return;
6513 }
6514
6515 //var_dump($societe_acheteuse);
6516 //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";
6517 //exit;
6518
6519 // Define list of countries to use to search VAT rates to show
6520 // First we defined code_country to use to find list
6521 if (is_object($societe_vendeuse)) {
6522 $code_country = "'" . $societe_vendeuse->country_code . "'";
6523 } else {
6524 $code_country = "'" . $mysoc->country_code . "'"; // Pour compatibilite ascendente
6525 }
6526 if (getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC')) { // If option to have vat for end customer for services is on
6527 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
6528 // If SERVICE_ARE_ECOMMERCE_200238EC=1 combo list vat rate of purchaser and seller countries
6529 // If SERVICE_ARE_ECOMMERCE_200238EC=2 combo list only the vat rate of the purchaser country
6530 $selectVatComboMode = getDolGlobalString('SERVICE_ARE_ECOMMERCE_200238EC');
6531 if (isInEEC($societe_vendeuse) && isInEEC($societe_acheteuse) && !$societe_acheteuse->isACompany()) {
6532 // We also add the buyer country code
6533 if (is_numeric($type)) {
6534 if ($type == 1) { // We know product is a service
6535 switch ($selectVatComboMode) {
6536 case '1':
6537 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6538 break;
6539 case '2':
6540 $code_country = "'" . $societe_acheteuse->country_code . "'";
6541 break;
6542 }
6543 }
6544 } elseif (!$idprod) { // We don't know type of product
6545 switch ($selectVatComboMode) {
6546 case '1':
6547 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6548 break;
6549 case '2':
6550 $code_country = "'" . $societe_acheteuse->country_code . "'";
6551 break;
6552 }
6553 } else {
6554 $prodstatic = new Product($this->db);
6555 $prodstatic->fetch($idprod);
6556 if ($prodstatic->type == Product::TYPE_SERVICE) { // We know product is a service
6557 $code_country .= ",'" . $societe_acheteuse->country_code . "'";
6558 }
6559 }
6560 }
6561 }
6562
6563 // Now we get list
6564 $num = $this->load_cache_vatrates($code_country); // If no vat at all defined for this country, return -1 with message into this->error
6565
6566 if ($num > 0) {
6567 // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '')
6568 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6569 $tmpthirdparty = new Societe($this->db);
6570
6571 $defaulttx = get_default_tva($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6572 $defaultnpr = get_default_npr($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod);
6573
6574 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6575 $defaultcode = $reg[1];
6576 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6577 }
6578 if (empty($defaulttx)) {
6579 $defaultnpr = 0;
6580 }
6581 }
6582
6583 // If we fails to find a default vat rate, we take the last one in list
6584 // Because they are sorted in ascending order, the last one will be the higher one (we suppose the higher one is the current rate)
6585 if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
6586 if (!getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS')) {
6587 // We take the last one found in list
6588 $defaulttx = $this->cache_vatrates[$num - 1]['txtva'];
6589 } else {
6590 // We will use the rate defined into MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS
6591 $defaulttx = '';
6592 if (getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS') != 'none') {
6593 $defaulttx = $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS;
6594 }
6595 if (preg_match('/\‍((.*)\‍)/', $defaulttx, $reg)) {
6596 $defaultcode = $reg[1];
6597 $defaulttx = preg_replace('/\s*\‍(.*\‍)/', '', $defaulttx);
6598 }
6599 }
6600 }
6601
6602 // Disabled if seller is not subject to VAT
6603 $disabled = false;
6604 $title = '';
6605 if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0") {
6606 // Override/enable VAT for expense report regardless of global setting - needed if expense report used for business expenses instead
6607 // of using supplier invoices (this is a very bad idea !)
6608 if (!getDolGlobalString('EXPENSEREPORT_OVERRIDE_VAT')) {
6609 $title = ' title="' . dol_escape_htmltag($langs->trans('VATIsNotUsed')) . '"';
6610 $disabled = true;
6611 }
6612 }
6613
6614 if (!$options_only) {
6615 $return .= '<select class="flat minwidth50imp maxwidth100" id="' . $htmlname . '" name="' . $htmlname . '"' . ($disabled ? ' disabled' : '') . $title . '>';
6616 }
6617
6618 $selectedfound = false;
6619 foreach ($this->cache_vatrates as $rate) {
6620 // Keep only 0 if seller is not subject to VAT
6621 if ($disabled && $rate['txtva'] != 0) {
6622 continue;
6623 }
6624
6625 // Define key to use into select list
6626 $key = $rate['txtva'];
6627 $key .= $rate['nprtva'] ? '*' : '';
6628 if ($mode > 0 && $rate['code']) {
6629 $key .= ' (' . $rate['code'] . ')';
6630 }
6631 if ($mode < 0) {
6632 $key = $rate['rowid'];
6633 }
6634
6635 $return .= '<option value="' . $key . '"';
6636 if (!$selectedfound) {
6637 if ($defaultcode) { // If defaultcode is defined, we used it in priority to select combo option instead of using rate+npr flag
6638 if ($defaultcode == $rate['code']) {
6639 $return .= ' selected';
6640 $selectedfound = true;
6641 }
6642 } elseif ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr) {
6643 $return .= ' selected';
6644 $selectedfound = true;
6645 }
6646 }
6647 $return .= '>';
6648
6649 // Show label of VAT
6650 if ($mysoc->country_code == 'IN' || getDolGlobalString('MAIN_VAT_LABEL_IS_POSITIVE_RATES')) {
6651 // Label with all localtax and code. For example: x.y / a.b / c.d (CODE)'
6652 $return .= $rate['labelpositiverates'];
6653 } else {
6654 // Simple label
6655 $return .= vatrate($rate['label']);
6656 }
6657
6658 //$return.=($rate['code']?' '.$rate['code']:'');
6659 $return .= (empty($rate['code']) && $rate['nprtva']) ? ' *' : ''; // We show the * (old behaviour only if new vat code is not used)
6660
6661 $return .= '</option>';
6662 }
6663
6664 if (!$options_only) {
6665 $return .= '</select>';
6666 //$return .= ajax_combobox($htmlname); // This break for the moment the dynamic autoselection of a value when selecting a product in object lines
6667 }
6668 } else {
6669 $return .= $this->error;
6670 }
6671
6672 $this->num = $num;
6673 return $return;
6674 }
6675
6676
6677 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6678
6703 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 = '')
6704 {
6705 // phpcs:enable
6706 dol_syslog(__METHOD__ . ': using select_date is deprecated. Use selectDate instead.', LOG_WARNING);
6707 $retstring = $this->selectDate($set_time, $prefix, $h, $m, $empty, $form_name, $d, $addnowlink, $disabled, $fullday, $addplusone, $adddateof);
6708 if (!empty($nooutput)) {
6709 return $retstring;
6710 }
6711 print $retstring;
6712
6713 return '';
6714 }
6715
6731 public function selectDateToDate($set_time = '', $set_time_end = '', $prefix = 're', $empty = 0, $forcenewline = 0)
6732 {
6733 global $langs;
6734
6735 $ret = $this->selectDate($set_time, $prefix . '_start', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("from"), 'tzuserrel');
6736 if ($forcenewline) {
6737 $ret .= '<br>';
6738 }
6739 $ret .= $this->selectDate($set_time_end, $prefix . '_end', 0, 0, $empty, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"), 'tzuserrel');
6740 return $ret;
6741 }
6742
6770 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')
6771 {
6772 global $conf, $langs;
6773
6774 if ($gm === 'auto') {
6775 $gm = (empty($conf) ? 'tzserver' : $conf->tzuserinputkey);
6776 }
6777
6778 $retstring = '';
6779
6780 if ($prefix == '') {
6781 $prefix = 're';
6782 }
6783 if ($h == '') {
6784 $h = 0;
6785 }
6786 if ($m == '') {
6787 $m = 0;
6788 }
6789 $emptydate = 0;
6790 $emptyhours = 0;
6791 if ($stepminutes <= 0 || $stepminutes > 30) {
6792 $stepminutes = 1;
6793 }
6794 if ($empty == 1) {
6795 $emptydate = 1;
6796 $emptyhours = 1;
6797 }
6798 if ($empty == 2) {
6799 $emptydate = 0;
6800 $emptyhours = 1;
6801 }
6802 $orig_set_time = $set_time;
6803
6804 if ($set_time === '' && $emptydate == 0) {
6805 include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
6806 if ($gm == 'tzuser' || $gm == 'tzuserrel') {
6807 $set_time = dol_now($gm);
6808 } else {
6809 $set_time = dol_now('tzuser') - (getServerTimeZoneInt('now') * 3600); // set_time must be relative to PHP server timezone
6810 }
6811 }
6812
6813 // Analysis of the pre-selection date
6814 $reg = array();
6815 $shour = '';
6816 $smin = '';
6817 $ssec = '';
6818 if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', $set_time, $reg)) { // deprecated usage
6819 // Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'
6820 $syear = (!empty($reg[1]) ? $reg[1] : '');
6821 $smonth = (!empty($reg[2]) ? $reg[2] : '');
6822 $sday = (!empty($reg[3]) ? $reg[3] : '');
6823 $shour = (!empty($reg[4]) ? $reg[4] : '');
6824 $smin = (!empty($reg[5]) ? $reg[5] : '');
6825 } elseif (strval($set_time) != '' && $set_time != -1) {
6826 // set_time est un timestamps (0 possible)
6827 $syear = dol_print_date($set_time, "%Y", $gm);
6828 $smonth = dol_print_date($set_time, "%m", $gm);
6829 $sday = dol_print_date($set_time, "%d", $gm);
6830 if ($orig_set_time != '') {
6831 $shour = dol_print_date($set_time, "%H", $gm);
6832 $smin = dol_print_date($set_time, "%M", $gm);
6833 $ssec = dol_print_date($set_time, "%S", $gm);
6834 }
6835 } else {
6836 // Date est '' ou vaut -1
6837 $syear = '';
6838 $smonth = '';
6839 $sday = '';
6840 $shour = !isset($conf->global->MAIN_DEFAULT_DATE_HOUR) ? ($h == -1 ? '23' : '') : $conf->global->MAIN_DEFAULT_DATE_HOUR;
6841 $smin = !isset($conf->global->MAIN_DEFAULT_DATE_MIN) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_MIN;
6842 $ssec = !isset($conf->global->MAIN_DEFAULT_DATE_SEC) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_SEC;
6843 }
6844 if ($h == 3) {
6845 $shour = '';
6846 }
6847 if ($m == 3) {
6848 $smin = '';
6849 }
6850
6851 $nowgmt = dol_now('gmt');
6852 //var_dump(dol_print_date($nowgmt, 'dayhourinputnoreduce', 'tzuserrel'));
6853
6854 // You can set MAIN_POPUP_CALENDAR to 'eldy' or 'jquery'
6855 $usecalendar = 'combo';
6856 if (!empty($conf->use_javascript_ajax) && (!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') != "none")) {
6857 $usecalendar = ((!getDolGlobalString('MAIN_POPUP_CALENDAR') || getDolGlobalString('MAIN_POPUP_CALENDAR') == 'eldy') ? 'jquery' : $conf->global->MAIN_POPUP_CALENDAR);
6858 }
6859
6860 if ($d) {
6861 // Show date with popup
6862 if ($usecalendar != 'combo') {
6863 $formated_date = '';
6864 //print "e".$set_time." t ".$conf->format_date_short;
6865 if (strval($set_time) != '' && $set_time != -1) {
6866 //$formated_date=dol_print_date($set_time,$conf->format_date_short);
6867 $formated_date = dol_print_date($set_time, $langs->trans("FormatDateShortInput"), $gm); // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
6868 }
6869
6870 // Calendrier popup version eldy
6871 if ($usecalendar == "eldy") {
6872 // Input area to enter date manually
6873 $retstring .= '<input id="' . $prefix . '" name="' . $prefix . '" type="text" class="maxwidthdate" maxlength="11" value="' . $formated_date . '"';
6874 $retstring .= ($disabled ? ' disabled' : '');
6875 $retstring .= ' onChange="dpChangeDay(\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
6876 $retstring .= '>';
6877
6878 // Icon calendar
6879 $retstringbuttom = '';
6880 if (!$disabled) {
6881 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons"';
6882 $base = DOL_URL_ROOT . '/core/';
6883 $retstringbuttom .= ' onClick="showDP(\'' . $base . '\',\'' . $prefix . '\',\'' . $langs->trans("FormatDateShortJavaInput") . '\',\'' . $langs->defaultlang . '\');"';
6884 $retstringbuttom .= '>' . img_object($langs->trans("SelectDate"), 'calendarday', 'class="datecallink"') . '</button>';
6885 } else {
6886 $retstringbuttom = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
6887 }
6888 $retstring = $retstringbuttom . $retstring;
6889
6890 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
6891 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
6892 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
6893 } elseif ($usecalendar == 'jquery') {
6894 if (!$disabled) {
6895 // Output javascript for datepicker
6896 $minYear = getDolGlobalInt('MIN_YEAR_SELECT_DATE', (date('Y') - 100));
6897 $maxYear = getDolGlobalInt('MAX_YEAR_SELECT_DATE', (date('Y') + 100));
6898
6899 $retstring .= '<script nonce="' . getNonce() . '" type="text/javascript">';
6900 $retstring .= "$(function(){ $('#" . $prefix . "').datepicker({
6901 dateFormat: '" . $langs->trans("FormatDateShortJQueryInput") . "',
6902 autoclose: true,
6903 todayHighlight: true,
6904 yearRange: '" . $minYear . ":" . $maxYear . "',";
6905 if (!empty($conf->dol_use_jmobile)) {
6906 $retstring .= "
6907 beforeShow: function (input, datePicker) {
6908 input.disabled = true;
6909 },
6910 onClose: function (dateText, datePicker) {
6911 this.disabled = false;
6912 },
6913 ";
6914 }
6915 // Note: We don't need monthNames, monthNamesShort, dayNames, dayNamesShort, dayNamesMin, they are set globally on datepicker component in lib_head.js.php
6916 if (!getDolGlobalString('MAIN_POPUP_CALENDAR_ON_FOCUS')) {
6917 $retstring .= "
6918 showOn: 'button', /* both has problem with autocompletion */
6919 buttonImage: '" . DOL_URL_ROOT . "/theme/" . dol_escape_js($conf->theme) . "/img/object_calendarday.png',
6920 buttonImageOnly: true";
6921 }
6922 $retstring .= "
6923 }) });";
6924 $retstring .= "</script>";
6925 }
6926
6927 // Zone de saisie manuelle de la date
6928 $retstring .= '<div class="nowraponall inline-block divfordateinput">';
6929 $retstring .= '<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidthdate" maxlength="11" value="'.$formated_date.'"';
6930 $retstring .= ($disabled ? ' disabled' : '');
6931 $retstring .= ($placeholder ? ' placeholder="' . dol_escape_htmltag($placeholder) . '"' : '');
6932 $retstring .= ' onChange="dpChangeDay(\'' . dol_escape_js($prefix) . '\',\'' . dol_escape_js($langs->trans("FormatDateShortJavaInput")) . '\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
6933 $retstring .= '>';
6934
6935 // Icone calendrier
6936 if (!$disabled) {
6937 /* Not required. Managed by option buttonImage of jquery
6938 $retstring.=img_object($langs->trans("SelectDate"),'calendarday','id="'.$prefix.'id" class="datecallink"');
6939 $retstring.='<script nonce="'.getNonce().'" type="text/javascript">';
6940 $retstring.="jQuery(document).ready(function() {";
6941 $retstring.=' jQuery("#'.$prefix.'id").click(function() {';
6942 $retstring.=" jQuery('#".$prefix."').focus();";
6943 $retstring.=' });';
6944 $retstring.='});';
6945 $retstring.="</script>";*/
6946 } else {
6947 $retstringbutton = '<button id="' . $prefix . 'Button" type="button" class="dpInvisibleButtons">' . img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"') . '</button>';
6948 $retsring = $retstringbutton . $retstring;
6949 }
6950
6951 $retstring .= '</div>';
6952 $retstring .= '<input type="hidden" id="' . $prefix . 'day" name="' . $prefix . 'day" value="' . $sday . '">' . "\n";
6953 $retstring .= '<input type="hidden" id="' . $prefix . 'month" name="' . $prefix . 'month" value="' . $smonth . '">' . "\n";
6954 $retstring .= '<input type="hidden" id="' . $prefix . 'year" name="' . $prefix . 'year" value="' . $syear . '">' . "\n";
6955 } else {
6956 $retstring .= "Bad value of MAIN_POPUP_CALENDAR";
6957 }
6958 } else {
6959 // Show date with combo selects
6960 // Day
6961 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50imp" id="' . $prefix . 'day" name="' . $prefix . 'day">';
6962
6963 if ($emptydate || $set_time == -1) {
6964 $retstring .= '<option value="0" selected>&nbsp;</option>';
6965 }
6966
6967 for ($day = 1; $day <= 31; $day++) {
6968 $retstring .= '<option value="' . $day . '"' . ($day == $sday ? ' selected' : '') . '>' . $day . '</option>';
6969 }
6970
6971 $retstring .= "</select>";
6972
6973 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'month" name="' . $prefix . 'month">';
6974 if ($emptydate || $set_time == -1) {
6975 $retstring .= '<option value="0" selected>&nbsp;</option>';
6976 }
6977
6978 // Month
6979 for ($month = 1; $month <= 12; $month++) {
6980 $retstring .= '<option value="' . $month . '"' . ($month == $smonth ? ' selected' : '') . '>';
6981 $retstring .= dol_print_date(mktime(12, 0, 0, $month, 1, 2000), "%b");
6982 $retstring .= "</option>";
6983 }
6984 $retstring .= "</select>";
6985
6986 // Year
6987 if ($emptydate || $set_time == -1) {
6988 $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 . '">';
6989 } else {
6990 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth75imp" id="' . $prefix . 'year" name="' . $prefix . 'year">';
6991
6992 for ($year = $syear - 10; $year < $syear + 10; $year++) {
6993 $retstring .= '<option value="' . $year . '"' . ($year == $syear ? ' selected' : '') . '>' . $year . '</option>';
6994 }
6995 $retstring .= "</select>\n";
6996 }
6997 }
6998 }
6999
7000 if ($d && $h) {
7001 $retstring .= ($h == 2 ? '<br>' : ' ');
7002 $retstring .= '<span class="nowraponall">';
7003 }
7004
7005 if ($h) {
7006 $hourstart = 0;
7007 $hourend = 24;
7008 if ($openinghours != '') {
7009 $openinghours = explode(',', $openinghours);
7010 $hourstart = $openinghours[0];
7011 $hourend = $openinghours[1];
7012 if ($hourend < $hourstart) {
7013 $hourend = $hourstart;
7014 }
7015 }
7016 // Show hour
7017 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'hour' : '') . '" id="' . $prefix . 'hour" name="' . $prefix . 'hour">';
7018 if ($emptyhours) {
7019 $retstring .= '<option value="-1">&nbsp;</option>';
7020 }
7021 for ($hour = $hourstart; $hour < $hourend; $hour++) {
7022 if (strlen($hour) < 2) {
7023 $hour = "0" . $hour;
7024 }
7025 $retstring .= '<option value="' . $hour . '"' . (($hour == $shour) ? ' selected' : '') . '>' . $hour;
7026 //$retstring .= (empty($conf->dol_optimize_smallscreen) ? '' : 'H');
7027 $retstring .= '</option>';
7028 }
7029 $retstring .= '</select>';
7030 //if ($m && empty($conf->dol_optimize_smallscreen)) $retstring .= ":";
7031 if ($m) {
7032 $retstring .= ":";
7033 }
7034 }
7035
7036 if ($m) {
7037 // Show minutes
7038 $retstring .= '<select' . ($disabled ? ' disabled' : '') . ' class="flat valignmiddle maxwidth50 ' . ($fullday ? $fullday . 'min' : '') . '" id="' . $prefix . 'min" name="' . $prefix . 'min">';
7039 if ($emptyhours) {
7040 $retstring .= '<option value="-1">&nbsp;</option>';
7041 }
7042 for ($min = 0; $min < 60; $min += $stepminutes) {
7043 if (strlen($min) < 2) {
7044 $min = "0" . $min;
7045 }
7046 $retstring .= '<option value="' . $min . '"' . (($min == $smin) ? ' selected' : '') . '>' . $min . (empty($conf->dol_optimize_smallscreen) ? '' : '') . '</option>';
7047 }
7048 $retstring .= '</select>';
7049
7050 $retstring .= '<input type="hidden" name="' . $prefix . 'sec" value="' . $ssec . '">';
7051 }
7052
7053 if ($d && $h) {
7054 $retstring .= '</span>';
7055 }
7056
7057 // Add a "Now" link
7058 if (!empty($conf->use_javascript_ajax) && $addnowlink) {
7059 // Script which will be inserted in the onClick of the "Now" link
7060 $reset_scripts = "";
7061 if ($addnowlink == 2) { // local computer time
7062 // pad add leading 0 on numbers
7063 $reset_scripts .= "Number.prototype.pad = function(size) {
7064 var s = String(this);
7065 while (s.length < (size || 2)) {s = '0' + s;}
7066 return s;
7067 };
7068 var d = new Date();";
7069 }
7070
7071 // Generate the date part, depending on the use or not of the javascript calendar
7072 if ($addnowlink == 1) { // server time expressed in user time setup
7073 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7074 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7075 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7076 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7077 } elseif ($addnowlink == 2) {
7078 /* Disabled because the output does not use the string format defined by FormatDateShort key to forge the value into #prefix.
7079 * This break application for foreign languages.
7080 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(d.toLocaleDateString(\''.str_replace('_', '-', $langs->defaultlang).'\'));';
7081 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(d.getDate().pad());';
7082 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(parseInt(d.getMonth().pad()) + 1);';
7083 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(d.getFullYear());';
7084 */
7085 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'day', 'tzuserrel') . '\');';
7086 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7087 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7088 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7089 }
7090 /*if ($usecalendar == "eldy")
7091 {
7092 $base=DOL_URL_ROOT.'/core/';
7093 $reset_scripts .= 'resetDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');';
7094 }
7095 else
7096 {
7097 $reset_scripts .= 'this.form.elements[\''.$prefix.'day\'].value=formatDate(new Date(), \'d\'); ';
7098 $reset_scripts .= 'this.form.elements[\''.$prefix.'month\'].value=formatDate(new Date(), \'M\'); ';
7099 $reset_scripts .= 'this.form.elements[\''.$prefix.'year\'].value=formatDate(new Date(), \'yyyy\'); ';
7100 }*/
7101 // Update the hour part
7102 if ($h) {
7103 if ($fullday) {
7104 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7105 }
7106 //$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); ';
7107 if ($addnowlink == 1) {
7108 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7109 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7110 } elseif ($addnowlink == 2) {
7111 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(d.getHours().pad());';
7112 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').change();';
7113 }
7114
7115 if ($fullday) {
7116 $reset_scripts .= ' } ';
7117 }
7118 }
7119 // Update the minute part
7120 if ($m) {
7121 if ($fullday) {
7122 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7123 }
7124 //$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); ';
7125 if ($addnowlink == 1) {
7126 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7127 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7128 } elseif ($addnowlink == 2) {
7129 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(d.getMinutes().pad());';
7130 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').change();';
7131 }
7132 if ($fullday) {
7133 $reset_scripts .= ' } ';
7134 }
7135 }
7136 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7137 if ($reset_scripts && !getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
7138 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonNow" type="button" name="_useless" value="now" onClick="' . $reset_scripts . '">';
7139 $retstring .= $langs->trans("Now");
7140 $retstring .= '</button> ';
7141 }
7142 }
7143
7144 // Add a "Plus one hour" link
7145 if ($conf->use_javascript_ajax && $addplusone) {
7146 // Script which will be inserted in the onClick of the "Add plusone" link
7147 $reset_scripts = "";
7148
7149 // Generate the date part, depending on the use or not of the javascript calendar
7150 $reset_scripts .= 'jQuery(\'#' . $prefix . '\').val(\'' . dol_print_date($nowgmt, 'dayinputnoreduce', 'tzuserrel') . '\');';
7151 $reset_scripts .= 'jQuery(\'#' . $prefix . 'day\').val(\'' . dol_print_date($nowgmt, '%d', 'tzuserrel') . '\');';
7152 $reset_scripts .= 'jQuery(\'#' . $prefix . 'month\').val(\'' . dol_print_date($nowgmt, '%m', 'tzuserrel') . '\');';
7153 $reset_scripts .= 'jQuery(\'#' . $prefix . 'year\').val(\'' . dol_print_date($nowgmt, '%Y', 'tzuserrel') . '\');';
7154 // Update the hour part
7155 if ($h) {
7156 if ($fullday) {
7157 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7158 }
7159 $reset_scripts .= 'jQuery(\'#' . $prefix . 'hour\').val(\'' . dol_print_date($nowgmt, '%H', 'tzuserrel') . '\');';
7160 if ($fullday) {
7161 $reset_scripts .= ' } ';
7162 }
7163 }
7164 // Update the minute part
7165 if ($m) {
7166 if ($fullday) {
7167 $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
7168 }
7169 $reset_scripts .= 'jQuery(\'#' . $prefix . 'min\').val(\'' . dol_print_date($nowgmt, '%M', 'tzuserrel') . '\');';
7170 if ($fullday) {
7171 $reset_scripts .= ' } ';
7172 }
7173 }
7174 // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
7175 if ($reset_scripts && empty($conf->dol_optimize_smallscreen)) {
7176 $retstring .= ' <button class="dpInvisibleButtons datenowlink" id="' . $prefix . 'ButtonPlusOne" type="button" name="_useless2" value="plusone" onClick="' . $reset_scripts . '">';
7177 $retstring .= $langs->trans("DateStartPlusOne");
7178 $retstring .= '</button> ';
7179 }
7180 }
7181
7182 // Add a link to set data
7183 if ($conf->use_javascript_ajax && !empty($adddateof)) {
7184 if (!is_array($adddateof)) {
7185 $arrayofdateof = array(array('adddateof'=>$adddateof, 'labeladddateof'=>$labeladddateof));
7186 } else {
7187 $arrayofdateof = $adddateof;
7188 }
7189 foreach ($arrayofdateof as $valuedateof) {
7190 $tmpadddateof = empty($valuedateof['adddateof']) ? 0 : $valuedateof['adddateof'];
7191 $tmplabeladddateof = empty($valuedateof['labeladddateof']) ? '' : $valuedateof['labeladddateof'];
7192 $tmparray = dol_getdate($tmpadddateof);
7193 if (empty($tmplabeladddateof)) {
7194 $tmplabeladddateof = $langs->trans("DateInvoice");
7195 }
7196 $reset_scripts = 'console.log(\'Click on now link\'); ';
7197 $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date($tmpadddateof, 'dayinputnoreduce').'\');';
7198 $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.$tmparray['mday'].'\');';
7199 $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.$tmparray['mon'].'\');';
7200 $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.$tmparray['year'].'\');';
7201 $retstring .= ' - <button class="dpInvisibleButtons datenowlink" id="dateofinvoice" type="button" name="_dateofinvoice" value="now" onclick="'.$reset_scripts.'">'.$tmplabeladddateof.'</button>';
7202 }
7203 }
7204
7205 return $retstring;
7206 }
7207
7216 public function selectTypeDuration($prefix, $selected = 'i', $excludetypes = array())
7217 {
7218 global $langs;
7219
7220 $TDurationTypes = array(
7221 'y' => $langs->trans('Years'),
7222 'm' => $langs->trans('Month'),
7223 'w' => $langs->trans('Weeks'),
7224 'd' => $langs->trans('Days'),
7225 'h' => $langs->trans('Hours'),
7226 'i' => $langs->trans('Minutes')
7227 );
7228
7229 // Removed undesired duration types
7230 foreach ($excludetypes as $value) {
7231 unset($TDurationTypes[$value]);
7232 }
7233
7234 $retstring = '<select class="flat minwidth75 maxwidth100" id="select_' . $prefix . 'type_duration" name="' . $prefix . 'type_duration">';
7235 foreach ($TDurationTypes as $key => $typeduration) {
7236 $retstring .= '<option value="' . $key . '"';
7237 if ($key == $selected) {
7238 $retstring .= " selected";
7239 }
7240 $retstring .= ">" . $typeduration . "</option>";
7241 }
7242 $retstring .= "</select>";
7243
7244 $retstring .= ajax_combobox('select_' . $prefix . 'type_duration');
7245
7246 return $retstring;
7247 }
7248
7249 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
7250
7264 public function select_duration($prefix, $iSecond = '', $disabled = 0, $typehour = 'select', $minunderhours = 0, $nooutput = 0)
7265 {
7266 // phpcs:enable
7267 global $langs;
7268
7269 $retstring = '<span class="nowraponall">';
7270
7271 $hourSelected = '';
7272 $minSelected = '';
7273
7274 // Hours
7275 if ($iSecond != '') {
7276 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
7277
7278 $hourSelected = convertSecondToTime($iSecond, 'allhour');
7279 $minSelected = convertSecondToTime($iSecond, 'min');
7280 }
7281
7282 if ($typehour == 'select') {
7283 $retstring .= '<select class="flat" id="select_' . $prefix . 'hour" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . '>';
7284 for ($hour = 0; $hour < 25; $hour++) { // For a duration, we allow 24 hours
7285 $retstring .= '<option value="' . $hour . '"';
7286 if (is_numeric($hourSelected) && $hourSelected == $hour) {
7287 $retstring .= " selected";
7288 }
7289 $retstring .= ">" . $hour . "</option>";
7290 }
7291 $retstring .= "</select>";
7292 } elseif ($typehour == 'text' || $typehour == 'textselect') {
7293 $retstring .= '<input placeholder="' . $langs->trans('HourShort') . '" type="number" min="0" name="' . $prefix . 'hour"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputhour right" value="' . (($hourSelected != '') ? ((int) $hourSelected) : '') . '">';
7294 } else {
7295 return 'BadValueForParameterTypeHour';
7296 }
7297
7298 if ($typehour != 'text') {
7299 $retstring .= ' ' . $langs->trans('HourShort');
7300 } else {
7301 $retstring .= '<span class="">:</span>';
7302 }
7303
7304 // Minutes
7305 if ($minunderhours) {
7306 $retstring .= '<br>';
7307 } else {
7308 if ($typehour != 'text') {
7309 $retstring .= '<span class="hideonsmartphone">&nbsp;</span>';
7310 }
7311 }
7312
7313 if ($typehour == 'select' || $typehour == 'textselect') {
7314 $retstring .= '<select class="flat" id="select_' . $prefix . 'min" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . '>';
7315 for ($min = 0; $min <= 55; $min = $min + 5) {
7316 $retstring .= '<option value="' . $min . '"';
7317 if (is_numeric($minSelected) && $minSelected == $min) {
7318 $retstring .= ' selected';
7319 }
7320 $retstring .= '>' . $min . '</option>';
7321 }
7322 $retstring .= "</select>";
7323 } elseif ($typehour == 'text') {
7324 $retstring .= '<input placeholder="' . $langs->trans('MinuteShort') . '" type="number" min="0" name="' . $prefix . 'min"' . ($disabled ? ' disabled' : '') . ' class="flat maxwidth50 inputminute right" value="' . (($minSelected != '') ? ((int) $minSelected) : '') . '">';
7325 }
7326
7327 if ($typehour != 'text') {
7328 $retstring .= ' ' . $langs->trans('MinuteShort');
7329 }
7330
7331 $retstring .= "</span>";
7332
7333 if (!empty($nooutput)) {
7334 return $retstring;
7335 }
7336
7337 print $retstring;
7338
7339 return '';
7340 }
7341
7361 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)
7362 {
7363 global $langs, $conf;
7364
7365 $out = '';
7366
7367 // check parameters
7368 if (is_null($ajaxoptions)) {
7369 $ajaxoptions = array();
7370 }
7371
7372 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7373 $placeholder = '';
7374
7375 if ($selected && empty($selected_input_value)) {
7376 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7377 $tickettmpselect = new Ticket($this->db);
7378 $tickettmpselect->fetch($selected);
7379 $selected_input_value = $tickettmpselect->ref;
7380 unset($tickettmpselect);
7381 }
7382
7383 $urloption = '';
7384 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/ticket/ajax/tickets.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7385
7386 if (empty($hidelabel)) {
7387 $out .= $langs->trans("RefOrLabel") . ' : ';
7388 } elseif ($hidelabel > 1) {
7389 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7390 if ($hidelabel == 2) {
7391 $out .= img_picto($langs->trans("Search"), 'search');
7392 }
7393 }
7394 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7395 if ($hidelabel == 3) {
7396 $out .= img_picto($langs->trans("Search"), 'search');
7397 }
7398 } else {
7399 $out .= $this->selectTicketsList($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss);
7400 }
7401
7402 if (empty($nooutput)) {
7403 print $out;
7404 } else {
7405 return $out;
7406 }
7407 return '';
7408 }
7409
7410
7427 public function selectTicketsList($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7428 {
7429 global $langs, $conf;
7430
7431 $out = '';
7432 $outarray = array();
7433
7434 $selectFields = " p.rowid, p.ref, p.message";
7435
7436 $sql = "SELECT ";
7437 $sql .= $selectFields;
7438 $sql .= " FROM " . $this->db->prefix() . "ticket as p";
7439 $sql .= ' WHERE p.entity IN (' . getEntity('ticket') . ')';
7440
7441 // Add criteria on ref/label
7442 if ($filterkey != '') {
7443 $sql .= ' AND (';
7444 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7445 // For natural search
7446 $scrit = explode(' ', $filterkey);
7447 $i = 0;
7448 if (count($scrit) > 1) {
7449 $sql .= "(";
7450 }
7451 foreach ($scrit as $crit) {
7452 if ($i > 0) {
7453 $sql .= " AND ";
7454 }
7455 $sql .= "(p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%' OR p.subject LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7456 $sql .= ")";
7457 $i++;
7458 }
7459 if (count($scrit) > 1) {
7460 $sql .= ")";
7461 }
7462 $sql .= ')';
7463 }
7464
7465 $sql .= $this->db->plimit($limit, 0);
7466
7467 // Build output string
7468 dol_syslog(get_class($this) . "::selectTicketsList search tickets", LOG_DEBUG);
7469 $result = $this->db->query($sql);
7470 if ($result) {
7471 require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
7472 require_once DOL_DOCUMENT_ROOT . '/core/lib/ticket.lib.php';
7473
7474 $num = $this->db->num_rows($result);
7475
7476 $events = null;
7477
7478 if (!$forcecombo) {
7479 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7480 $out .= ajax_combobox($htmlname, $events, $conf->global->TICKET_USE_SEARCH_TO_SELECT);
7481 }
7482
7483 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7484
7485 $textifempty = '';
7486 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7487 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7488 if (getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7489 if ($showempty && !is_numeric($showempty)) {
7490 $textifempty = $langs->trans($showempty);
7491 } else {
7492 $textifempty .= $langs->trans("All");
7493 }
7494 } else {
7495 if ($showempty && !is_numeric($showempty)) {
7496 $textifempty = $langs->trans($showempty);
7497 }
7498 }
7499 if ($showempty) {
7500 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7501 }
7502
7503 $i = 0;
7504 while ($num && $i < $num) {
7505 $opt = '';
7506 $optJson = array();
7507 $objp = $this->db->fetch_object($result);
7508
7509 $this->constructTicketListOption($objp, $opt, $optJson, $selected, $filterkey);
7510 // Add new entry
7511 // "key" value of json key array is used by jQuery automatically as selected value
7512 // "label" value of json key array is used by jQuery automatically as text for combo box
7513 $out .= $opt;
7514 array_push($outarray, $optJson);
7515
7516 $i++;
7517 }
7518
7519 $out .= '</select>';
7520
7521 $this->db->free($result);
7522
7523 if (empty($outputmode)) {
7524 return $out;
7525 }
7526 return $outarray;
7527 } else {
7528 dol_print_error($this->db);
7529 }
7530
7531 return array();
7532 }
7533
7545 protected function constructTicketListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7546 {
7547 $outkey = '';
7548 $outref = '';
7549 $outtype = '';
7550
7551 $outkey = $objp->rowid;
7552 $outref = $objp->ref;
7553 $outtype = $objp->fk_product_type;
7554
7555 $opt = '<option value="' . $objp->rowid . '"';
7556 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7557 $opt .= '>';
7558 $opt .= $objp->ref;
7559 $objRef = $objp->ref;
7560 if (!empty($filterkey) && $filterkey != '') {
7561 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
7562 }
7563
7564 $opt .= "</option>\n";
7565 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
7566 }
7567
7587 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)
7588 {
7589 global $langs, $conf;
7590
7591 $out = '';
7592
7593 // check parameters
7594 if (is_null($ajaxoptions)) {
7595 $ajaxoptions = array();
7596 }
7597
7598 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7599 $placeholder = '';
7600
7601 if ($selected && empty($selected_input_value)) {
7602 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7603 $projecttmpselect = new Project($this->db);
7604 $projecttmpselect->fetch($selected);
7605 $selected_input_value = $projecttmpselect->ref;
7606 unset($projecttmpselect);
7607 }
7608
7609 $urloption = '';
7610 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/projet/ajax/projects.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7611
7612 if (empty($hidelabel)) {
7613 $out .= $langs->trans("RefOrLabel") . ' : ';
7614 } elseif ($hidelabel > 1) {
7615 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7616 if ($hidelabel == 2) {
7617 $out .= img_picto($langs->trans("Search"), 'search');
7618 }
7619 }
7620 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7621 if ($hidelabel == 3) {
7622 $out .= img_picto($langs->trans("Search"), 'search');
7623 }
7624 } else {
7625 $out .= $this->selectProjectsList($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss);
7626 }
7627
7628 if (empty($nooutput)) {
7629 print $out;
7630 } else {
7631 return $out;
7632 }
7633 return '';
7634 }
7635
7652 public function selectProjectsList($selected = '', $htmlname = 'projectid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7653 {
7654 global $langs, $conf;
7655
7656 $out = '';
7657 $outarray = array();
7658
7659 $selectFields = " p.rowid, p.ref";
7660
7661 $sql = "SELECT ";
7662 $sql .= $selectFields;
7663 $sql .= " FROM " . $this->db->prefix() . "projet as p";
7664 $sql .= ' WHERE p.entity IN (' . getEntity('project') . ')';
7665
7666 // Add criteria on ref/label
7667 if ($filterkey != '') {
7668 $sql .= ' AND (';
7669 $prefix = !getDolGlobalString('TICKET_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7670 // For natural search
7671 $scrit = explode(' ', $filterkey);
7672 $i = 0;
7673 if (count($scrit) > 1) {
7674 $sql .= "(";
7675 }
7676 foreach ($scrit as $crit) {
7677 if ($i > 0) {
7678 $sql .= " AND ";
7679 }
7680 $sql .= "p.ref LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7681 $sql .= "";
7682 $i++;
7683 }
7684 if (count($scrit) > 1) {
7685 $sql .= ")";
7686 }
7687 $sql .= ')';
7688 }
7689
7690 $sql .= $this->db->plimit($limit, 0);
7691
7692 // Build output string
7693 dol_syslog(get_class($this) . "::selectProjectsList search projects", LOG_DEBUG);
7694 $result = $this->db->query($sql);
7695 if ($result) {
7696 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
7697 require_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
7698
7699 $num = $this->db->num_rows($result);
7700
7701 $events = null;
7702
7703 if (!$forcecombo) {
7704 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7705 $out .= ajax_combobox($htmlname, $events, $conf->global->PROJECT_USE_SEARCH_TO_SELECT);
7706 }
7707
7708 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7709
7710 $textifempty = '';
7711 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7712 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7713 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
7714 if ($showempty && !is_numeric($showempty)) {
7715 $textifempty = $langs->trans($showempty);
7716 } else {
7717 $textifempty .= $langs->trans("All");
7718 }
7719 } else {
7720 if ($showempty && !is_numeric($showempty)) {
7721 $textifempty = $langs->trans($showempty);
7722 }
7723 }
7724 if ($showempty) {
7725 $out .= '<option value="0" selected>' . $textifempty . '</option>';
7726 }
7727
7728 $i = 0;
7729 while ($num && $i < $num) {
7730 $opt = '';
7731 $optJson = array();
7732 $objp = $this->db->fetch_object($result);
7733
7734 $this->constructProjectListOption($objp, $opt, $optJson, $selected, $filterkey);
7735 // Add new entry
7736 // "key" value of json key array is used by jQuery automatically as selected value
7737 // "label" value of json key array is used by jQuery automatically as text for combo box
7738 $out .= $opt;
7739 array_push($outarray, $optJson);
7740
7741 $i++;
7742 }
7743
7744 $out .= '</select>';
7745
7746 $this->db->free($result);
7747
7748 if (empty($outputmode)) {
7749 return $out;
7750 }
7751 return $outarray;
7752 } else {
7753 dol_print_error($this->db);
7754 }
7755
7756 return array();
7757 }
7758
7770 protected function constructProjectListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
7771 {
7772 $outkey = '';
7773 $outref = '';
7774 $outtype = '';
7775
7776 $label = $objp->label;
7777
7778 $outkey = $objp->rowid;
7779 $outref = $objp->ref;
7780 $outlabel = $objp->label;
7781 $outtype = $objp->fk_product_type;
7782
7783 $opt = '<option value="' . $objp->rowid . '"';
7784 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
7785 $opt .= '>';
7786 $opt .= $objp->ref;
7787 $objRef = $objp->ref;
7788 if (!empty($filterkey) && $filterkey != '') {
7789 $objRef = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $objRef, 1);
7790 }
7791
7792 $opt .= "</option>\n";
7793 $optJson = array('key' => $outkey, 'value' => $outref, 'type' => $outtype);
7794 }
7795
7796
7816 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)
7817 {
7818 global $langs, $conf;
7819
7820 $out = '';
7821
7822 // check parameters
7823 if (is_null($ajaxoptions)) {
7824 $ajaxoptions = array();
7825 }
7826
7827 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('TICKET_USE_SEARCH_TO_SELECT')) {
7828 $placeholder = '';
7829 $urloption = '';
7830
7831 if ($selected && empty($selected_input_value)) {
7832 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
7833 $adherenttmpselect = new Adherent($this->db);
7834 $adherenttmpselect->fetch($selected);
7835 $selected_input_value = $adherenttmpselect->ref;
7836 unset($adherenttmpselect);
7837 }
7838
7839 $urloption = '';
7840
7841 $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT . '/adherents/ajax/adherents.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
7842
7843 if (empty($hidelabel)) {
7844 $out .= $langs->trans("RefOrLabel") . ' : ';
7845 } elseif ($hidelabel > 1) {
7846 $placeholder = ' placeholder="' . $langs->trans("RefOrLabel") . '"';
7847 if ($hidelabel == 2) {
7848 $out .= img_picto($langs->trans("Search"), 'search');
7849 }
7850 }
7851 $out .= '<input type="text" class="minwidth100" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (getDolGlobalString('PRODUCT_SEARCH_AUTOFOCUS') ? 'autofocus' : '') . ' />';
7852 if ($hidelabel == 3) {
7853 $out .= img_picto($langs->trans("Search"), 'search');
7854 }
7855 } else {
7856 $filterkey = '';
7857
7858 $out .= $this->selectMembersList($selected, $htmlname, $filtertype, $limit, $filterkey, $status, 0, $showempty, $forcecombo, $morecss);
7859 }
7860
7861 if (empty($nooutput)) {
7862 print $out;
7863 } else {
7864 return $out;
7865 }
7866 return '';
7867 }
7868
7885 public function selectMembersList($selected = '', $htmlname = 'adherentid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
7886 {
7887 global $langs, $conf;
7888
7889 $out = '';
7890 $outarray = array();
7891
7892 $selectFields = " p.rowid, p.ref, p.firstname, p.lastname, p.fk_adherent_type";
7893
7894 $sql = "SELECT ";
7895 $sql .= $selectFields;
7896 $sql .= " FROM " . $this->db->prefix() . "adherent as p";
7897 $sql .= ' WHERE p.entity IN (' . getEntity('adherent') . ')';
7898
7899 // Add criteria on ref/label
7900 if ($filterkey != '') {
7901 $sql .= ' AND (';
7902 $prefix = !getDolGlobalString('MEMBER_DONOTSEARCH_ANYWHERE') ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
7903 // For natural search
7904 $scrit = explode(' ', $filterkey);
7905 $i = 0;
7906 if (count($scrit) > 1) {
7907 $sql .= "(";
7908 }
7909 foreach ($scrit as $crit) {
7910 if ($i > 0) {
7911 $sql .= " AND ";
7912 }
7913 $sql .= "(p.firstname LIKE '" . $this->db->escape($prefix . $crit) . "%'";
7914 $sql .= " OR p.lastname LIKE '" . $this->db->escape($prefix . $crit) . "%')";
7915 $i++;
7916 }
7917 if (count($scrit) > 1) {
7918 $sql .= ")";
7919 }
7920 $sql .= ')';
7921 }
7922 if ($status != -1) {
7923 $sql .= ' AND statut = ' . ((int) $status);
7924 }
7925 $sql .= $this->db->plimit($limit, 0);
7926
7927 // Build output string
7928 dol_syslog(get_class($this) . "::selectMembersList search adherents", LOG_DEBUG);
7929 $result = $this->db->query($sql);
7930 if ($result) {
7931 require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
7932 require_once DOL_DOCUMENT_ROOT . '/core/lib/member.lib.php';
7933
7934 $num = $this->db->num_rows($result);
7935
7936 $events = null;
7937
7938 if (!$forcecombo) {
7939 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7940 $out .= ajax_combobox($htmlname, $events, getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT') ? $conf->global->PROJECT_USE_SEARCH_TO_SELECT : '');
7941 }
7942
7943 $out .= '<select class="flat' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '" id="' . $htmlname . '">';
7944
7945 $textifempty = '';
7946 // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
7947 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
7948 if (getDolGlobalString('PROJECT_USE_SEARCH_TO_SELECT')) {
7949 if ($showempty && !is_numeric($showempty)) {
7950 $textifempty = $langs->trans($showempty);
7951 } else {
7952 $textifempty .= $langs->trans("All");
7953 }
7954 } else {
7955 if ($showempty && !is_numeric($showempty)) {
7956 $textifempty = $langs->trans($showempty);
7957 }
7958 }
7959 if ($showempty) {
7960 $out .= '<option value="-1" selected>' . $textifempty . '</option>';
7961 }
7962
7963 $i = 0;
7964 while ($num && $i < $num) {
7965 $opt = '';
7966 $optJson = array();
7967 $objp = $this->db->fetch_object($result);
7968
7969 $this->constructMemberListOption($objp, $opt, $optJson, $selected, $filterkey);
7970
7971 // Add new entry
7972 // "key" value of json key array is used by jQuery automatically as selected value
7973 // "label" value of json key array is used by jQuery automatically as text for combo box
7974 $out .= $opt;
7975 array_push($outarray, $optJson);
7976
7977 $i++;
7978 }
7979
7980 $out .= '</select>';
7981
7982 $this->db->free($result);
7983
7984 if (empty($outputmode)) {
7985 return $out;
7986 }
7987 return $outarray;
7988 } else {
7989 dol_print_error($this->db);
7990 }
7991
7992 return array();
7993 }
7994
8006 protected function constructMemberListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
8007 {
8008 $outkey = '';
8009 $outlabel = '';
8010 $outtype = '';
8011
8012 $outkey = $objp->rowid;
8013 $outlabel = dolGetFirstLastname($objp->firstname, $objp->lastname);
8014 $outtype = $objp->fk_adherent_type;
8015
8016 $opt = '<option value="' . $objp->rowid . '"';
8017 $opt .= ($objp->rowid == $selected) ? ' selected' : '';
8018 $opt .= '>';
8019 if (!empty($filterkey) && $filterkey != '') {
8020 $outlabel = preg_replace('/(' . preg_quote($filterkey, '/') . ')/i', '<strong>$1</strong>', $outlabel, 1);
8021 }
8022 $opt .= $outlabel;
8023 $opt .= "</option>\n";
8024
8025 $optJson = array('key' => $outkey, 'value' => $outlabel, 'type' => $outtype);
8026 }
8027
8048 public function selectForForms($objectdesc, $htmlname, $preSelectedValue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '', $objectfield = '')
8049 {
8050 global $conf, $extrafields, $user;
8051
8052 //var_dump($objectdesc); debug_print_backtrace();
8053
8054 $objectdescorig = $objectdesc;
8055 $objecttmp = null;
8056 $InfoFieldList = array();
8057
8058 if ($objectfield) { // We must retreive the objectdesc from the field or extrafield
8059 // Example: $objectfield = 'product:options_package'
8060 $tmparray = explode(':', $objectfield);
8061
8062 // Load object according to $id and $element
8063 $objectforfieldstmp = fetchObjectByElement(0, strtolower($tmparray[0]));
8064
8065 if (is_object($objectforfieldstmp)) {
8066 $objectdesc = '';
8067
8068 $reg = array();
8069 if (preg_match('/^options_(.*)$/', $tmparray[1], $reg)) {
8070 // For a property in extrafields
8071 $key = $reg[1];
8072 // fetch optionals attributes and labels
8073 $extrafields->fetch_name_optionals_label($objectforfieldstmp->table_element);
8074
8075 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key]) && $extrafields->attributes[$objectforfieldstmp->table_element]['type'][$key] == 'link') {
8076 if (!empty($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options'])) {
8077 $tmpextrafields = array_keys($extrafields->attributes[$objectforfieldstmp->table_element]['param'][$key]['options']);
8078 $objectdesc = $tmpextrafields[0];
8079 }
8080 }
8081 } else {
8082 // For a property in ->fields
8083 if (array_key_exists($tmparray[1], $objectforfieldstmp->fields)) {
8084 $objectdesc = $objectforfieldstmp->fields[$tmparray[1]]['type'];
8085 $objectdesc = preg_replace('/^integer[^:]*:/', '', $objectdesc);
8086 }
8087 }
8088 }
8089 }
8090
8091 if ($objectdesc) {
8092 // Example of value for $objectdesc:
8093 // Bom:bom/class/bom.class.php:0:t.status=1
8094 // Bom:bom/class/bom.class.php:0:t.status=1:ref
8095 // Bom:bom/class/bom.class.php:0:(t.status:=:1) OR (t.field2:=:2):ref
8096 $InfoFieldList = explode(":", $objectdesc, 4);
8097 $vartmp = (empty($InfoFieldList[3]) ? '' : $InfoFieldList[3]);
8098 $reg = array();
8099 if (preg_match('/^.*:(\w*)$/', $vartmp, $reg)) {
8100 $InfoFieldList[4] = $reg[1]; // take the sort field
8101 }
8102 $InfoFieldList[3] = preg_replace('/:\w*$/', '', $vartmp); // take the filter field
8103
8104 $classname = $InfoFieldList[0];
8105 $classpath = empty($InfoFieldList[1]) ? '' : $InfoFieldList[1];
8106 //$addcreatebuttonornot = empty($InfoFieldList[2]) ? 0 : $InfoFieldList[2];
8107 $filter = empty($InfoFieldList[3]) ? '' : $InfoFieldList[3];
8108 $sortfield = empty($InfoFieldList[4]) ? '' : $InfoFieldList[4];
8109
8110 // Load object according to $id and $element
8111 $objecttmp = fetchObjectByElement(0, strtolower($InfoFieldList[0]));
8112
8113 // Fallback to another solution to get $objecttmp
8114 if (empty($objecttmp) && !empty($classpath)) {
8115 dol_include_once($classpath);
8116
8117 if ($classname && class_exists($classname)) {
8118 $objecttmp = new $classname($this->db);
8119 }
8120 }
8121 }
8122
8123 // Make some replacement in $filter. May not be used if we used the ajax mode with $objectfield. In such a case
8124 // we propagate the $objectfield and not the filter and replacement is done by the ajax/selectobject.php component.
8125 $sharedentities = getEntity($objecttmp->element);
8126 $filter = str_replace(
8127 array('__ENTITY__', '__SHARED_ENTITIES__', '__USER_ID__'),
8128 array($conf->entity, $sharedentities, $user->id),
8129 $filter
8130 );
8131
8132 if (!is_object($objecttmp)) {
8133 dol_syslog('selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc, LOG_WARNING);
8134 return 'selectForForms: Error bad setup of field objectdescorig=' . $objectdescorig.', objectfield='.$objectfield.', objectdesc='.$objectdesc;
8135 }
8136
8137 //var_dump($filter);
8138 $prefixforautocompletemode = $objecttmp->element;
8139 if ($prefixforautocompletemode == 'societe') {
8140 $prefixforautocompletemode = 'company';
8141 }
8142 if ($prefixforautocompletemode == 'product') {
8143 $prefixforautocompletemode = 'produit';
8144 }
8145 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8146
8147 dol_syslog(get_class($this) . "::selectForForms filter=" . $filter, LOG_DEBUG);
8148
8149 // Generate the combo HTML component
8150 $out = '';
8151 if (!empty($conf->use_javascript_ajax) && getDolGlobalString($confkeyforautocompletemode) && !$forcecombo) {
8152 // No immediate load of all database
8153 $placeholder = '';
8154
8155 if ($preSelectedValue && empty($selected_input_value)) {
8156 $objecttmp->fetch($preSelectedValue);
8157 $selected_input_value = ($prefixforautocompletemode == 'company' ? $objecttmp->name : $objecttmp->ref);
8158
8159 $oldValueForShowOnCombobox = 0;
8160 foreach ($objecttmp->fields as $fieldK => $fielV) {
8161 if (!array_key_exists('showoncombobox', $fielV) || !$fielV['showoncombobox'] || empty($objecttmp->$fieldK)) continue;
8162
8163 if (!$oldValueForShowOnCombobox) {
8164 $selected_input_value = '';
8165 }
8166
8167 $selected_input_value .= $oldValueForShowOnCombobox ? ' - ' : '';
8168 $selected_input_value .= $objecttmp->$fieldK;
8169 $oldValueForShowOnCombobox = empty($fielV['showoncombobox']) ? 0 : $fielV['showoncombobox'];
8170 }
8171 }
8172
8173 // Set url and param to call to get json of the search results
8174 $urlforajaxcall = DOL_URL_ROOT . '/core/ajax/selectobject.php';
8175 $urloption = 'htmlname=' . urlencode($htmlname) . '&outjson=1&objectdesc=' . urlencode($objectdescorig) . '&objectfield='.urlencode($objectfield) . ($sortfield ? '&sortfield=' . urlencode($sortfield) : '');
8176
8177 // Activate the auto complete using ajax call.
8178 $out .= ajax_autocompleter($preSelectedValue, $htmlname, $urlforajaxcall, $urloption, getDolGlobalString($confkeyforautocompletemode), 0);
8179 $out .= '<!-- force css to be higher than dialog popup --><style type="text/css">.ui-autocomplete { z-index: 1010; }</style>';
8180 $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) . '"' : '') . ' />';
8181 } else {
8182 // Immediate load of table record.
8183 $out .= $this->selectForFormsList($objecttmp, $htmlname, $preSelectedValue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, 0, $disabled, $sortfield, $filter);
8184 }
8185
8186 return $out;
8187 }
8188
8189
8210 public function selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $outputmode = 0, $disabled = 0, $sortfield = '', $filter = '')
8211 {
8212 global $langs, $user, $hookmanager;
8213
8214 //print "$htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, $outputmode, $disabled";
8215
8216 $prefixforautocompletemode = $objecttmp->element;
8217 if ($prefixforautocompletemode == 'societe') {
8218 $prefixforautocompletemode = 'company';
8219 }
8220 $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
8221
8222 if (!empty($objecttmp->fields)) { // For object that declare it, it is better to use declared fields (like societe, contact, ...)
8223 $tmpfieldstoshow = '';
8224 foreach ($objecttmp->fields as $key => $val) {
8225 if (!dol_eval($val['enabled'], 1, 1, '1')) {
8226 continue;
8227 }
8228 if (!empty($val['showoncombobox'])) {
8229 $tmpfieldstoshow .= ($tmpfieldstoshow ? ',' : '') . 't.' . $key;
8230 }
8231 }
8232 if ($tmpfieldstoshow) {
8233 $fieldstoshow = $tmpfieldstoshow;
8234 }
8235 } else {
8236 // For backward compatibility
8237 $objecttmp->fields['ref'] = array('type' => 'varchar(30)', 'label' => 'Ref', 'showoncombobox' => 1);
8238 }
8239
8240 if (empty($fieldstoshow)) {
8241 if (isset($objecttmp->fields['ref'])) {
8242 $fieldstoshow = 't.ref';
8243 } else {
8244 $langs->load("errors");
8245 $this->error = $langs->trans("ErrorNoFieldWithAttributeShowoncombobox");
8246 return $langs->trans('ErrorNoFieldWithAttributeShowoncombobox');
8247 }
8248 }
8249
8250 $out = '';
8251 $outarray = array();
8252 $tmparray = array();
8253
8254 $num = 0;
8255
8256 // Search data
8257 $sql = "SELECT t.rowid, " . $fieldstoshow . " FROM " . $this->db->prefix() . $objecttmp->table_element . " as t";
8258 if (!empty($objecttmp->isextrafieldmanaged)) {
8259 $sql .= " LEFT JOIN " . $this->db->prefix() . $objecttmp->table_element . "_extrafields as e ON t.rowid=e.fk_object";
8260 }
8261 if (isset($objecttmp->ismultientitymanaged)) {
8262 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8263 $tmparray = explode('@', $objecttmp->ismultientitymanaged);
8264 $sql .= " INNER JOIN " . $this->db->prefix() . $tmparray[1] . " as parenttable ON parenttable.rowid = t." . $tmparray[0];
8265 }
8266 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8267 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
8268 $sql .= ", " . $this->db->prefix() . "societe_commerciaux as sc";
8269 }
8270 }
8271 }
8272
8273 // Add where from hooks
8274 $parameters = array(
8275 'object' => $objecttmp,
8276 'htmlname' => $htmlname,
8277 'filter' => $filter,
8278 'searchkey' => $searchkey
8279 );
8280
8281 $reshook = $hookmanager->executeHooks('selectForFormsListWhere', $parameters); // Note that $action and $object may have been modified by hook
8282 if (!empty($hookmanager->resPrint)) {
8283 $sql .= $hookmanager->resPrint;
8284 } else {
8285 $sql .= " WHERE 1=1";
8286 if (isset($objecttmp->ismultientitymanaged)) {
8287 if ($objecttmp->ismultientitymanaged == 1) {
8288 $sql .= " AND t.entity IN (" . getEntity($objecttmp->table_element) . ")";
8289 }
8290 if (!is_numeric($objecttmp->ismultientitymanaged)) {
8291 $sql .= " AND parenttable.entity = t." . $tmparray[0];
8292 }
8293 if ($objecttmp->ismultientitymanaged == 1 && !empty($user->socid)) {
8294 if ($objecttmp->element == 'societe') {
8295 $sql .= " AND t.rowid = " . ((int) $user->socid);
8296 } else {
8297 $sql .= " AND t.fk_soc = " . ((int) $user->socid);
8298 }
8299 }
8300 if ($objecttmp->ismultientitymanaged === 'fk_soc@societe') {
8301 if (!$user->hasRight('societe', 'client', 'voir') && !$user->socid) {
8302 $sql .= " AND t.rowid = sc.fk_soc AND sc.fk_user = " . ((int) $user->id);
8303 }
8304 }
8305 }
8306 if ($searchkey != '') {
8307 $sql .= natural_search(explode(',', $fieldstoshow), $searchkey);
8308 }
8309
8310 if ($filter) { // Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
8311 $errormessage = '';
8312 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
8313 if ($errormessage) {
8314 return 'Error forging a SQL request from an universal criteria: ' . $errormessage;
8315 }
8316 }
8317 }
8318 $sql .= $this->db->order($sortfield ? $sortfield : $fieldstoshow, "ASC");
8319 //$sql.=$this->db->plimit($limit, 0);
8320 //print $sql;
8321
8322 // Build output string
8323 $resql = $this->db->query($sql);
8324 if ($resql) {
8325 // Construct $out and $outarray
8326 $out .= '<select id="' . $htmlname . '" class="flat minwidth100' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ($moreparams ? ' ' . $moreparams : '') . ' name="' . $htmlname . '">' . "\n";
8327
8328 // 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
8329 $textifempty = '&nbsp;';
8330
8331 //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
8332 if (getDolGlobalInt($confkeyforautocompletemode)) {
8333 if ($showempty && !is_numeric($showempty)) {
8334 $textifempty = $langs->trans($showempty);
8335 } else {
8336 $textifempty .= $langs->trans("All");
8337 }
8338 }
8339 if ($showempty) {
8340 $out .= '<option value="-1">' . $textifempty . '</option>' . "\n";
8341 }
8342
8343 $num = $this->db->num_rows($resql);
8344 $i = 0;
8345 if ($num) {
8346 while ($i < $num) {
8347 $obj = $this->db->fetch_object($resql);
8348 $label = '';
8349 $labelhtml = '';
8350 $tmparray = explode(',', $fieldstoshow);
8351 $oldvalueforshowoncombobox = 0;
8352 foreach ($tmparray as $key => $val) {
8353 $val = preg_replace('/t\./', '', $val);
8354 $label .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8355 $labelhtml .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
8356 $label .= $obj->$val;
8357 $labelhtml .= $obj->$val;
8358
8359 $oldvalueforshowoncombobox = empty($objecttmp->fields[$val]['showoncombobox']) ? 0 : $objecttmp->fields[$val]['showoncombobox'];
8360 }
8361 if (empty($outputmode)) {
8362 if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid) {
8363 $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>';
8364 } else {
8365 $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
8366 }
8367 } else {
8368 array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label));
8369 }
8370
8371 $i++;
8372 if (($i % 10) == 0) {
8373 $out .= "\n";
8374 }
8375 }
8376 }
8377
8378 $out .= '</select>' . "\n";
8379
8380 if (!$forcecombo) {
8381 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8382 $out .= ajax_combobox($htmlname, null, getDolGlobalInt($confkeyforautocompletemode, 0));
8383 }
8384 } else {
8385 dol_print_error($this->db);
8386 }
8387
8388 $this->result = array('nbofelement' => $num);
8389
8390 if ($outputmode) {
8391 return $outarray;
8392 }
8393 return $out;
8394 }
8395
8396
8420 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)
8421 {
8422 global $conf, $langs;
8423
8424 // Do we want a multiselect ?
8425 //$jsbeautify = 0;
8426 //if (preg_match('/^multi/',$htmlname)) $jsbeautify = 1;
8427 $jsbeautify = 1;
8428
8429 if ($value_as_key) {
8430 $array = array_combine($array, $array);
8431 }
8432
8433 $out = '';
8434
8435 if ($addjscombo < 0) {
8436 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8437 $addjscombo = 1;
8438 } else {
8439 $addjscombo = 0;
8440 }
8441 }
8442 $idname = str_replace(array('[', ']'), array('', ''), $htmlname);
8443 $out .= '<select id="' . preg_replace('/^\./', '', $idname) . '" ' . ($disabled ? 'disabled="disabled" ' : '') . 'class="flat ' . (preg_replace('/^\./', '', $htmlname)) . ($morecss ? ' ' . $morecss : '') . ' selectformat"';
8444 $out .= ' name="' . preg_replace('/^\./', '', $htmlname) . '" ' . ($moreparam ? $moreparam : '');
8445 $out .= '>'."\n";
8446
8447 if ($show_empty) {
8448 $textforempty = ' ';
8449 if (!empty($conf->use_javascript_ajax)) {
8450 $textforempty = '&nbsp;'; // If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
8451 }
8452 if (!is_numeric($show_empty)) {
8453 $textforempty = $show_empty;
8454 }
8455 $out .= '<option class="optiongrey" ' . ($moreparamonempty ? $moreparamonempty . ' ' : '') . 'value="' . (((int) $show_empty) < 0 ? $show_empty : -1) . '"' . ($id == $show_empty ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
8456 }
8457 if (is_array($array)) {
8458 // Translate
8459 if ($translate) {
8460 foreach ($array as $key => $value) {
8461 if (!is_array($value)) {
8462 $array[$key] = $langs->trans($value);
8463 } else {
8464 $array[$key]['label'] = $langs->trans($value['label']);
8465 }
8466 }
8467 }
8468 // Sort
8469 if ($sort == 'ASC') {
8470 asort($array);
8471 } elseif ($sort == 'DESC') {
8472 arsort($array);
8473 }
8474 foreach ($array as $key => $tmpvalue) {
8475 if (is_array($tmpvalue)) {
8476 $value = $tmpvalue['label'];
8477 $disabled = empty($tmpvalue['disabled']) ? '' : ' disabled';
8478 $style = empty($tmpvalue['css']) ? '' : ' class="' . $tmpvalue['css'] . '"';
8479 } else {
8480 $value = $tmpvalue;
8481 $disabled = '';
8482 $style = '';
8483 }
8484 if (!empty($disablebademail)) {
8485 if (($disablebademail == 1 && !preg_match('/&lt;.+@.+&gt;/', $value))
8486 || ($disablebademail == 2 && preg_match('/---/', $value))) {
8487 $disabled = ' disabled';
8488 $style = ' class="warning"';
8489 }
8490 }
8491 if ($key_in_label) {
8492 if (empty($nohtmlescape)) {
8493 $selectOptionValue = dol_escape_htmltag($key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value));
8494 } else {
8495 $selectOptionValue = $key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value);
8496 }
8497 } else {
8498 if (empty($nohtmlescape)) {
8499 $selectOptionValue = dol_escape_htmltag($maxlen ? dol_trunc($value, $maxlen) : $value);
8500 } else {
8501 $selectOptionValue = $maxlen ? dol_trunc($value, $maxlen) : $value;
8502 }
8503 if ($value == '' || $value == '-') {
8504 $selectOptionValue = '&nbsp;';
8505 }
8506 }
8507 $out .= '<option value="' . $key . '"';
8508 $out .= $style . $disabled;
8509 if (is_array($id)) {
8510 if (in_array($key, $id) && !$disabled) {
8511 $out .= ' selected'; // To preselect a value
8512 }
8513 } else {
8514 $id = (string) $id; // if $id = 0, then $id = '0'
8515 if ($id != '' && ($id == $key || ($id == 'ifone' && count($array) == 1)) && !$disabled) {
8516 $out .= ' selected'; // To preselect a value
8517 }
8518 }
8519 if ($nohtmlescape) {
8520 $out .= ' data-html="' . dol_escape_htmltag($selectOptionValue) . '"';
8521 }
8522 if (is_array($tmpvalue)) {
8523 foreach ($tmpvalue as $keyforvalue => $valueforvalue) {
8524 if (preg_match('/^data-/', $keyforvalue)) {
8525 $out .= ' '.$keyforvalue.'="'.dol_escape_htmltag($valueforvalue).'"';
8526 }
8527 }
8528 }
8529 $out .= '>';
8530 $out .= $selectOptionValue;
8531 $out .= "</option>\n";
8532 }
8533 }
8534 $out .= "</select>";
8535 // Add code for jquery to use multiselect
8536 if ($addjscombo && $jsbeautify) {
8537 // Enhance with select2
8538 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
8539 $out .= ajax_combobox($idname, array(), 0, 0, 'resolve', (((int) $show_empty) < 0 ? (string) $show_empty : '-1'), $morecss);
8540 }
8541
8542 return $out;
8543 }
8544
8563 public static function selectArrayAjax($htmlname, $url, $id = '', $moreparam = '', $moreparamtourl = '', $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0)
8564 {
8565 global $conf, $langs;
8566 global $delayedhtmlcontent; // Will be used later outside of this function
8567
8568 // TODO Use an internal dolibarr component instead of select2
8569 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8570 return '';
8571 }
8572
8573 $out = '<select type="text" class="' . $htmlname . ($morecss ? ' ' . $morecss : '') . '" ' . ($moreparam ? $moreparam . ' ' : '') . 'name="' . $htmlname . '"></select>';
8574
8575 $outdelayed = '';
8576 if (!empty($conf->use_javascript_ajax)) {
8577 $tmpplugin = 'select2';
8578 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8579 <script nonce="' . getNonce() . '">
8580 $(document).ready(function () {
8581
8582 ' . ($callurlonselect ? 'var saveRemoteData = [];' : '') . '
8583
8584 $(".' . $htmlname . '").select2({
8585 ajax: {
8586 dir: "ltr",
8587 url: "' . $url . '",
8588 dataType: \'json\',
8589 delay: 250,
8590 data: function (params) {
8591 return {
8592 q: params.term, // search term
8593 page: params.page
8594 }
8595 },
8596 processResults: function (data) {
8597 // parse the results into the format expected by Select2.
8598 // since we are using custom formatting functions we do not need to alter the remote JSON data
8599 //console.log(data);
8600 saveRemoteData = data;
8601 /* format json result for select2 */
8602 result = []
8603 $.each( data, function( key, value ) {
8604 result.push({id: key, text: value.text});
8605 });
8606 //return {results:[{id:\'none\', text:\'aa\'}, {id:\'rrr\', text:\'Red\'},{id:\'bbb\', text:\'Search a into projects\'}], more:false}
8607 //console.log(result);
8608 return {results: result, more: false}
8609 },
8610 cache: true
8611 },
8612 language: select2arrayoflanguage,
8613 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8614 placeholder: "' . dol_escape_js($placeholder) . '",
8615 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8616 minimumInputLength: ' . ((int) $minimumInputLength) . ',
8617 formatResult: function (result, container, query, escapeMarkup) {
8618 return escapeMarkup(result.text);
8619 },
8620 });
8621
8622 ' . ($callurlonselect ? '
8623 /* Code to execute a GET when we select a value */
8624 $(".' . $htmlname . '").change(function() {
8625 var selected = $(".' . $htmlname . '").val();
8626 console.log("We select in selectArrayAjax the entry "+selected)
8627 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8628 $.each( saveRemoteData, function( key, value ) {
8629 if (key == selected)
8630 {
8631 console.log("selectArrayAjax - Do a redirect to "+value.url)
8632 location.assign(value.url);
8633 }
8634 });
8635 });' : '') . '
8636
8637 });
8638 </script>';
8639 }
8640
8641 if ($acceptdelayedhtml) {
8642 $delayedhtmlcontent .= $outdelayed;
8643 } else {
8644 $out .= $outdelayed;
8645 }
8646 return $out;
8647 }
8648
8668 public static function selectArrayFilter($htmlname, $array, $id = '', $moreparam = '', $disableFiltering = 0, $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0, $textfortitle = '')
8669 {
8670 global $conf, $langs;
8671 global $delayedhtmlcontent; // Will be used later outside of this function
8672
8673 // TODO Use an internal dolibarr component instead of select2
8674 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
8675 return '';
8676 }
8677
8678 $out = '<select type="text"'.($textfortitle ? ' title="'.dol_escape_htmltag($textfortitle).'"' : '').' id="'.$htmlname.'" class="'.$htmlname.($morecss ? ' ' . $morecss : '').'"'.($moreparam ? ' '.$moreparam : '').' name="'.$htmlname.'"><option></option></select>';
8679
8680 $formattedarrayresult = array();
8681
8682 foreach ($array as $key => $value) {
8683 $o = new stdClass();
8684 $o->id = $key;
8685 $o->text = $value['text'];
8686 $o->url = $value['url'];
8687 $formattedarrayresult[] = $o;
8688 }
8689
8690 $outdelayed = '';
8691 if (!empty($conf->use_javascript_ajax)) {
8692 $tmpplugin = 'select2';
8693 $outdelayed = "\n" . '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' -->
8694 <script nonce="' . getNonce() . '">
8695 $(document).ready(function () {
8696 var data = ' . json_encode($formattedarrayresult) . ';
8697
8698 ' . ($callurlonselect ? 'var saveRemoteData = ' . json_encode($array) . ';' : '') . '
8699
8700 $(".' . $htmlname . '").select2({
8701 data: data,
8702 language: select2arrayoflanguage,
8703 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
8704 placeholder: "' . dol_escape_js($placeholder) . '",
8705 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8706 minimumInputLength: ' . $minimumInputLength . ',
8707 formatResult: function (result, container, query, escapeMarkup) {
8708 return escapeMarkup(result.text);
8709 },
8710 matcher: function (params, data) {
8711
8712 if(! data.id) return null;';
8713
8714 if ($callurlonselect) {
8715 // We forge the url with 'sall='
8716 $outdelayed .= '
8717
8718 var urlBase = data.url;
8719 var separ = urlBase.indexOf("?") >= 0 ? "&" : "?";
8720 /* console.log("params.term="+params.term); */
8721 /* console.log("params.term encoded="+encodeURIComponent(params.term)); */
8722 saveRemoteData[data.id].url = urlBase + separ + "search_all=" + encodeURIComponent(params.term.replace(/\"/g, ""));';
8723 }
8724
8725 if (!$disableFiltering) {
8726 $outdelayed .= '
8727
8728 if(data.text.match(new RegExp(params.term))) {
8729 return data;
8730 }
8731
8732 return null;';
8733 } else {
8734 $outdelayed .= '
8735
8736 return data;';
8737 }
8738
8739 $outdelayed .= '
8740 }
8741 });
8742
8743 ' . ($callurlonselect ? '
8744 /* Code to execute a GET when we select a value */
8745 $(".' . $htmlname . '").change(function() {
8746 var selected = $(".' . $htmlname . '").val();
8747 console.log("We select "+selected)
8748
8749 $(".' . $htmlname . '").val(""); /* reset visible combo value */
8750 $.each( saveRemoteData, function( key, value ) {
8751 if (key == selected)
8752 {
8753 console.log("selectArrayFilter - Do a redirect to "+value.url)
8754 location.assign(value.url);
8755 }
8756 });
8757 });' : '') . '
8758
8759 });
8760 </script>';
8761 }
8762
8763 if ($acceptdelayedhtml) {
8764 $delayedhtmlcontent .= $outdelayed;
8765 } else {
8766 $out .= $outdelayed;
8767 }
8768 return $out;
8769 }
8770
8789 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)
8790 {
8791 global $conf, $langs;
8792
8793 $out = '';
8794
8795 if ($addjscombo < 0) {
8796 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8797 $addjscombo = 1;
8798 } else {
8799 $addjscombo = 0;
8800 }
8801 }
8802
8803 $useenhancedmultiselect = 0;
8804 if (!empty($conf->use_javascript_ajax) && (getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT'))) {
8805 if ($addjscombo) {
8806 $useenhancedmultiselect = 1; // Use the js multiselect in one line. Possible only if $addjscombo not 0.
8807 }
8808 }
8809
8810 // We need a hidden field because when using the multiselect, if we unselect all, there is no
8811 // variable submitted at all, so no way to make a difference between variable not submited and variable
8812 // submited to nothing.
8813 $out .= '<input type="hidden" name="'.$htmlname.'_multiselect" value="1">';
8814 // Output select component
8815 $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";
8816 if (is_array($array) && !empty($array)) {
8817 if ($value_as_key) {
8818 $array = array_combine($array, $array);
8819 }
8820
8821 if (!empty($array)) {
8822 foreach ($array as $key => $value) {
8823 $tmpkey = $key;
8824 $tmpvalue = $value;
8825 $tmpcolor = '';
8826 $tmppicto = '';
8827 $tmplabelhtml = '';
8828 if (is_array($value) && array_key_exists('id', $value) && array_key_exists('label', $value)) {
8829 $tmpkey = $value['id'];
8830 $tmpvalue = empty($value['label']) ? '' : $value['label'];
8831 $tmpcolor = empty($value['color']) ? '' : $value['color'];
8832 $tmppicto = empty($value['picto']) ? '' : $value['picto'];
8833 $tmplabelhtml = empty($value['labelhtml']) ? '' : $value['labelhtml'];
8834 }
8835 $newval = ($translate ? $langs->trans($tmpvalue) : $tmpvalue);
8836 $newval = ($key_in_label ? $tmpkey . ' - ' . $newval : $newval);
8837
8838 $out .= '<option value="' . $tmpkey . '"';
8839 if (is_array($selected) && !empty($selected) && in_array((string) $tmpkey, $selected) && ((string) $tmpkey != '')) {
8840 $out .= ' selected';
8841 }
8842 if (!empty($tmplabelhtml)) {
8843 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
8844 } else {
8845 $tmplabelhtml = ($tmppicto ? img_picto('', $tmppicto, 'class="pictofixedwidth" style="color: #' . $tmpcolor . '"') : '') . $newval;
8846 $out .= ' data-html="' . dol_escape_htmltag($tmplabelhtml, 0, 0, '', 0, 1) . '"';
8847 }
8848 $out .= '>';
8849 $out .= dol_htmlentitiesbr($newval);
8850 $out .= '</option>' . "\n";
8851 }
8852 }
8853 }
8854 $out .= '</select>' . "\n";
8855
8856 // Add code for jquery to use multiselect
8857 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT')) {
8858 $out .= "\n" . '<!-- JS CODE TO ENABLE select for id ' . $htmlname . ', addjscombo=' . $addjscombo . ' -->';
8859 $out .= "\n" . '<script nonce="' . getNonce() . '">' . "\n";
8860 if ($addjscombo == 1) {
8861 $tmpplugin = !getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT;
8862 $out .= 'function formatResult(record, container) {' . "\n";
8863 // If property html set, we decode html entities and use this.
8864 // Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, '', 0, 1) when building the select option.
8865 $out .= ' if ($(record.element).attr("data-html") != undefined) { return htmlEntityDecodeJs($(record.element).attr("data-html")); }'."\n";
8866 $out .= ' return record.text;';
8867 $out .= '}' . "\n";
8868 $out .= 'function formatSelection(record) {' . "\n";
8869 if ($elemtype == 'category') {
8870 $out .= 'return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';';
8871 } else {
8872 $out .= 'return record.text;';
8873 }
8874 $out .= '}' . "\n";
8875 $out .= '$(document).ready(function () {
8876 $(\'#' . $htmlname . '\').' . $tmpplugin . '({';
8877 if ($placeholder) {
8878 $out .= '
8879 placeholder: {
8880 id: \'-1\',
8881 text: \'' . dol_escape_js($placeholder) . '\'
8882 },';
8883 }
8884 $out .= ' dir: \'ltr\',
8885 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag (ko with multiselect) */
8886 dropdownCssClass: \'' . $morecss . '\', /* Line to add class on the new <span class="select2-selection...> tag (ok with multiselect) */
8887 // Specify format function for dropdown item
8888 formatResult: formatResult,
8889 templateResult: formatResult, /* For 4.0 */
8890 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
8891 // Specify format function for selected item
8892 formatSelection: formatSelection,
8893 templateSelection: formatSelection /* For 4.0 */
8894 });
8895
8896 /* Add also morecss to the css .select2 that is after the #htmlname, for component that are show dynamically after load, because select2 set
8897 the size only if component is not hidden by default on load */
8898 $(\'#' . $htmlname . ' + .select2\').addClass(\'' . $morecss . '\');
8899 });' . "\n";
8900 } elseif ($addjscombo == 2 && !defined('DISABLE_MULTISELECT')) {
8901 // Add other js lib
8902 // TODO external lib multiselect/jquery.multi-select.js must have been loaded to use this multiselect plugin
8903 // ...
8904 $out .= 'console.log(\'addjscombo=2 for htmlname=' . $htmlname . '\');';
8905 $out .= '$(document).ready(function () {
8906 $(\'#' . $htmlname . '\').multiSelect({
8907 containerHTML: \'<div class="multi-select-container">\',
8908 menuHTML: \'<div class="multi-select-menu">\',
8909 buttonHTML: \'<span class="multi-select-button ' . $morecss . '">\',
8910 menuItemHTML: \'<label class="multi-select-menuitem">\',
8911 activeClass: \'multi-select-container--open\',
8912 noneText: \'' . $placeholder . '\'
8913 });
8914 })';
8915 }
8916 $out .= '</script>';
8917 }
8918
8919 return $out;
8920 }
8921
8922
8933 public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage, $pos = '')
8934 {
8935 global $conf, $langs, $user, $extrafields;
8936
8937 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
8938 return '';
8939 }
8940 if (empty($array)) {
8941 return '';
8942 }
8943
8944 $tmpvar = "MAIN_SELECTEDFIELDS_" . $varpage; // To get list of saved selected fields to show
8945
8946 if (!empty($user->conf->$tmpvar)) { // A list of fields was already customized for user
8947 $tmparray = explode(',', $user->conf->$tmpvar);
8948 foreach ($array as $key => $val) {
8949 //var_dump($key);
8950 //var_dump($tmparray);
8951 if (in_array($key, $tmparray)) {
8952 $array[$key]['checked'] = 1;
8953 } else {
8954 $array[$key]['checked'] = 0;
8955 }
8956 }
8957 } else { // There is no list of fields already customized for user
8958 foreach ($array as $key => $val) {
8959 if (!empty($array[$key]['checked']) && $array[$key]['checked'] < 0) {
8960 $array[$key]['checked'] = 0;
8961 }
8962 }
8963 }
8964
8965 $listoffieldsforselection = '';
8966 $listcheckedstring = '';
8967
8968 foreach ($array as $key => $val) {
8969 // var_dump($val);
8970 // var_dump(array_key_exists('enabled', $val));
8971 // var_dump(!$val['enabled']);
8972 if (array_key_exists('enabled', $val) && isset($val['enabled']) && !$val['enabled']) {
8973 unset($array[$key]); // We don't want this field
8974 continue;
8975 }
8976 if (!empty($val['type']) && $val['type'] == 'separate') {
8977 // Field remains in array but we don't add it into $listoffieldsforselection
8978 //$listoffieldsforselection .= '<li>-----</li>';
8979 continue;
8980 }
8981 if ($val['label']) {
8982 if (!empty($val['langfile']) && is_object($langs)) {
8983 $langs->load($val['langfile']);
8984 }
8985
8986 // Note: $val['checked'] <> 0 means we must show the field into the combo list
8987 $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>';
8988 $listcheckedstring .= (empty($val['checked']) ? '' : $key . ',');
8989 }
8990 }
8991
8992 $out = '<!-- Component multiSelectArrayWithCheckbox ' . $htmlname . ' -->
8993
8994 <dl class="dropdown">
8995 <dt>
8996 <a href="#' . $htmlname . '">
8997 ' . img_picto('', 'list') . '
8998 </a>
8999 <input type="hidden" class="' . $htmlname . '" name="' . $htmlname . '" value="' . $listcheckedstring . '">
9000 </dt>
9001 <dd class="dropdowndd">
9002 <div class="multiselectcheckbox'.$htmlname.'">
9003 <ul class="'.$htmlname.($pos == '1' ? 'left' : '').'">
9004 <li><input class="inputsearch_dropdownselectedfields width90p minwidth200imp" style="width:90%;" type="text" placeholder="'.$langs->trans('Search').'"></li>
9005 '.$listoffieldsforselection.'
9006 </ul>
9007 </div>
9008 </dd>
9009 </dl>
9010
9011 <script nonce="' . getNonce() . '" type="text/javascript">
9012 jQuery(document).ready(function () {
9013 $(\'.multiselectcheckbox' . $htmlname . ' input[type="checkbox"]\').on(\'click\', function () {
9014 console.log("A new field was added/removed, we edit field input[name=formfilteraction]");
9015
9016 $("input:hidden[name=formfilteraction]").val(\'listafterchangingselectedfields\'); // Update field so we know we changed something on selected fields after POST
9017
9018 var title = $(this).val() + ",";
9019 if ($(this).is(\':checked\')) {
9020 $(\'.' . $htmlname . '\').val(title + $(\'.' . $htmlname . '\').val());
9021 }
9022 else {
9023 $(\'.' . $htmlname . '\').val( $(\'.' . $htmlname . '\').val().replace(title, \'\') )
9024 }
9025 // Now, we submit page
9026 //$(this).parents(\'form:first\').submit();
9027 });
9028 $("input.inputsearch_dropdownselectedfields").on("keyup", function() {
9029 var value = $(this).val().toLowerCase();
9030 $(\'.multiselectcheckbox'.$htmlname.' li > label\').filter(function() {
9031 $(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
9032 });
9033 });
9034
9035
9036 });
9037 </script>
9038
9039 ';
9040 return $out;
9041 }
9042
9052 public function showCategories($id, $type, $rendermode = 0, $nolink = 0)
9053 {
9054 include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
9055
9056 $cat = new Categorie($this->db);
9057 $categories = $cat->containing($id, $type);
9058
9059 if ($rendermode == 1) {
9060 $toprint = array();
9061 foreach ($categories as $c) {
9062 $ways = $c->print_all_ways(' &gt;&gt; ', ($nolink ? 'none' : ''), 0, 1); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formated text
9063 foreach ($ways as $way) {
9064 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . $way . '</li>';
9065 }
9066 }
9067 return '<div class="select2-container-multi-dolibarr"><ul class="select2-choices-dolibarr">' . implode(' ', $toprint) . '</ul></div>';
9068 }
9069
9070 if ($rendermode == 0) {
9071 $arrayselected = array();
9072 $cate_arbo = $this->select_all_categories($type, '', 'parent', 64, 0, 1);
9073 foreach ($categories as $c) {
9074 $arrayselected[] = $c->id;
9075 }
9076
9077 return $this->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, '', 0, '100%', 'disabled', 'category');
9078 }
9079
9080 return 'ErrorBadValueForParameterRenderMode'; // Should not happened
9081 }
9082
9092 public function showLinkedObjectBlock($object, $morehtmlright = '', $compatibleImportElementsList = array(), $title = 'RelatedObjects')
9093 {
9094 global $conf, $langs, $hookmanager;
9095 global $bc, $action;
9096
9097 $object->fetchObjectLinked();
9098
9099 // Bypass the default method
9100 $hookmanager->initHooks(array('commonobject'));
9101 $parameters = array(
9102 'morehtmlright' => $morehtmlright,
9103 'compatibleImportElementsList' => &$compatibleImportElementsList,
9104 );
9105 $reshook = $hookmanager->executeHooks('showLinkedObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9106
9107 $nbofdifferenttypes = count($object->linkedObjects);
9108
9109 if (empty($reshook)) {
9110 print '<!-- showLinkedObjectBlock -->';
9111 print load_fiche_titre($langs->trans($title), $morehtmlright, '', 0, 0, 'showlinkedobjectblock');
9112
9113
9114 print '<div class="div-table-responsive-no-min">';
9115 print '<table class="noborder allwidth" data-block="showLinkedObject" data-element="' . $object->element . '" data-elementid="' . $object->id . '" >';
9116
9117 print '<tr class="liste_titre">';
9118 print '<td>' . $langs->trans("Type") . '</td>';
9119 print '<td>' . $langs->trans("Ref") . '</td>';
9120 print '<td class="center"></td>';
9121 print '<td class="center">' . $langs->trans("Date") . '</td>';
9122 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9123 print '<td class="right">' . $langs->trans("Status") . '</td>';
9124 print '<td></td>';
9125 print '</tr>';
9126
9127 $nboftypesoutput = 0;
9128
9129 foreach ($object->linkedObjects as $objecttype => $objects) {
9130 $tplpath = $element = $subelement = $objecttype;
9131
9132 // to display inport button on tpl
9133 $showImportButton = false;
9134 if (!empty($compatibleImportElementsList) && in_array($element, $compatibleImportElementsList)) {
9135 $showImportButton = true;
9136 }
9137
9138 $regs = array();
9139 if ($objecttype != 'supplier_proposal' && preg_match('/^([^_]+)_([^_]+)/i', $objecttype, $regs)) {
9140 $element = $regs[1];
9141 $subelement = $regs[2];
9142 $tplpath = $element . '/' . $subelement;
9143 }
9144 $tplname = 'linkedobjectblock';
9145
9146 // To work with non standard path
9147 if ($objecttype == 'facture') {
9148 $tplpath = 'compta/' . $element;
9149 if (!isModEnabled('facture')) {
9150 continue; // Do not show if module disabled
9151 }
9152 } elseif ($objecttype == 'facturerec') {
9153 $tplpath = 'compta/facture';
9154 $tplname = 'linkedobjectblockForRec';
9155 if (!isModEnabled('facture')) {
9156 continue; // Do not show if module disabled
9157 }
9158 } elseif ($objecttype == 'propal') {
9159 $tplpath = 'comm/' . $element;
9160 if (!isModEnabled('propal')) {
9161 continue; // Do not show if module disabled
9162 }
9163 } elseif ($objecttype == 'supplier_proposal') {
9164 if (!isModEnabled('supplier_proposal')) {
9165 continue; // Do not show if module disabled
9166 }
9167 } elseif ($objecttype == 'shipping' || $objecttype == 'shipment' || $objecttype == 'expedition') {
9168 $tplpath = 'expedition';
9169 if (!isModEnabled('expedition')) {
9170 continue; // Do not show if module disabled
9171 }
9172 } elseif ($objecttype == 'reception') {
9173 $tplpath = 'reception';
9174 if (!isModEnabled('reception')) {
9175 continue; // Do not show if module disabled
9176 }
9177 } elseif ($objecttype == 'delivery') {
9178 $tplpath = 'delivery';
9179 if (!isModEnabled('expedition')) {
9180 continue; // Do not show if module disabled
9181 }
9182 } elseif ($objecttype == 'ficheinter') {
9183 $tplpath = 'fichinter';
9184 if (!isModEnabled('ficheinter')) {
9185 continue; // Do not show if module disabled
9186 }
9187 } elseif ($objecttype == 'invoice_supplier') {
9188 $tplpath = 'fourn/facture';
9189 } elseif ($objecttype == 'order_supplier') {
9190 $tplpath = 'fourn/commande';
9191 } elseif ($objecttype == 'expensereport') {
9192 $tplpath = 'expensereport';
9193 } elseif ($objecttype == 'subscription') {
9194 $tplpath = 'adherents';
9195 } elseif ($objecttype == 'conferenceorbooth') {
9196 $tplpath = 'eventorganization';
9197 } elseif ($objecttype == 'conferenceorboothattendee') {
9198 $tplpath = 'eventorganization';
9199 } elseif ($objecttype == 'mo') {
9200 $tplpath = 'mrp';
9201 if (!isModEnabled('mrp')) {
9202 continue; // Do not show if module disabled
9203 }
9204 }
9205
9206 global $linkedObjectBlock;
9207 $linkedObjectBlock = $objects;
9208
9209 // Output template part (modules that overwrite templates must declare this into descriptor)
9210 $dirtpls = array_merge($conf->modules_parts['tpl'], array('/' . $tplpath . '/tpl'));
9211 foreach ($dirtpls as $reldir) {
9212 if ($nboftypesoutput == ($nbofdifferenttypes - 1)) { // No more type to show after
9213 global $noMoreLinkedObjectBlockAfter;
9214 $noMoreLinkedObjectBlockAfter = 1;
9215 }
9216
9217 $res = @include dol_buildpath($reldir . '/' . $tplname . '.tpl.php');
9218 if ($res) {
9219 $nboftypesoutput++;
9220 break;
9221 }
9222 }
9223 }
9224
9225 if (!$nboftypesoutput) {
9226 print '<tr><td class="impair" colspan="7"><span class="opacitymedium">' . $langs->trans("None") . '</span></td></tr>';
9227 }
9228
9229 print '</table>';
9230
9231 if (!empty($compatibleImportElementsList)) {
9232 $res = @include dol_buildpath('core/tpl/objectlinked_lineimport.tpl.php');
9233 }
9234
9235 print '</div>';
9236 }
9237
9238 return $nbofdifferenttypes;
9239 }
9240
9249 public function showLinkToObjectBlock($object, $restrictlinksto = array(), $excludelinksto = array())
9250 {
9251 global $conf, $langs, $hookmanager;
9252 global $action;
9253
9254 $linktoelem = '';
9255 $linktoelemlist = '';
9256 $listofidcompanytoscan = '';
9257
9258 if (!is_object($object->thirdparty)) {
9259 $object->fetch_thirdparty();
9260 }
9261
9262 $possiblelinks = array();
9263 if (is_object($object->thirdparty) && !empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
9264 $listofidcompanytoscan = $object->thirdparty->id;
9265 if (($object->thirdparty->parent > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PARENT_IN_LINKTO')) {
9266 $listofidcompanytoscan .= ',' . $object->thirdparty->parent;
9267 }
9268 if (($object->fk_project > 0) && getDolGlobalString('THIRDPARTY_INCLUDE_PROJECT_THIRDPARY_IN_LINKTO')) {
9269 include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
9270 $tmpproject = new Project($this->db);
9271 $tmpproject->fetch($object->fk_project);
9272 if ($tmpproject->socid > 0 && ($tmpproject->socid != $object->thirdparty->id)) {
9273 $listofidcompanytoscan .= ',' . $tmpproject->socid;
9274 }
9275 unset($tmpproject);
9276 }
9277
9278 $possiblelinks = array(
9279 'propal' => array(
9280 'enabled' => isModEnabled('propal'),
9281 'perms' => 1,
9282 'label' => 'LinkToProposal',
9283 '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') . ')'),
9284 'shipping' => array(
9285 'enabled' => isModEnabled('expedition'),
9286 'perms' => 1,
9287 'label' => 'LinkToExpedition',
9288 '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') . ')'),
9289 'order' => array(
9290 'enabled' => isModEnabled('commande'),
9291 'perms' => 1,
9292 'label' => 'LinkToOrder',
9293 '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') . ')'),
9294 'invoice' => array(
9295 'enabled' => isModEnabled('facture'),
9296 'perms' => 1,
9297 'label' => 'LinkToInvoice',
9298 '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') . ')'),
9299 'invoice_template' => array(
9300 'enabled' => isModEnabled('facture'),
9301 'perms' => 1,
9302 'label' => 'LinkToTemplateInvoice',
9303 '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') . ')'),
9304 'contrat' => array(
9305 'enabled' => isModEnabled('contrat'),
9306 'perms' => 1,
9307 'label' => 'LinkToContract',
9308 '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
9309 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'
9310 ),
9311 'fichinter' => array(
9312 'enabled' => isModEnabled('ficheinter'),
9313 'perms' => 1,
9314 'label' => 'LinkToIntervention',
9315 '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') . ')'),
9316 'supplier_proposal' => array(
9317 'enabled' => isModEnabled('supplier_proposal'),
9318 'perms' => 1,
9319 'label' => 'LinkToSupplierProposal',
9320 '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') . ')'),
9321 'order_supplier' => array(
9322 'enabled' => isModEnabled("supplier_order"),
9323 'perms' => 1,
9324 'label' => 'LinkToSupplierOrder',
9325 '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') . ')'),
9326 'invoice_supplier' => array(
9327 'enabled' => isModEnabled("supplier_invoice"),
9328 'perms' => 1, 'label' => 'LinkToSupplierInvoice',
9329 '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') . ')'),
9330 'ticket' => array(
9331 'enabled' => isModEnabled('ticket'),
9332 'perms' => 1,
9333 'label' => 'LinkToTicket',
9334 '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') . ')'),
9335 'mo' => array(
9336 'enabled' => isModEnabled('mrp'),
9337 'perms' => 1,
9338 'label' => 'LinkToMo',
9339 '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') . ')')
9340 );
9341 }
9342
9343 if ($object->table_element == 'commande_fournisseur') {
9344 $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').')';
9345 } elseif ($object->table_element == 'mrp_mo') {
9346 $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').')';
9347 }
9348
9349 if (!empty($listofidcompanytoscan)) { // If empty, we don't have criteria to scan the object we can link to
9350 // Can complete the possiblelink array
9351 $hookmanager->initHooks(array('commonobject'));
9352 $parameters = array('listofidcompanytoscan' => $listofidcompanytoscan, 'possiblelinks' => $possiblelinks);
9353 $reshook = $hookmanager->executeHooks('showLinkToObjectBlock', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
9354 }
9355
9356 if (empty($reshook)) {
9357 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9358 $possiblelinks = array_merge($possiblelinks, $hookmanager->resArray);
9359 }
9360 } elseif ($reshook > 0) {
9361 if (is_array($hookmanager->resArray) && count($hookmanager->resArray)) {
9362 $possiblelinks = $hookmanager->resArray;
9363 }
9364 }
9365
9366 foreach ($possiblelinks as $key => $possiblelink) {
9367 $num = 0;
9368
9369 if (empty($possiblelink['enabled'])) {
9370 continue;
9371 }
9372
9373 if (!empty($possiblelink['perms']) && (empty($restrictlinksto) || in_array($key, $restrictlinksto)) && (empty($excludelinksto) || !in_array($key, $excludelinksto))) {
9374 print '<div id="' . $key . 'list"' . (empty($conf->use_javascript_ajax) ? '' : ' style="display:none"') . '>';
9375
9376 if (getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9377 print '<br>'."\n";
9378 print '<!-- form to add a link from anywhere -->'."\n";
9379 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinkedbyref' . $key . '">';
9380 print '<input type="hidden" name="id" value="' . $object->id . '">';
9381 print '<input type="hidden" name="action" value="addlinkbyref">';
9382 print '<input type="hidden" name="token" value="' . newToken() . '">';
9383 print '<input type="hidden" name="addlink" value="' . $key . '">';
9384 print '<table class="noborder">';
9385 print '<tr>';
9386 //print '<td>' . $langs->trans("Ref") . '</td>';
9387 print '<td class="center"><input type="text" placeholder="'.dol_escape_htmltag($langs->trans("Ref")).'" name="reftolinkto" value="' . dol_escape_htmltag(GETPOST('reftolinkto', 'alpha')) . '">&nbsp;';
9388 print '<input type="submit" class="button small valignmiddle" value="' . $langs->trans('ToLink') . '">&nbsp;';
9389 print '<input type="submit" class="button small" name="cancel" value="' . $langs->trans('Cancel') . '"></td>';
9390 print '</tr>';
9391 print '</table>';
9392 print '</form>';
9393 }
9394
9395 $sql = $possiblelink['sql'];
9396
9397 $resqllist = $this->db->query($sql);
9398 if ($resqllist) {
9399 $num = $this->db->num_rows($resqllist);
9400 $i = 0;
9401
9402 print '<br>';
9403 print '<!-- form to add a link from object to same thirdparty -->'."\n";
9404 print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" name="formlinked' . $key . '">';
9405 print '<input type="hidden" name="action" value="addlink">';
9406 print '<input type="hidden" name="token" value="' . newToken() . '">';
9407 print '<input type="hidden" name="id" value="' . $object->id . '">';
9408 print '<input type="hidden" name="addlink" value="' . $key . '">';
9409 print '<table class="noborder">';
9410 print '<tr class="liste_titre">';
9411 print '<td class="nowrap"></td>';
9412 print '<td class="center">' . $langs->trans("Ref") . '</td>';
9413 print '<td class="left">' . $langs->trans("RefCustomer") . '</td>';
9414 print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
9415 print '<td class="left">' . $langs->trans("Company") . '</td>';
9416 print '</tr>';
9417 while ($i < $num) {
9418 $objp = $this->db->fetch_object($resqllist);
9419
9420 print '<tr class="oddeven">';
9421 print '<td class="left">';
9422 print '<input type="radio" name="idtolinkto" id="' . $key . '_' . $objp->rowid . '" value="' . $objp->rowid . '">';
9423 print '</td>';
9424 print '<td class="center"><label for="' . $key . '_' . $objp->rowid . '">' . $objp->ref . '</label></td>';
9425 print '<td>' . (!empty($objp->ref_client) ? $objp->ref_client : (!empty($objp->ref_supplier) ? $objp->ref_supplier : '')) . '</td>';
9426 print '<td class="right">';
9427 if ($possiblelink['label'] == 'LinkToContract') {
9428 $form = new Form($this->db);
9429 print $form->textwithpicto('', $langs->trans("InformationOnLinkToContract")) . ' ';
9430 }
9431 print '<span class="amount">' . (isset($objp->total_ht) ? price($objp->total_ht) : '') . '</span>';
9432 print '</td>';
9433 print '<td>' . $objp->name . '</td>';
9434 print '</tr>';
9435 $i++;
9436 }
9437 print '</table>';
9438 print '<div class="center">';
9439 if ($num) {
9440 print '<input type="submit" class="button valignmiddle marginleftonly marginrightonly small" value="' . $langs->trans('ToLink') . '">';
9441 }
9442 if (empty($conf->use_javascript_ajax)) {
9443 print '<input type="submit" class="button button-cancel marginleftonly marginrightonly small" name="cancel" value="' . $langs->trans("Cancel") . '"></div>';
9444 } else {
9445 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>';
9446 }
9447 print '</form>';
9448 $this->db->free($resqllist);
9449 } else {
9450 dol_print_error($this->db);
9451 }
9452 print '</div>';
9453
9454 //$linktoelem.=($linktoelem?' &nbsp; ':'');
9455 if ($num > 0 || getDolGlobalString('MAIN_LINK_BY_REF_IN_LINKTO')) {
9456 $linktoelemlist .= '<li><a href="#linkto' . $key . '" class="linkto dropdowncloseonclick" rel="' . $key . '">' . $langs->trans($possiblelink['label']) . ' (' . $num . ')</a></li>';
9457 // } else $linktoelem.=$langs->trans($possiblelink['label']);
9458 } else {
9459 $linktoelemlist .= '<li><span class="linktodisabled">' . $langs->trans($possiblelink['label']) . ' (0)</span></li>';
9460 }
9461 }
9462 }
9463
9464 if ($linktoelemlist) {
9465 $linktoelem = '
9466 <dl class="dropdown" id="linktoobjectname">
9467 ';
9468 if (!empty($conf->use_javascript_ajax)) {
9469 $linktoelem .= '<dt><a href="#linktoobjectname"><span class="fas fa-link paddingrightonly"></span>' . $langs->trans("LinkTo") . '...</a></dt>';
9470 }
9471 $linktoelem .= '<dd>
9472 <div class="multiselectlinkto">
9473 <ul class="ulselectedfields">' . $linktoelemlist . '
9474 </ul>
9475 </div>
9476 </dd>
9477 </dl>';
9478 } else {
9479 $linktoelem = '';
9480 }
9481
9482 if (!empty($conf->use_javascript_ajax)) {
9483 print '<!-- Add js to show linkto box -->
9484 <script nonce="' . getNonce() . '">
9485 jQuery(document).ready(function() {
9486 jQuery(".linkto").click(function() {
9487 console.log("We choose to show/hide links for rel="+jQuery(this).attr(\'rel\')+" so #"+jQuery(this).attr(\'rel\')+"list");
9488 jQuery("#"+jQuery(this).attr(\'rel\')+"list").toggle();
9489 });
9490 });
9491 </script>
9492 ';
9493 }
9494
9495 return $linktoelem;
9496 }
9497
9512 public function selectyesno($htmlname, $value = '', $option = 0, $disabled = false, $useempty = 0, $addjscombo = 0, $morecss = '', $labelyes = 'Yes', $labelno = 'No')
9513 {
9514 global $langs;
9515
9516 $yes = "yes";
9517 $no = "no";
9518 if ($option) {
9519 $yes = "1";
9520 $no = "0";
9521 }
9522
9523 $disabled = ($disabled ? ' disabled' : '');
9524
9525 $resultyesno = '<select class="flat width75' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . '"' . $disabled . '>' . "\n";
9526 if ($useempty) {
9527 $resultyesno .= '<option value="-1"' . (($value < 0) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
9528 }
9529 if (("$value" == 'yes') || ($value == 1)) {
9530 $resultyesno .= '<option value="' . $yes . '" selected>' . $langs->trans($labelyes) . '</option>' . "\n";
9531 $resultyesno .= '<option value="' . $no . '">' . $langs->trans($labelno) . '</option>' . "\n";
9532 } else {
9533 $selected = (($useempty && $value != '0' && $value != 'no') ? '' : ' selected');
9534 $resultyesno .= '<option value="' . $yes . '">' . $langs->trans($labelyes) . '</option>' . "\n";
9535 $resultyesno .= '<option value="' . $no . '"' . $selected . '>' . $langs->trans($labelno) . '</option>' . "\n";
9536 }
9537 $resultyesno .= '</select>' . "\n";
9538
9539 if ($addjscombo) {
9540 $resultyesno .= ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($useempty < 0 ? (string) $useempty : '-1'), $morecss);
9541 }
9542
9543 return $resultyesno;
9544 }
9545
9546 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
9547
9557 public function select_export_model($selected = '', $htmlname = 'exportmodelid', $type = '', $useempty = 0)
9558 {
9559 // phpcs:enable
9560 $sql = "SELECT rowid, label";
9561 $sql .= " FROM " . $this->db->prefix() . "export_model";
9562 $sql .= " WHERE type = '" . $this->db->escape($type) . "'";
9563 $sql .= " ORDER BY rowid";
9564 $result = $this->db->query($sql);
9565 if ($result) {
9566 print '<select class="flat" id="select_' . $htmlname . '" name="' . $htmlname . '">';
9567 if ($useempty) {
9568 print '<option value="-1">&nbsp;</option>';
9569 }
9570
9571 $num = $this->db->num_rows($result);
9572 $i = 0;
9573 while ($i < $num) {
9574 $obj = $this->db->fetch_object($result);
9575 if ($selected == $obj->rowid) {
9576 print '<option value="' . $obj->rowid . '" selected>';
9577 } else {
9578 print '<option value="' . $obj->rowid . '">';
9579 }
9580 print $obj->label;
9581 print '</option>';
9582 $i++;
9583 }
9584 print "</select>";
9585 } else {
9586 dol_print_error($this->db);
9587 }
9588 }
9589
9608 public function showrefnav($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $morehtmlright = '')
9609 {
9610 global $conf, $langs, $hookmanager, $extralanguages;
9611
9612 $ret = '';
9613 if (empty($fieldid)) {
9614 $fieldid = 'rowid';
9615 }
9616 if (empty($fieldref)) {
9617 $fieldref = 'ref';
9618 }
9619
9620 // Preparing gender's display if there is one
9621 $addgendertxt = '';
9622 if (property_exists($object, 'gender') && !empty($object->gender)) {
9623 $addgendertxt = ' ';
9624 switch ($object->gender) {
9625 case 'man':
9626 $addgendertxt .= '<i class="fas fa-mars"></i>';
9627 break;
9628 case 'woman':
9629 $addgendertxt .= '<i class="fas fa-venus"></i>';
9630 break;
9631 case 'other':
9632 $addgendertxt .= '<i class="fas fa-transgender"></i>';
9633 break;
9634 }
9635 }
9636
9637 // Add where from hooks
9638 if (is_object($hookmanager)) {
9639 $parameters = array('showrefnav' => true);
9640 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
9641 $object->next_prev_filter .= $hookmanager->resPrint;
9642 }
9643 $previous_ref = $next_ref = '';
9644 if ($shownav) {
9645 //print "paramid=$paramid,morehtml=$morehtml,shownav=$shownav,$fieldid,$fieldref,$morehtmlref,$moreparam";
9646 $object->load_previous_next_ref((isset($object->next_prev_filter) ? $object->next_prev_filter : ''), $fieldid, $nodbprefix);
9647
9648 $navurl = $_SERVER["PHP_SELF"];
9649 // Special case for project/task page
9650 if ($paramid == 'project_ref') {
9651 if (preg_match('/\/tasks\/(task|contact|note|document)\.php/', $navurl)) { // TODO Remove this when nav with project_ref on task pages are ok
9652 $navurl = preg_replace('/\/tasks\/(task|contact|time|note|document)\.php/', '/tasks.php', $navurl);
9653 $paramid = 'ref';
9654 }
9655 }
9656
9657 // accesskey is for Windows or Linux: ALT + key for chrome, ALT + SHIFT + KEY for firefox
9658 // accesskey is for Mac: CTRL + key for all browsers
9659 $stringforfirstkey = $langs->trans("KeyboardShortcut");
9660 if ($conf->browser->name == 'chrome') {
9661 $stringforfirstkey .= ' ALT +';
9662 } elseif ($conf->browser->name == 'firefox') {
9663 $stringforfirstkey .= ' ALT + SHIFT +';
9664 } else {
9665 $stringforfirstkey .= ' CTL +';
9666 }
9667
9668 $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>';
9669 $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>';
9670 }
9671
9672 //print "xx".$previous_ref."x".$next_ref;
9673 $ret .= '<!-- Start banner content --><div style="vertical-align: middle">';
9674
9675 // Right part of banner
9676 if ($morehtmlright) {
9677 $ret .= '<div class="inline-block floatleft">' . $morehtmlright . '</div>';
9678 }
9679
9680 if ($previous_ref || $next_ref || $morehtml) {
9681 $ret .= '<div class="pagination paginationref"><ul class="right">';
9682 }
9683 if ($morehtml) {
9684 $ret .= '<li class="noborder litext' . (($shownav && $previous_ref && $next_ref) ? ' clearbothonsmartphone' : '') . '">' . $morehtml . '</li>';
9685 }
9686 if ($shownav && ($previous_ref || $next_ref)) {
9687 $ret .= '<li class="pagination">' . $previous_ref . '</li>';
9688 $ret .= '<li class="pagination">' . $next_ref . '</li>';
9689 }
9690 if ($previous_ref || $next_ref || $morehtml) {
9691 $ret .= '</ul></div>';
9692 }
9693
9694 // Status
9695 $parameters = array('morehtmlstatus' => $morehtmlstatus);
9696 $reshook = $hookmanager->executeHooks('moreHtmlStatus', $parameters, $object); // Note that $action and $object may have been modified by hook
9697 if (empty($reshook)) {
9698 $morehtmlstatus .= $hookmanager->resPrint;
9699 } else {
9700 $morehtmlstatus = $hookmanager->resPrint;
9701 }
9702 if ($morehtmlstatus) {
9703 $ret .= '<div class="statusref">' . $morehtmlstatus . '</div>';
9704 }
9705
9706 $parameters = array();
9707 $reshook = $hookmanager->executeHooks('moreHtmlRef', $parameters, $object); // Note that $action and $object may have been modified by hook
9708 if (empty($reshook)) {
9709 $morehtmlref .= $hookmanager->resPrint;
9710 } elseif ($reshook > 0) {
9711 $morehtmlref = $hookmanager->resPrint;
9712 }
9713
9714 // Left part of banner
9715 if ($morehtmlleft) {
9716 if ($conf->browser->layout == 'phone') {
9717 $ret .= '<!-- morehtmlleft --><div class="floatleft">' . $morehtmlleft . '</div>';
9718 } else {
9719 $ret .= '<!-- morehtmlleft --><div class="inline-block floatleft">' . $morehtmlleft . '</div>';
9720 }
9721 }
9722
9723 //if ($conf->browser->layout == 'phone') $ret.='<div class="clearboth"></div>';
9724 $ret .= '<div class="inline-block floatleft valignmiddle maxwidth750 marginbottomonly refid' . (($shownav && ($previous_ref || $next_ref)) ? ' refidpadding' : '') . '">';
9725
9726 // For thirdparty, contact, user, member, the ref is the id, so we show something else
9727 if ($object->element == 'societe') {
9728 $ret .= dol_htmlentities($object->name);
9729
9730 // List of extra languages
9731 $arrayoflangcode = array();
9732 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
9733 $arrayoflangcode[] = $conf->global->PDF_USE_ALSO_LANGUAGE_CODE;
9734 }
9735
9736 if (is_array($arrayoflangcode) && count($arrayoflangcode)) {
9737 if (!is_object($extralanguages)) {
9738 include_once DOL_DOCUMENT_ROOT . '/core/class/extralanguages.class.php';
9739 $extralanguages = new ExtraLanguages($this->db);
9740 }
9741 $extralanguages->fetch_name_extralanguages('societe');
9742
9743 if (!empty($extralanguages->attributes['societe']['name'])) {
9744 $object->fetchValuesForExtraLanguages();
9745
9746 $htmltext = '';
9747 // If there is extra languages
9748 foreach ($arrayoflangcode as $extralangcode) {
9749 $htmltext .= picto_from_langcode($extralangcode, 'class="pictoforlang paddingright"');
9750 if ($object->array_languages['name'][$extralangcode]) {
9751 $htmltext .= $object->array_languages['name'][$extralangcode];
9752 } else {
9753 $htmltext .= '<span class="opacitymedium">' . $langs->trans("SwitchInEditModeToAddTranslation") . '</span>';
9754 }
9755 }
9756 $ret .= '<!-- Show translations of name -->' . "\n";
9757 $ret .= $this->textwithpicto('', $htmltext, -1, 'language', 'opacitymedium paddingleft');
9758 }
9759 }
9760 } elseif ($object->element == 'member') {
9761 $ret .= $object->ref . '<br>';
9762 $fullname = $object->getFullName($langs);
9763 if ($object->morphy == 'mor' && $object->societe) {
9764 $ret .= dol_htmlentities($object->societe) . ((!empty($fullname) && $object->societe != $fullname) ? ' (' . dol_htmlentities($fullname) . $addgendertxt . ')' : '');
9765 } else {
9766 $ret .= dol_htmlentities($fullname) . $addgendertxt . ((!empty($object->societe) && $object->societe != $fullname) ? ' (' . dol_htmlentities($object->societe) . ')' : '');
9767 }
9768 } elseif (in_array($object->element, array('contact', 'user'))) {
9769 $ret .= dol_htmlentities($object->getFullName($langs)) . $addgendertxt;
9770 } elseif ($object->element == 'usergroup') {
9771 $ret .= dol_htmlentities($object->name);
9772 } elseif (in_array($object->element, array('action', 'agenda'))) {
9773 $ret .= $object->ref . '<br>' . $object->label;
9774 } elseif (in_array($object->element, array('adherent_type'))) {
9775 $ret .= $object->label;
9776 } elseif ($object->element == 'ecm_directories') {
9777 $ret .= '';
9778 } elseif ($fieldref != 'none') {
9779 $ret .= dol_htmlentities(!empty($object->$fieldref) ? $object->$fieldref : "");
9780 }
9781 if ($morehtmlref) {
9782 // don't add a additional space, when "$morehtmlref" starts with a HTML div tag
9783 if (substr($morehtmlref, 0, 4) != '<div') {
9784 $ret .= ' ';
9785 }
9786
9787 $ret .= $morehtmlref;
9788 }
9789
9790 $ret .= '</div>';
9791
9792 $ret .= '</div><!-- End banner content -->';
9793
9794 return $ret;
9795 }
9796
9797
9806 public function showbarcode(&$object, $width = 100, $morecss = '')
9807 {
9808 global $conf;
9809
9810 //Check if barcode is filled in the card
9811 if (empty($object->barcode)) {
9812 return '';
9813 }
9814
9815 // Complete object if not complete
9816 if (empty($object->barcode_type_code) || empty($object->barcode_type_coder)) {
9817 $result = $object->fetch_barcode();
9818 //Check if fetch_barcode() failed
9819 if ($result < 1) {
9820 return '<!-- ErrorFetchBarcode -->';
9821 }
9822 }
9823
9824 // Barcode image
9825 $url = DOL_URL_ROOT . '/viewimage.php?modulepart=barcode&generator=' . urlencode($object->barcode_type_coder) . '&code=' . urlencode($object->barcode) . '&encoding=' . urlencode($object->barcode_type_code);
9826 $out = '<!-- url barcode = ' . $url . ' -->';
9827 $out .= '<img src="' . $url . '"' . ($morecss ? ' class="' . $morecss . '"' : '') . '>';
9828
9829 return $out;
9830 }
9831
9848 public static function showphoto($modulepart, $object, $width = 100, $height = 0, $caneditfield = 0, $cssclass = 'photowithmargin', $imagesize = '', $addlinktofullsize = 1, $cache = 0, $forcecapture = '', $noexternsourceoverwrite = 0)
9849 {
9850 global $conf, $langs;
9851
9852 $entity = (empty($object->entity) ? $conf->entity : $object->entity);
9853 $id = (empty($object->id) ? $object->rowid : $object->id);
9854
9855 $ret = '';
9856 $dir = '';
9857 $file = '';
9858 $originalfile = '';
9859 $altfile = '';
9860 $email = '';
9861 $capture = '';
9862 if ($modulepart == 'societe') {
9863 $dir = $conf->societe->multidir_output[$entity];
9864 if (!empty($object->logo)) {
9865 if (dolIsAllowedForPreview($object->logo)) {
9866 if ((string) $imagesize == 'mini') {
9867 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_mini'); // getImageFileNameForSize include the thumbs
9868 } elseif ((string) $imagesize == 'small') {
9869 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . getImageFileNameForSize($object->logo, '_small');
9870 } else {
9871 $file = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
9872 }
9873 $originalfile = get_exdir(0, 0, 0, 0, $object, 'thirdparty') . 'logos/' . $object->logo;
9874 }
9875 }
9876 $email = $object->email;
9877 } elseif ($modulepart == 'contact') {
9878 $dir = $conf->societe->multidir_output[$entity] . '/contact';
9879 if (!empty($object->photo)) {
9880 if (dolIsAllowedForPreview($object->photo)) {
9881 if ((string) $imagesize == 'mini') {
9882 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
9883 } elseif ((string) $imagesize == 'small') {
9884 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
9885 } else {
9886 $file = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
9887 }
9888 $originalfile = get_exdir(0, 0, 0, 0, $object, 'contact') . 'photos/' . $object->photo;
9889 }
9890 }
9891 $email = $object->email;
9892 $capture = 'user';
9893 } elseif ($modulepart == 'userphoto') {
9894 $dir = $conf->user->dir_output;
9895 if (!empty($object->photo)) {
9896 if (dolIsAllowedForPreview($object->photo)) {
9897 if ((string) $imagesize == 'mini') {
9898 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
9899 } elseif ((string) $imagesize == 'small') {
9900 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
9901 } else {
9902 $file = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
9903 }
9904 $originalfile = get_exdir(0, 0, 0, 0, $object, 'user') . 'photos/' . $object->photo;
9905 }
9906 }
9907 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
9908 $altfile = $object->id . ".jpg"; // For backward compatibility
9909 }
9910 $email = $object->email;
9911 $capture = 'user';
9912 } elseif ($modulepart == 'memberphoto') {
9913 $dir = $conf->adherent->dir_output;
9914 if (!empty($object->photo)) {
9915 if (dolIsAllowedForPreview($object->photo)) {
9916 if ((string) $imagesize == 'mini') {
9917 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
9918 } elseif ((string) $imagesize == 'small') {
9919 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . getImageFileNameForSize($object->photo, '_small');
9920 } else {
9921 $file = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
9922 }
9923 $originalfile = get_exdir(0, 0, 0, 0, $object, 'member') . 'photos/' . $object->photo;
9924 }
9925 }
9926 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
9927 $altfile = $object->id . ".jpg"; // For backward compatibility
9928 }
9929 $email = $object->email;
9930 $capture = 'user';
9931 } else {
9932 // Generic case to show photos
9933 $dir = $conf->$modulepart->dir_output;
9934 if (!empty($object->photo)) {
9935 if (dolIsAllowedForPreview($object->photo)) {
9936 if ((string) $imagesize == 'mini') {
9937 $file = get_exdir($id, 2, 0, 0, $object, $modulepart) . 'photos/' . getImageFileNameForSize($object->photo, '_mini');
9938 } elseif ((string) $imagesize == 'small') {
9939 $file = get_exdir($id, 2, 0, 0, $object, $modulepart) . 'photos/' . getImageFileNameForSize($object->photo, '_small');
9940 } else {
9941 $file = get_exdir($id, 2, 0, 0, $object, $modulepart) . 'photos/' . $object->photo;
9942 }
9943 $originalfile = get_exdir($id, 2, 0, 0, $object, $modulepart) . 'photos/' . $object->photo;
9944 }
9945 }
9946 if (getDolGlobalString('MAIN_OLD_IMAGE_LINKS')) {
9947 $altfile = $object->id . ".jpg"; // For backward compatibility
9948 }
9949 $email = $object->email;
9950 }
9951
9952 if ($forcecapture) {
9953 $capture = $forcecapture;
9954 }
9955
9956 if ($dir) {
9957 if ($file && file_exists($dir . "/" . $file)) {
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 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 . '">';
9967 if ($addlinktofullsize) {
9968 $ret .= '</a>';
9969 }
9970 } elseif ($altfile && file_exists($dir . "/" . $altfile)) {
9971 if ($addlinktofullsize) {
9972 $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity=' . $entity);
9973 if ($urladvanced) {
9974 $ret .= '<a href="' . $urladvanced . '">';
9975 } else {
9976 $ret .= '<a href="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($originalfile) . '&cache=' . $cache . '">';
9977 }
9978 }
9979 $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 . '">';
9980 if ($addlinktofullsize) {
9981 $ret .= '</a>';
9982 }
9983 } else {
9984 $nophoto = '/public/theme/common/nophoto.png';
9985 $defaultimg = 'identicon'; // For gravatar
9986 if (in_array($modulepart, array('societe', 'userphoto', 'contact', 'memberphoto'))) { // For modules that need a special image when photo not found
9987 if ($modulepart == 'societe' || ($modulepart == 'memberphoto' && !empty($object->morphy) && strpos($object->morphy, 'mor')) !== false) {
9988 $nophoto = 'company';
9989 } else {
9990 $nophoto = '/public/theme/common/user_anonymous.png';
9991 if (!empty($object->gender) && $object->gender == 'man') {
9992 $nophoto = '/public/theme/common/user_man.png';
9993 }
9994 if (!empty($object->gender) && $object->gender == 'woman') {
9995 $nophoto = '/public/theme/common/user_woman.png';
9996 }
9997 }
9998 }
9999
10000 if (isModEnabled('gravatar') && $email && empty($noexternsourceoverwrite)) {
10001 // see https://gravatar.com/site/implement/images/php/
10002 $ret .= '<!-- Put link to gravatar -->';
10003 $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
10004 } else {
10005 if ($nophoto == 'company') {
10006 $ret .= '<div class="divforspanimg photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . '>' . img_picto('', 'company') . '</div>';
10007 $ret .= '<div class="difforspanimgright"></div>';
10008 } else {
10009 $ret .= '<img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="" ' . ($width ? ' width="' . $width . '"' : '') . ($height ? ' height="' . $height . '"' : '') . ' src="' . DOL_URL_ROOT . $nophoto . '">';
10010 }
10011 }
10012 }
10013
10014 if ($caneditfield) {
10015 if ($object->photo) {
10016 $ret .= "<br>\n";
10017 }
10018 $ret .= '<table class="nobordernopadding centpercent">';
10019 if ($object->photo) {
10020 $ret .= '<tr><td><input type="checkbox" class="flat photodelete" name="deletephoto" id="photodelete"> <label for="photodelete">' . $langs->trans("Delete") . '</label><br><br></td></tr>';
10021 }
10022 $ret .= '<tr><td class="tdoverflow">';
10023 $maxfilesizearray = getMaxFileSizeArray();
10024 $maxmin = $maxfilesizearray['maxmin'];
10025 if ($maxmin > 0) {
10026 $ret .= '<input type="hidden" name="MAX_FILE_SIZE" value="' . ($maxmin * 1024) . '">'; // MAX_FILE_SIZE must precede the field type=file
10027 }
10028 $ret .= '<input type="file" class="flat maxwidth200onsmartphone" name="photo" id="photoinput" accept="image/*"' . ($capture ? ' capture="' . $capture . '"' : '') . '>';
10029 $ret .= '</td></tr>';
10030 $ret .= '</table>';
10031 }
10032 }
10033
10034 return $ret;
10035 }
10036
10037 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
10038
10055 public function select_dolgroups($selected = '', $htmlname = 'groupid', $show_empty = 0, $exclude = '', $disabled = 0, $include = '', $enableonly = array(), $force_entity = '0', $multiple = false, $morecss = '')
10056 {
10057 // phpcs:enable
10058 global $conf, $user, $langs;
10059
10060 // Permettre l'exclusion de groupes
10061 $excludeGroups = null;
10062 if (is_array($exclude)) {
10063 $excludeGroups = implode(",", $exclude);
10064 }
10065 // Permettre l'inclusion de groupes
10066 $includeGroups = null;
10067 if (is_array($include)) {
10068 $includeGroups = implode(",", $include);
10069 }
10070
10071 if (!is_array($selected)) {
10072 $selected = array($selected);
10073 }
10074
10075 $out = '';
10076
10077 // On recherche les groupes
10078 $sql = "SELECT ug.rowid, ug.nom as name";
10079 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10080 $sql .= ", e.label";
10081 }
10082 $sql .= " FROM " . $this->db->prefix() . "usergroup as ug ";
10083 if (isModEnabled('multicompany') && $conf->entity == 1 && $user->admin && !$user->entity) {
10084 $sql .= " LEFT JOIN " . $this->db->prefix() . "entity as e ON e.rowid=ug.entity";
10085 if ($force_entity) {
10086 $sql .= " WHERE ug.entity IN (0, " . $force_entity . ")";
10087 } else {
10088 $sql .= " WHERE ug.entity IS NOT NULL";
10089 }
10090 } else {
10091 $sql .= " WHERE ug.entity IN (0, " . $conf->entity . ")";
10092 }
10093 if (is_array($exclude) && $excludeGroups) {
10094 $sql .= " AND ug.rowid NOT IN (" . $this->db->sanitize($excludeGroups) . ")";
10095 }
10096 if (is_array($include) && $includeGroups) {
10097 $sql .= " AND ug.rowid IN (" . $this->db->sanitize($includeGroups) . ")";
10098 }
10099 $sql .= " ORDER BY ug.nom ASC";
10100
10101 dol_syslog(get_class($this) . "::select_dolgroups", LOG_DEBUG);
10102 $resql = $this->db->query($sql);
10103 if ($resql) {
10104 // Enhance with select2
10105 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10106
10107 $out .= '<select class="flat minwidth200' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiple ? '[]' : '') . '" ' . ($multiple ? 'multiple' : '') . ' ' . ($disabled ? ' disabled' : '') . '>';
10108
10109 $num = $this->db->num_rows($resql);
10110 $i = 0;
10111 if ($num) {
10112 if ($show_empty && !$multiple) {
10113 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '>&nbsp;</option>' . "\n";
10114 }
10115
10116 while ($i < $num) {
10117 $obj = $this->db->fetch_object($resql);
10118 $disableline = 0;
10119 if (is_array($enableonly) && count($enableonly) && !in_array($obj->rowid, $enableonly)) {
10120 $disableline = 1;
10121 }
10122
10123 $label = $obj->name;
10124 $labelhtml = $obj->name;
10125 if (isModEnabled('multicompany') && !getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE') && $conf->entity == 1) {
10126 $label .= " (" . $obj->label . ")";
10127 $labelhtml .= ' <span class="opacitymedium">(' . $obj->label . ')</span>';
10128 }
10129
10130 $out .= '<option value="' . $obj->rowid . '"';
10131 if ($disableline) {
10132 $out .= ' disabled';
10133 }
10134 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))) {
10135 $out .= ' selected';
10136 }
10137 $out .= ' data-html="'.dol_escape_htmltag($labelhtml).'"';
10138 $out .= '>';
10139 $out .= $label;
10140 $out .= '</option>';
10141 $i++;
10142 }
10143 } else {
10144 if ($show_empty) {
10145 $out .= '<option value="-1"' . (in_array(-1, $selected) ? ' selected' : '') . '></option>' . "\n";
10146 }
10147 $out .= '<option value="" disabled>' . $langs->trans("NoUserGroupDefined") . '</option>';
10148 }
10149 $out .= '</select>';
10150
10151 $out .= ajax_combobox($htmlname);
10152 } else {
10153 dol_print_error($this->db);
10154 }
10155
10156 return $out;
10157 }
10158
10159
10166 public function showFilterButtons($pos = '')
10167 {
10168 $out = '<div class="nowraponall">';
10169 if ($pos == 'left') {
10170 $out .= '<button type="submit" class="liste_titre button_search reposition" name="button_search_x" value="x"><span class="fas fa-search"></span></button>';
10171 $out .= '<button type="submit" class="liste_titre button_removefilter reposition" name="button_removefilter_x" value="x"><span class="fas fa-times"></span></button>';
10172 } else {
10173 $out .= '<button type="submit" class="liste_titre button_search reposition" name="button_search_x" value="x"><span class="fas fa-search"></span></button>';
10174 $out .= '<button type="submit" class="liste_titre button_removefilter reposition" name="button_removefilter_x" value="x"><span class="fas fa-times"></span></button>';
10175 }
10176 $out .= '</div>';
10177
10178 return $out;
10179 }
10180
10189 public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10190 {
10191 global $conf;
10192
10193 $out = '';
10194
10195 if (!empty($conf->use_javascript_ajax)) {
10196 $out .= '<div class="inline-block checkallactions"><input type="checkbox" id="' . $cssclass . 's" name="' . $cssclass . 's" class="checkallactions"></div>';
10197 }
10198 $out .= '<script nonce="' . getNonce() . '">
10199 $(document).ready(function() {
10200 $("#' . $cssclass . 's").click(function() {
10201 if($(this).is(\':checked\')){
10202 console.log("We check all ' . $cssclass . ' and trigger the change method");
10203 $(".' . $cssclass . '").prop(\'checked\', true).trigger(\'change\');
10204 }
10205 else
10206 {
10207 console.log("We uncheck all");
10208 $(".' . $cssclass . '").prop(\'checked\', false).trigger(\'change\');
10209 }' . "\n";
10210 if ($calljsfunction) {
10211 $out .= 'if (typeof initCheckForSelect == \'function\') { initCheckForSelect(0, "' . $massactionname . '", "' . $cssclass . '"); } else { console.log("No function initCheckForSelect found. Call won\'t be done."); }';
10212 }
10213 $out .= ' });
10214 $(".' . $cssclass . '").change(function() {
10215 $(this).closest("tr").toggleClass("highlight", this.checked);
10216 });
10217 });
10218 </script>';
10219
10220 return $out;
10221 }
10222
10232 public function showFilterAndCheckAddButtons($addcheckuncheckall = 0, $cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction")
10233 {
10234 $out = $this->showFilterButtons();
10235 if ($addcheckuncheckall) {
10236 $out .= $this->showCheckAddButtons($cssclass, $calljsfunction, $massactionname);
10237 }
10238 return $out;
10239 }
10240
10254 public function selectExpenseCategories($selected = '', $htmlname = 'fk_c_exp_tax_cat', $useempty = 0, $excludeid = array(), $target = '', $default_selected = 0, $params = array(), $info_admin = 1)
10255 {
10256 global $langs, $user;
10257
10258 $out = '';
10259 $sql = "SELECT rowid, label FROM " . $this->db->prefix() . "c_exp_tax_cat WHERE active = 1";
10260 $sql .= " AND entity IN (0," . getEntity('exp_tax_cat') . ")";
10261 if (!empty($excludeid)) {
10262 $sql .= " AND rowid NOT IN (" . $this->db->sanitize(implode(',', $excludeid)) . ")";
10263 }
10264 $sql .= " ORDER BY label";
10265
10266 $resql = $this->db->query($sql);
10267 if ($resql) {
10268 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp maxwidth200">';
10269 if ($useempty) {
10270 $out .= '<option value="0">&nbsp;</option>';
10271 }
10272
10273 while ($obj = $this->db->fetch_object($resql)) {
10274 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . $langs->trans($obj->label) . '</option>';
10275 }
10276 $out .= '</select>';
10277 $out .= ajax_combobox('select_' . $htmlname);
10278
10279 if (!empty($htmlname) && $user->admin && $info_admin) {
10280 $out .= ' ' . info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
10281 }
10282
10283 if (!empty($target)) {
10284 $sql = "SELECT c.id FROM " . $this->db->prefix() . "c_type_fees as c WHERE c.code = 'EX_KME' AND c.active = 1";
10285 $resql = $this->db->query($sql);
10286 if ($resql) {
10287 if ($this->db->num_rows($resql) > 0) {
10288 $obj = $this->db->fetch_object($resql);
10289 $out .= '<script nonce="' . getNonce() . '">
10290 $(function() {
10291 $("select[name=' . $target . ']").on("change", function() {
10292 var current_val = $(this).val();
10293 if (current_val == ' . $obj->id . ') {';
10294 if (!empty($default_selected) || !empty($selected)) {
10295 $out .= '$("select[name=' . $htmlname . ']").val("' . ($default_selected > 0 ? $default_selected : $selected) . '");';
10296 }
10297
10298 $out .= '
10299 $("select[name=' . $htmlname . ']").change();
10300 }
10301 });
10302
10303 $("select[name=' . $htmlname . ']").change(function() {
10304
10305 if ($("select[name=' . $target . ']").val() == ' . $obj->id . ') {
10306 // get price of kilometer to fill the unit price
10307 $.ajax({
10308 method: "POST",
10309 dataType: "json",
10310 data: { fk_c_exp_tax_cat: $(this).val(), token: \'' . currentToken() . '\' },
10311 url: "' . (DOL_URL_ROOT . '/expensereport/ajax/ajaxik.php?' . join('&', $params)) . '",
10312 }).done(function( data, textStatus, jqXHR ) {
10313 console.log(data);
10314 if (typeof data.up != "undefined") {
10315 $("input[name=value_unit]").val(data.up);
10316 $("select[name=' . $htmlname . ']").attr("title", data.title);
10317 } else {
10318 $("input[name=value_unit]").val("");
10319 $("select[name=' . $htmlname . ']").attr("title", "");
10320 }
10321 });
10322 }
10323 });
10324 });
10325 </script>';
10326 }
10327 }
10328 }
10329 } else {
10330 dol_print_error($this->db);
10331 }
10332
10333 return $out;
10334 }
10335
10344 public function selectExpenseRanges($selected = '', $htmlname = 'fk_range', $useempty = 0)
10345 {
10346 global $conf, $langs;
10347
10348 $out = '';
10349 $sql = "SELECT rowid, range_ik FROM " . $this->db->prefix() . "c_exp_tax_range";
10350 $sql .= " WHERE entity = " . $conf->entity . " AND active = 1";
10351
10352 $resql = $this->db->query($sql);
10353 if ($resql) {
10354 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10355 if ($useempty) {
10356 $out .= '<option value="0"></option>';
10357 }
10358
10359 while ($obj = $this->db->fetch_object($resql)) {
10360 $out .= '<option ' . ($selected == $obj->rowid ? 'selected="selected"' : '') . ' value="' . $obj->rowid . '">' . price($obj->range_ik, 0, $langs, 1, 0) . '</option>';
10361 }
10362 $out .= '</select>';
10363 } else {
10364 dol_print_error($this->db);
10365 }
10366
10367 return $out;
10368 }
10369
10380 public function selectExpense($selected = '', $htmlname = 'fk_c_type_fees', $useempty = 0, $allchoice = 1, $useid = 0)
10381 {
10382 global $langs;
10383
10384 $out = '';
10385 $sql = "SELECT id, code, label";
10386 $sql .= " FROM ".$this->db->prefix()."c_type_fees";
10387 $sql .= " WHERE active = 1";
10388
10389 $resql = $this->db->query($sql);
10390 if ($resql) {
10391 $out = '<select id="select_' . $htmlname . '" name="' . $htmlname . '" class="' . $htmlname . ' flat minwidth75imp">';
10392 if ($useempty) {
10393 $out .= '<option value="0"></option>';
10394 }
10395 if ($allchoice) {
10396 $out .= '<option value="-1">' . $langs->trans('AllExpenseReport') . '</option>';
10397 }
10398
10399 $field = 'code';
10400 if ($useid) {
10401 $field = 'id';
10402 }
10403
10404 while ($obj = $this->db->fetch_object($resql)) {
10405 $key = $langs->trans($obj->code);
10406 $out .= '<option ' . ($selected == $obj->{$field} ? 'selected="selected"' : '') . ' value="' . $obj->{$field} . '">' . ($key != $obj->code ? $key : $obj->label) . '</option>';
10407 }
10408 $out .= '</select>';
10409
10410 $out .= ajax_combobox('select_'.$htmlname);
10411 } else {
10412 dol_print_error($this->db);
10413 }
10414
10415 return $out;
10416 }
10417
10436 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)
10437 {
10438 global $user, $conf, $langs;
10439
10440 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
10441
10442 if (is_null($usertofilter)) {
10443 $usertofilter = $user;
10444 }
10445
10446 $out = '';
10447
10448 $hideunselectables = false;
10449 if (getDolGlobalString('PROJECT_HIDE_UNSELECTABLES')) {
10450 $hideunselectables = true;
10451 }
10452
10453 if (empty($projectsListId)) {
10454 if (!$usertofilter->hasRight('projet', 'all', 'lire')) {
10455 $projectstatic = new Project($this->db);
10456 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertofilter, 0, 1);
10457 }
10458 }
10459
10460 // Search all projects
10461 $sql = "SELECT f.rowid, f.ref as fref, 'nolabel' as flabel, p.rowid as pid, f.ref,
10462 p.title, p.fk_soc, p.fk_statut, p.public,";
10463 $sql .= ' s.nom as name';
10464 $sql .= ' FROM ' . $this->db->prefix() . 'projet as p';
10465 $sql .= ' LEFT JOIN ' . $this->db->prefix() . 'societe as s ON s.rowid = p.fk_soc,';
10466 $sql .= ' ' . $this->db->prefix() . 'facture as f';
10467 $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
10468 $sql .= " AND f.fk_projet = p.rowid AND f.fk_statut=0"; //Brouillons seulement
10469 //if ($projectsListId) $sql.= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")";
10470 //if ($socid == 0) $sql.= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)";
10471 //if ($socid > 0) $sql.= " AND (p.fk_soc=".((int) $socid)." OR p.fk_soc IS NULL)";
10472 $sql .= " ORDER BY p.ref, f.ref ASC";
10473
10474 $resql = $this->db->query($sql);
10475 if ($resql) {
10476 // Use select2 selector
10477 if (!empty($conf->use_javascript_ajax)) {
10478 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10479 $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus);
10480 $out .= $comboenhancement;
10481 $morecss = 'minwidth200imp maxwidth500';
10482 }
10483
10484 if (empty($option_only)) {
10485 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10486 }
10487 if (!empty($show_empty)) {
10488 $out .= '<option value="0" class="optiongrey">';
10489 if (!is_numeric($show_empty)) {
10490 $out .= $show_empty;
10491 } else {
10492 $out .= '&nbsp;';
10493 }
10494 $out .= '</option>';
10495 }
10496 $num = $this->db->num_rows($resql);
10497 $i = 0;
10498 if ($num) {
10499 while ($i < $num) {
10500 $obj = $this->db->fetch_object($resql);
10501 // 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.
10502 if ($socid > 0 && (empty($obj->fk_soc) || $obj->fk_soc == $socid) && !$usertofilter->hasRight('societe', 'lire')) {
10503 // Do nothing
10504 } else {
10505 if ($discard_closed == 1 && $obj->fk_statut == Project::STATUS_CLOSED) {
10506 $i++;
10507 continue;
10508 }
10509
10510 $labeltoshow = '';
10511
10512 if ($showproject == 'all') {
10513 $labeltoshow .= dol_trunc($obj->ref, 18); // Invoice ref
10514 if ($obj->name) {
10515 $labeltoshow .= ' - ' . $obj->name; // Soc name
10516 }
10517
10518 $disabled = 0;
10519 if ($obj->fk_statut == Project::STATUS_DRAFT) {
10520 $disabled = 1;
10521 $labeltoshow .= ' - ' . $langs->trans("Draft");
10522 } elseif ($obj->fk_statut == Project::STATUS_CLOSED) {
10523 if ($discard_closed == 2) {
10524 $disabled = 1;
10525 }
10526 $labeltoshow .= ' - ' . $langs->trans("Closed");
10527 } elseif ($socid > 0 && (!empty($obj->fk_soc) && $obj->fk_soc != $socid)) {
10528 $disabled = 1;
10529 $labeltoshow .= ' - ' . $langs->trans("LinkedToAnotherCompany");
10530 }
10531 }
10532
10533 if (!empty($selected) && $selected == $obj->rowid) {
10534 $out .= '<option value="' . $obj->rowid . '" selected';
10535 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10536 $out .= '>' . $labeltoshow . '</option>';
10537 } else {
10538 if ($hideunselectables && $disabled && ($selected != $obj->rowid)) {
10539 $resultat = '';
10540 } else {
10541 $resultat = '<option value="' . $obj->rowid . '"';
10542 if ($disabled) {
10543 $resultat .= ' disabled';
10544 }
10545 //if ($obj->public) $labeltoshow.=' ('.$langs->trans("Public").')';
10546 //else $labeltoshow.=' ('.$langs->trans("Private").')';
10547 $resultat .= '>';
10548 $resultat .= $labeltoshow;
10549 $resultat .= '</option>';
10550 }
10551 $out .= $resultat;
10552 }
10553 }
10554 $i++;
10555 }
10556 }
10557 if (empty($option_only)) {
10558 $out .= '</select>';
10559 }
10560
10561 $this->db->free($resql);
10562
10563 return $out;
10564 } else {
10565 dol_print_error($this->db);
10566 return '';
10567 }
10568 }
10569
10583 public function selectInvoiceRec($selected = '', $htmlname = 'facrecid', $maxlength = 24, $option_only = 0, $show_empty = '1', $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500')
10584 {
10585 global $conf, $langs;
10586
10587 $out = '';
10588
10589 dol_syslog('FactureRec::fetch', LOG_DEBUG);
10590
10591 $sql = 'SELECT f.rowid, f.entity, f.titre as title, f.suspended, f.fk_soc';
10592 //$sql.= ', el.fk_source';
10593 $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_rec as f';
10594 $sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")";
10595 $sql .= " ORDER BY f.titre ASC";
10596
10597 $resql = $this->db->query($sql);
10598 if ($resql) {
10599 // Use select2 selector
10600 if (!empty($conf->use_javascript_ajax)) {
10601 include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
10602 $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus);
10603 $out .= $comboenhancement;
10604 $morecss = 'minwidth200imp maxwidth500';
10605 }
10606
10607 if (empty($option_only)) {
10608 $out .= '<select class="valignmiddle flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ' id="' . $htmlname . '" name="' . $htmlname . '">';
10609 }
10610 if (!empty($show_empty)) {
10611 $out .= '<option value="0" class="optiongrey">';
10612 if (!is_numeric($show_empty)) {
10613 $out .= $show_empty;
10614 } else {
10615 $out .= '&nbsp;';
10616 }
10617 $out .= '</option>';
10618 }
10619 $num = $this->db->num_rows($resql);
10620 if ($num) {
10621 while ($obj = $this->db->fetch_object($resql)) {
10622 $labeltoshow = dol_trunc($obj->title, 18); // Invoice ref
10623
10624 $disabled = 0;
10625 if (!empty($obj->suspended)) {
10626 $disabled = 1;
10627 $labeltoshow .= ' - ' . $langs->trans("Closed");
10628 }
10629
10630
10631 if (!empty($selected) && $selected == $obj->rowid) {
10632 $out .= '<option value="' . $obj->rowid . '" selected';
10633 //if ($disabled) $out.=' disabled'; // with select2, field can't be preselected if disabled
10634 $out .= '>' . $labeltoshow . '</option>';
10635 } else {
10636 if ($disabled && ($selected != $obj->rowid)) {
10637 $resultat = '';
10638 } else {
10639 $resultat = '<option value="' . $obj->rowid . '"';
10640 if ($disabled) {
10641 $resultat .= ' disabled';
10642 }
10643 $resultat .= '>';
10644 $resultat .= $labeltoshow;
10645 $resultat .= '</option>';
10646 }
10647 $out .= $resultat;
10648 }
10649 }
10650 }
10651 if (empty($option_only)) {
10652 $out .= '</select>';
10653 }
10654
10655 print $out;
10656
10657 $this->db->free($resql);
10658 return $num;
10659 } else {
10660 $this->errors[] = $this->db->lasterror;
10661 return -1;
10662 }
10663 }
10664
10674 public function searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput = array(), $search_component_params_hidden = '')
10675 {
10676 global $langs;
10677
10678 if ($search_component_params_hidden != '' && !preg_match('/^\‍(.*\‍)$/', $search_component_params_hidden)) { // If $search_component_params_hidden does not start and end with ()
10679 $search_component_params_hidden = '(' . $search_component_params_hidden . ')';
10680 }
10681
10682 $ret = '';
10683
10684 $ret .= '<div class="divadvancedsearchfieldcomp inline-block">';
10685 $ret .= '<a href="#" class="dropdownsearch-toggle unsetcolor">';
10686 $ret .= '<span class="fas fa-filter linkobject boxfilter paddingright pictofixedwidth" title="' . dol_escape_htmltag($langs->trans("Filters")) . '" id="idsubimgproductdistribution"></span>';
10687 $ret .= '</a>';
10688
10689 $ret .= '<div class="divadvancedsearchfieldcompinput inline-block minwidth500 maxwidth300onsmartphone">';
10690
10691 // Show select fields as tags.
10692 $ret .= '<div name="divsearch_component_params" class="noborderbottom search_component_params inline-block valignmiddle">';
10693
10694 if ($search_component_params_hidden) {
10695 // Split the criteria on each AND
10696 //var_dump($search_component_params_hidden);
10697
10698 $nbofchars = dol_strlen($search_component_params_hidden);
10699 $arrayofandtags = array();
10700 $i = 0;
10701 $s = '';
10702 $countparenthesis = 0;
10703 while ($i < $nbofchars) {
10704 $char = dol_substr($search_component_params_hidden, $i, 1);
10705
10706 if ($char == '(') {
10707 $countparenthesis++;
10708 } elseif ($char == ')') {
10709 $countparenthesis--;
10710 }
10711
10712 if ($countparenthesis == 0) {
10713 $char2 = dol_substr($search_component_params_hidden, $i+1, 1);
10714 $char3 = dol_substr($search_component_params_hidden, $i+2, 1);
10715 if ($char == 'A' && $char2 == 'N' && $char3 == 'D') {
10716 // We found a AND
10717 $arrayofandtags[] = trim($s);
10718 $s = '';
10719 $i+=2;
10720 } else {
10721 $s .= $char;
10722 }
10723 } else {
10724 $s .= $char;
10725 }
10726 $i++;
10727 }
10728 if ($s) {
10729 $arrayofandtags[] = trim($s);
10730 }
10731
10732 // Show each AND part
10733 foreach ($arrayofandtags as $tmpkey => $tmpval) {
10734 $errormessage = '';
10735 $searchtags = forgeSQLFromUniversalSearchCriteria($tmpval, $errormessage, 1, 1);
10736 if ($errormessage) {
10737 $this->error = 'ERROR in parsing search string: '.$errormessage;
10738 }
10739 // Remove first and last parenthesis but only if first is the opening and last the closing of the same group
10740 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
10741 $searchtags = removeGlobalParenthesis($searchtags);
10742
10743 $ret .= '<span class="marginleftonlyshort valignmiddle tagsearch" data-ufilterid="'.($tmpkey+1).'" data-ufilter="'.dol_escape_htmltag($tmpval).'">';
10744 $ret .= '<span class="tagsearchdelete select2-selection__choice__remove" data-ufilterid="'.($tmpkey+1).'">x</span> ';
10745 $ret .= dol_escape_htmltag($searchtags);
10746 $ret .= '</span>';
10747 }
10748 }
10749
10750 //$ret .= '<button type="submit" class="liste_titre button_search paddingleftonly" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
10751
10752 //$ret .= search_component_params
10753 //$texttoshow = '<div class="opacitymedium inline-block search_component_searchtext">'.$langs->trans("Search").'</div>';
10754 //$ret .= '<div class="search_component inline-block valignmiddle">'.$texttoshow.'</div>';
10755
10756 $show_search_component_params_hidden = 1;
10757 if ($show_search_component_params_hidden) {
10758 $ret .= '<input type="hidden" name="show_search_component_params_hidden" value="1">';
10759 }
10760 $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%')) -->";
10761 $ret .= '<input type="hidden" name="search_component_params_hidden" value="' . dol_escape_htmltag($search_component_params_hidden) . '">';
10762 // $ret .= "<!-- sql= ".forgeSQLFromUniversalSearchCriteria($search_component_params_hidden, $errormessage)." -->";
10763
10764 // For compatibility with forms that show themself the search criteria in addition of this component, we output these fields
10765 foreach ($arrayofcriterias as $criterias) {
10766 foreach ($criterias as $criteriafamilykey => $criteriafamilyval) {
10767 if (in_array('search_' . $criteriafamilykey, $arrayofinputfieldsalreadyoutput)) {
10768 continue;
10769 }
10770 if (in_array($criteriafamilykey, array('rowid', 'ref_ext', 'entity', 'extraparams'))) {
10771 continue;
10772 }
10773 if (in_array($criteriafamilyval['type'], array('date', 'datetime', 'timestamp'))) {
10774 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_start">';
10775 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startyear">';
10776 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startmonth">';
10777 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_startday">';
10778 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_end">';
10779 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endyear">';
10780 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endmonth">';
10781 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '_endday">';
10782 } else {
10783 $ret .= '<input type="hidden" name="search_' . $criteriafamilykey . '">';
10784 }
10785 }
10786 }
10787
10788 $ret .= '</div>';
10789
10790 $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";
10791 $ret .= '<input type="text" placeholder="' . $langs->trans("Search") . '" name="search_component_params_input" class="noborderbottom search_component_input" value="">';
10792
10793 $ret .= '</div>';
10794 $ret .= '</div>';
10795
10796 $ret .= '<script>
10797 jQuery(".tagsearchdelete").click(function() {
10798 var filterid = $(this).parents().data("ufilterid");
10799 console.log("We click to delete a criteria nb "+filterid);
10800 // TODO Update the search_component_params_hidden with all data-ufilter except the one delete and post page
10801
10802 });
10803 </script>
10804 ';
10805
10806
10807 return $ret;
10808 }
10809
10819 public function selectModelMail($prefix, $modelType = '', $default = 0, $addjscombo = 0)
10820 {
10821 global $langs, $user;
10822
10823 $retstring = '';
10824
10825 $TModels = array();
10826
10827 include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
10828 $formmail = new FormMail($this->db);
10829 $result = $formmail->fetchAllEMailTemplate($modelType, $user, $langs);
10830
10831 if ($default) {
10832 $TModels[0] = $langs->trans('DefaultMailModel');
10833 }
10834 if ($result > 0) {
10835 foreach ($formmail->lines_model as $model) {
10836 $TModels[$model->id] = $model->label;
10837 }
10838 }
10839
10840 $retstring .= '<select class="flat" id="select_' . $prefix . 'model_mail" name="' . $prefix . 'model_mail">';
10841
10842 foreach ($TModels as $id_model => $label_model) {
10843 $retstring .= '<option value="' . $id_model . '"';
10844 $retstring .= ">" . $label_model . "</option>";
10845 }
10846
10847 $retstring .= "</select>";
10848
10849 if ($addjscombo) {
10850 $retstring .= ajax_combobox('select_' . $prefix . 'model_mail');
10851 }
10852
10853 return $retstring;
10854 }
10855
10867 public function buttonsSaveCancel($save_label = 'Save', $cancel_label = 'Cancel', $morebuttons = array(), $withoutdiv = false, $morecss = '', $dol_openinpopup = '')
10868 {
10869 global $langs;
10870
10871 $buttons = array();
10872
10873 $save = array(
10874 'name' => 'save',
10875 'label_key' => $save_label,
10876 );
10877
10878 if ($save_label == 'Create' || $save_label == 'Add') {
10879 $save['name'] = 'add';
10880 } elseif ($save_label == 'Modify') {
10881 $save['name'] = 'edit';
10882 }
10883
10884 $cancel = array(
10885 'name' => 'cancel',
10886 'label_key' => 'Cancel',
10887 );
10888
10889 !empty($save_label) ? $buttons[] = $save : '';
10890
10891 if (!empty($morebuttons)) {
10892 $buttons[] = $morebuttons;
10893 }
10894
10895 !empty($cancel_label) ? $buttons[] = $cancel : '';
10896
10897 $retstring = $withoutdiv ? '' : '<div class="center">';
10898
10899 foreach ($buttons as $button) {
10900 $addclass = empty($button['addclass']) ? '' : $button['addclass'];
10901 $retstring .= '<input type="submit" class="button button-' . $button['name'] . ($morecss ? ' ' . $morecss : '') . ' ' . $addclass . '" name="' . $button['name'] . '" value="' . dol_escape_htmltag($langs->trans($button['label_key'])) . '">';
10902 }
10903 $retstring .= $withoutdiv ? '' : '</div>';
10904
10905 if ($dol_openinpopup) {
10906 $retstring .= '<!-- buttons are shown into a $dol_openinpopup=' . $dol_openinpopup . ' context, so we enable the close of dialog on cancel -->' . "\n";
10907 $retstring .= '<script nonce="' . getNonce() . '">';
10908 $retstring .= 'jQuery(".button-cancel").click(function(e) {
10909 e.preventDefault(); console.log(\'We click on cancel in iframe popup ' . $dol_openinpopup . '\');
10910 window.parent.jQuery(\'#idfordialog' . $dol_openinpopup . '\').dialog(\'close\');
10911 });';
10912 $retstring .= '</script>';
10913 }
10914
10915 return $retstring;
10916 }
10917
10918
10919 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
10920
10927 {
10928 // phpcs:enable
10929 global $langs;
10930
10931 $num = count($this->cache_invoice_subtype);
10932 if ($num > 0) {
10933 return 0; // Cache already loaded
10934 }
10935
10936 dol_syslog(__METHOD__, LOG_DEBUG);
10937
10938 $sql = "SELECT rowid, code, label as label";
10939 $sql .= " FROM " . MAIN_DB_PREFIX . 'c_invoice_subtype';
10940 $sql .= " WHERE active = 1";
10941
10942 $resql = $this->db->query($sql);
10943 if ($resql) {
10944 $num = $this->db->num_rows($resql);
10945 $i = 0;
10946 while ($i < $num) {
10947 $obj = $this->db->fetch_object($resql);
10948
10949 // If translation exists, we use it, otherwise we take the default wording
10950 $label = ($langs->trans("InvoiceSubtype" . $obj->rowid) != "InvoiceSubtype" . $obj->rowid) ? $langs->trans("InvoiceSubtype" . $obj->rowid) : (($obj->label != '-') ? $obj->label : '');
10951 $this->cache_invoice_subtype[$obj->rowid]['rowid'] = $obj->rowid;
10952 $this->cache_invoice_subtype[$obj->rowid]['code'] = $obj->code;
10953 $this->cache_invoice_subtype[$obj->rowid]['label'] = $label;
10954 $i++;
10955 }
10956
10957 $this->cache_invoice_subtype = dol_sort_array($this->cache_invoice_subtype, 'code', 'asc', 0, 0, 1);
10958
10959 return $num;
10960 } else {
10961 dol_print_error($this->db);
10962 return -1;
10963 }
10964 }
10965
10966
10977 public function getSelectInvoiceSubtype($selected = 0, $htmlname = 'subtypeid', $addempty = 0, $noinfoadmin = 0, $morecss = '')
10978 {
10979 global $langs, $user;
10980
10981 $out = '';
10982 dol_syslog(__METHOD__ . " selected=" . $selected . ", htmlname=" . $htmlname, LOG_DEBUG);
10983
10984 $this->load_cache_invoice_subtype();
10985
10986 $out .= '<select id="' . $htmlname . '" class="flat selectsubtype' . ($morecss ? ' ' . $morecss : '') . '" name="' . $htmlname . '">';
10987 if ($addempty) {
10988 $out .= '<option value="0">&nbsp;</option>';
10989 }
10990
10991 foreach ($this->cache_invoice_subtype as $rowid => $subtype) {
10992 $label = $subtype['label'];
10993 $out .= '<option value="' . $subtype['rowid'] . '"';
10994 if ($selected == $subtype['rowid']) {
10995 $out .= ' selected="selected"';
10996 }
10997 $out .= '>';
10998 $out .= $label;
10999 $out .= '</option>';
11000 }
11001
11002 $out .= '</select>';
11003 if ($user->admin && empty($noinfoadmin)) {
11004 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
11005 }
11006 $out .= ajax_combobox($htmlname);
11007
11008 return $out;
11009 }
11010}
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:455
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:303
ajax_event($htmlname, $events)
Add event management script.
Definition ajax.lib.php:556
$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:86
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:1926
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