Passed
Branch develop (5cbde9)
by
unknown
26:38
created

Form::selectUnits()   B

Complexity

Conditions 8

Size

Total Lines 36
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 18
c 0
b 0
f 0
nop 3
dl 0
loc 36
rs 8.4444
1
<?php
2
/* Copyright (c) 2002-2007  Rodolphe Quiedeville    <[email protected]>
3
 * Copyright (C) 2004-2012  Laurent Destailleur     <[email protected]>
4
 * Copyright (C) 2004       Benoit Mortier          <[email protected]>
5
 * Copyright (C) 2004       Sebastien Di Cintio     <[email protected]>
6
 * Copyright (C) 2004       Eric Seigne             <[email protected]>
7
 * Copyright (C) 2005-2017  Regis Houssin           <[email protected]>
8
 * Copyright (C) 2006       Andre Cianfarani        <[email protected]>
9
 * Copyright (C) 2006       Marc Barilley/Ocebo     <[email protected]>
10
 * Copyright (C) 2007       Franky Van Liedekerke   <[email protected]>
11
 * Copyright (C) 2007       Patrick Raguin          <[email protected]>
12
 * Copyright (C) 2010       Juanjo Menent           <[email protected]>
13
 * Copyright (C) 2010-2019  Philippe Grand          <[email protected]>
14
 * Copyright (C) 2011       Herve Prot              <[email protected]>
15
 * Copyright (C) 2012-2016  Marcos García           <[email protected]>
16
 * Copyright (C) 2012       Cedric Salvador         <[email protected]>
17
 * Copyright (C) 2012-2015  Raphaël Doursenaud      <[email protected]>
18
 * Copyright (C) 2014       Alexandre Spangaro      <[email protected]>
19
 * Copyright (C) 2018       Ferran Marcet           <[email protected]>
20
 * Copyright (C) 2018-2019  Frédéric France         <[email protected]>
21
 * Copyright (C) 2018       Nicolas ZABOURI	        <[email protected]>
22
 * Copyright (C) 2018       Christophe Battarel     <[email protected]>
23
 * Copyright (C) 2018       Josep Lluis Amador      <[email protected]>
24
 *
25
 * This program is free software; you can redistribute it and/or modify
26
 * it under the terms of the GNU General Public License as published by
27
 * the Free Software Foundation; either version 3 of the License, or
28
 * (at your option) any later version.
29
 *
30
 * This program is distributed in the hope that it will be useful,
31
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33
 * GNU General Public License for more details.
34
 *
35
 * You should have received a copy of the GNU General Public License
36
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
37
 */
38
39
/**
40
 *	\file       htdocs/core/class/html.form.class.php
41
 *  \ingroup    core
42
 *	\brief      File of class with all html predefined components
43
 */
44
45
46
/**
47
 *	Class to manage generation of HTML components
48
 *	Only common components must be here.
49
 *
50
 *  TODO Merge all function load_cache_* and loadCache* (except load_cache_vatrates) into one generic function loadCacheTable
51
 */
52
class Form
53
{
54
	/**
55
     * @var DoliDB Database handler.
56
     */
57
    public $db;
58
59
	/**
60
	 * @var string Error code (or message)
61
	 */
62
	public $error='';
63
64
    /**
65
     * @var string[]    Array of error strings
66
     */
67
    public $errors = array();
68
69
	public $num;
70
71
	// Cache arrays
72
	public $cache_types_paiements=array();
73
	public $cache_conditions_paiements=array();
74
	public $cache_availability=array();
75
	public $cache_demand_reason=array();
76
	public $cache_types_fees=array();
77
	public $cache_vatrates=array();
78
79
80
	/**
81
	 * Constructor
82
	 *
83
	 * @param		DoliDB		$db      Database handler
84
	 */
85
	public function __construct($db)
86
	{
87
		$this->db = $db;
88
	}
89
90
	/**
91
	 * Output key field for an editable field
92
	 *
93
	 * @param   string	$text			Text of label or key to translate
94
	 * @param   string	$htmlname		Name of select field ('edit' prefix will be added)
95
	 * @param   string	$preselected    Value to show/edit (not used in this function)
96
	 * @param	object	$object			Object
97
	 * @param	boolean	$perm			Permission to allow button to edit parameter. Set it to 0 to have a not edited field.
98
	 * @param	string	$typeofdata		Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols', 'datepicker' ('day' do not work, don't know why), 'ckeditor:dolibarr_zzz:width:height:savemethod:1:rows:cols', 'select;xxx[:class]'...)
99
	 * @param	string	$moreparam		More param to add on a href URL.
100
	 * @param   int     $fieldrequired  1 if we want to show field as mandatory using the "fieldrequired" CSS.
101
	 * @param   int     $notabletag     1=Do not output table tags but output a ':', 2=Do not output table tags and no ':', 3=Do not output table tags but output a ' '
102
	 * @param	string	$paramid		Key of parameter for id ('id', 'socid')
103
	 * @return	string					HTML edit field
104
	 */
105
    public function editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata = 'string', $moreparam = '', $fieldrequired = 0, $notabletag = 0, $paramid = 'id')
106
    {
107
		global $conf,$langs;
108
109
		$ret='';
110
111
		// TODO change for compatibility
112
		if (! empty($conf->global->MAIN_USE_JQUERY_JEDITABLE) && ! preg_match('/^select;/', $typeofdata))
113
		{
114
			if (! empty($perm))
115
			{
116
				$tmp=explode(':', $typeofdata);
117
				$ret.= '<div class="editkey_'.$tmp[0].(! empty($tmp[1]) ? ' '.$tmp[1] : '').'" id="'.$htmlname.'">';
118
				if ($fieldrequired) $ret.='<span class="fieldrequired">';
119
				$ret.= $langs->trans($text);
120
				if ($fieldrequired) $ret.='</span>';
121
				$ret.= '</div>'."\n";
122
			}
123
			else
124
			{
125
				if ($fieldrequired) $ret.='<span class="fieldrequired">';
126
				$ret.= $langs->trans($text);
127
				if ($fieldrequired) $ret.='</span>';
128
			}
129
		}
130
		else
131
		{
132
			if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret.='<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
133
			if ($fieldrequired) $ret.='<span class="fieldrequired">';
134
			$ret.=$langs->trans($text);
135
			if ($fieldrequired) $ret.='</span>';
136
			if (! empty($notabletag)) $ret.=' ';
137
			if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret.='</td>';
138
			if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret.='<td class="right">';
139
			if ($htmlname && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret.='<a href="'.$_SERVER["PHP_SELF"].'?action=edit'.$htmlname.'&amp;'.$paramid.'='.$object->id.$moreparam.'">'.img_edit($langs->trans('Edit'), ($notabletag ? 0 : 1)).'</a>';
140
			if (! empty($notabletag) && $notabletag == 1) $ret.=' : ';
141
			if (! empty($notabletag) && $notabletag == 3) $ret.=' ';
142
			if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret.='</td>';
143
			if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret.='</tr></table>';
144
		}
145
146
		return $ret;
147
    }
148
149
	/**
150
	 * Output value of a field for an editable field
151
	 *
152
	 * @param	string	$text			Text of label (not used in this function)
153
	 * @param	string	$htmlname		Name of select field
154
	 * @param	string	$value			Value to show/edit
155
	 * @param	object	$object			Object
156
	 * @param	boolean	$perm			Permission to allow button to edit parameter
157
	 * @param	string	$typeofdata		Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols%', 'datepicker' ('day' do not work, don't know why), 'dayhour' or 'datepickerhour', 'ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols', 'select;xkey:xval,ykey:yval,...')
158
	 * @param	string	$editvalue		When in edit mode, use this value as $value instead of value (for example, you can provide here a formated price instead of value). Use '' to use same than $value
159
	 * @param	object	$extObject		External object
160
	 * @param	mixed	$custommsg		String or Array of custom messages : eg array('success' => 'MyMessage', 'error' => 'MyMessage')
161
	 * @param	string	$moreparam		More param to add on the form action href URL
162
	 * @param   int     $notabletag     Do no output table tags
163
	 * @param	string	$formatfunc		Call a specific function to output field
164
	 * @param	string	$paramid		Key of parameter for id ('id', 'socid')
165
	 * @return  string					HTML edit field
166
	 */
167
    public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 0, $formatfunc = '', $paramid = 'id')
168
	{
169
		global $conf,$langs,$db;
170
171
		$ret='';
172
173
		// Check parameters
174
		if (empty($typeofdata)) return 'ErrorBadParameter';
175
176
		// When option to edit inline is activated
177
		if (! empty($conf->global->MAIN_USE_JQUERY_JEDITABLE) && ! preg_match('/^select;|datehourpicker/', $typeofdata)) // TODO add jquery timepicker and support select
178
		{
179
			$ret.=$this->editInPlace($object, $value, $htmlname, $perm, $typeofdata, $editvalue, $extObject, $custommsg);
180
		}
181
		else
182
		{
183
			if (GETPOST('action', 'aZ09') == 'edit'.$htmlname)
184
			{
185
				$ret.="\n";
186
				$ret.='<form method="post" action="'.$_SERVER["PHP_SELF"].($moreparam?'?'.$moreparam:'').'">';
187
				$ret.='<input type="hidden" name="action" value="set'.$htmlname.'">';
188
				$ret.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
189
				$ret.='<input type="hidden" name="'.$paramid.'" value="'.$object->id.'">';
190
				if (empty($notabletag)) $ret.='<table class="nobordernopadding centpercent" cellpadding="0" cellspacing="0">';
191
				if (empty($notabletag)) $ret.='<tr><td>';
192
				if (preg_match('/^(string|email)/', $typeofdata))
193
				{
194
					$tmp=explode(':', $typeofdata);
195
					$ret.='<input type="text" id="'.$htmlname.'" name="'.$htmlname.'" value="'.($editvalue?$editvalue:$value).'"'.($tmp[1]?' size="'.$tmp[1].'"':'').'>';
196
				}
197
				elseif (preg_match('/^(numeric|amount)/', $typeofdata))
198
				{
199
					$tmp=explode(':', $typeofdata);
200
					$valuetoshow=price2num($editvalue?$editvalue:$value);
201
					$ret.='<input type="text" id="'.$htmlname.'" name="'.$htmlname.'" value="'.($valuetoshow!=''?price($valuetoshow):'').'"'.($tmp[1]?' size="'.$tmp[1].'"':'').'>';
202
				}
203
				elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata))
204
				{
205
					$tmp=explode(':', $typeofdata);
206
					$cols=$tmp[2];
207
					$morealt='';
208
					if (preg_match('/%/', $cols))
209
					{
210
						$morealt=' style="width: '.$cols.'"';
211
						$cols='';
212
					}
213
214
					$valuetoshow = ($editvalue?$editvalue:$value);
215
216
					$ret.='<textarea id="'.$htmlname.'" name="'.$htmlname.'" wrap="soft" rows="'.($tmp[1]?$tmp[1]:'20').'"'.($cols?' cols="'.$cols.'"':'class="quatrevingtpercent"').$morealt.'">';
217
					$ret.=dol_string_neverthesehtmltags($valuetoshow, array('textarea'));
218
					$ret.='</textarea>';
219
				}
220
				elseif ($typeofdata == 'day' || $typeofdata == 'datepicker')
221
				{
222
					$ret.=$this->selectDate($value, $htmlname, 0, 0, 1, 'form'.$htmlname, 1, 0);
223
				}
224
				elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker')
225
				{
226
					$ret.=$this->selectDate($value, $htmlname, 1, 1, 1, 'form'.$htmlname, 1, 0);
227
				}
228
				elseif (preg_match('/^select;/', $typeofdata))
229
				{
230
					 $arraydata=explode(',', preg_replace('/^select;/', '', $typeofdata));
231
					 foreach($arraydata as $val)
232
					 {
233
						 $tmp=explode(':', $val);
234
						 $tmpkey=str_replace('|', ':', $tmp[0]);
235
						 $arraylist[$tmpkey]=$tmp[1];
236
					 }
237
					 $ret.=$this->selectarray($htmlname, $arraylist, $value);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $arraylist seems to be defined by a foreach iteration on line 231. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
238
				}
239
				elseif (preg_match('/^ckeditor/', $typeofdata))
240
				{
241
				    $tmp=explode(':', $typeofdata);		// Example: ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols:uselocalbrowser
242
					require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
243
					$doleditor=new DolEditor($htmlname, ($editvalue?$editvalue:$value), ($tmp[2]?$tmp[2]:''), ($tmp[3]?$tmp[3]:'100'), ($tmp[1]?$tmp[1]:'dolibarr_notes'), 'In', ($tmp[5]?$tmp[5]:0), (isset($tmp[8])?($tmp[8]?true:false):true), true, ($tmp[6]?$tmp[6]:'20'), ($tmp[7]?$tmp[7]:'100'));
244
					$ret.=$doleditor->Create(1);
245
				}
246
				if (empty($notabletag)) $ret.='</td>';
247
248
				if (empty($notabletag)) $ret.='<td class="left">';
249
				//else $ret.='<div class="clearboth"></div>';
250
			   	$ret.='<input type="submit" class="button'.(empty($notabletag)?'':' ').'" name="modify" value="'.$langs->trans("Modify").'">';
251
			   	if (preg_match('/ckeditor|textarea/', $typeofdata) && empty($notabletag)) $ret.='<br>'."\n";
252
			   	$ret.='<input type="submit" class="button'.(empty($notabletag)?'':' ').'" name="cancel" value="'.$langs->trans("Cancel").'">';
253
			   	if (empty($notabletag)) $ret.='</td>';
254
255
			   	if (empty($notabletag)) $ret.='</tr></table>'."\n";
256
				$ret.='</form>'."\n";
257
			}
258
			else
259
			{
260
				if (preg_match('/^(email)/', $typeofdata))              $ret.=dol_print_email($value, 0, 0, 0, 0, 1);
261
				elseif (preg_match('/^(amount|numeric)/', $typeofdata)) $ret.=($value != '' ? price($value, '', $langs, 0, -1, -1, $conf->currency) : '');
262
				elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata))  $ret.=dol_htmlentitiesbr($value);
263
				elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') $ret.=dol_print_date($value, 'day');
264
				elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') $ret.=dol_print_date($value, 'dayhour');
265
				elseif (preg_match('/^select;/', $typeofdata))
266
				{
267
					$arraydata=explode(',', preg_replace('/^select;/', '', $typeofdata));
268
					foreach($arraydata as $val)
269
					{
270
						$tmp=explode(':', $val);
271
						$arraylist[$tmp[0]]=$tmp[1];
272
					}
273
					$ret.=$arraylist[$value];
274
				}
275
				elseif (preg_match('/^ckeditor/', $typeofdata))
276
				{
277
					$tmpcontent=dol_htmlentitiesbr($value);
278
					if (! empty($conf->global->MAIN_DISABLE_NOTES_TAB))
279
					{
280
						$firstline=preg_replace('/<br>.*/', '', $tmpcontent);
281
						$firstline=preg_replace('/[\n\r].*/', '', $firstline);
282
						$tmpcontent=$firstline.((strlen($firstline) != strlen($tmpcontent))?'...':'');
283
					}
284
					$ret.=$tmpcontent;
285
				}
286
				else $ret.=$value;
287
288
				if ($formatfunc && method_exists($object, $formatfunc))
289
				{
290
					$ret=$object->$formatfunc($ret);
291
				}
292
			}
293
		}
294
		return $ret;
295
	}
296
297
	/**
298
	 * Output edit in place form
299
	 *
300
	 * @param	object	$object			Object
301
	 * @param	string	$value			Value to show/edit
302
	 * @param	string	$htmlname		DIV ID (field name)
303
	 * @param	int		$condition		Condition to edit
304
	 * @param	string	$inputType		Type of input ('string', 'numeric', 'datepicker' ('day' do not work, don't know why), 'textarea:rows:cols', 'ckeditor:dolibarr_zzz:width:height:?:1:rows:cols', 'select:loadmethod:savemethod:buttononly')
305
	 * @param	string	$editvalue		When in edit mode, use this value as $value instead of value
306
	 * @param	object	$extObject		External object
307
	 * @param	mixed	$custommsg		String or Array of custom messages : eg array('success' => 'MyMessage', 'error' => 'MyMessage')
308
	 * @return	string   		      	HTML edit in place
309
	 */
310
	private function editInPlace($object, $value, $htmlname, $condition, $inputType = 'textarea', $editvalue = null, $extObject = null, $custommsg = null)
311
	{
312
		global $conf;
313
314
		$out='';
315
316
		// Check parameters
317
		if (preg_match('/^text/', $inputType)) $value = dol_nl2br($value);
318
		elseif (preg_match('/^numeric/', $inputType)) $value = price($value);
319
		elseif ($inputType == 'day' || $inputType == 'datepicker') $value = dol_print_date($value, 'day');
320
321
		if ($condition)
322
		{
323
			$element		= false;
324
			$table_element	= false;
325
			$fk_element		= false;
326
			$loadmethod		= false;
327
			$savemethod		= false;
328
			$ext_element	= false;
329
			$button_only	= false;
330
			$inputOption    = '';
331
332
			if (is_object($object))
333
			{
334
				$element = $object->element;
335
				$table_element = $object->table_element;
336
				$fk_element = $object->id;
337
			}
338
339
			if (is_object($extObject))
340
			{
341
				$ext_element = $extObject->element;
342
			}
343
344
			if (preg_match('/^(string|email|numeric)/', $inputType))
345
			{
346
				$tmp=explode(':', $inputType);
347
				$inputType=$tmp[0];
348
				if (! empty($tmp[1])) $inputOption=$tmp[1];
349
				if (! empty($tmp[2])) $savemethod=$tmp[2];
350
				$out.= '<input id="width_'.$htmlname.'" value="'.$inputOption.'" type="hidden"/>'."\n";
351
			}
352
			elseif ((preg_match('/^day$/', $inputType)) || (preg_match('/^datepicker/', $inputType)) || (preg_match('/^datehourpicker/', $inputType)))
353
			{
354
				$tmp=explode(':', $inputType);
355
				$inputType=$tmp[0];
356
				if (! empty($tmp[1])) $inputOption=$tmp[1];
357
				if (! empty($tmp[2])) $savemethod=$tmp[2];
358
359
				$out.= '<input id="timestamp" type="hidden"/>'."\n"; // Use for timestamp format
360
			}
361
			elseif (preg_match('/^(select|autocomplete)/', $inputType))
362
			{
363
				$tmp=explode(':', $inputType);
364
				$inputType=$tmp[0]; $loadmethod=$tmp[1];
365
				if (! empty($tmp[2])) $savemethod=$tmp[2];
366
				if (! empty($tmp[3])) $button_only=true;
367
			}
368
			elseif (preg_match('/^textarea/', $inputType))
369
			{
370
				$tmp=explode(':', $inputType);
371
				$inputType=$tmp[0];
372
				$rows=(empty($tmp[1])?'8':$tmp[1]);
373
				$cols=(empty($tmp[2])?'80':$tmp[2]);
374
			}
375
			elseif (preg_match('/^ckeditor/', $inputType))
376
			{
377
				$tmp=explode(':', $inputType);
378
				$inputType=$tmp[0]; $toolbar=$tmp[1];
379
				if (! empty($tmp[2])) $width=$tmp[2];
380
				if (! empty($tmp[3])) $heigth=$tmp[3];
381
				if (! empty($tmp[4])) $savemethod=$tmp[4];
382
383
				if (! empty($conf->fckeditor->enabled))
384
				{
385
					$out.= '<input id="ckeditor_toolbar" value="'.$toolbar.'" type="hidden"/>'."\n";
386
				}
387
				else
388
				{
389
					$inputType = 'textarea';
390
				}
391
			}
392
393
			$out.= '<input id="element_'.$htmlname.'" value="'.$element.'" type="hidden"/>'."\n";
394
			$out.= '<input id="table_element_'.$htmlname.'" value="'.$table_element.'" type="hidden"/>'."\n";
395
			$out.= '<input id="fk_element_'.$htmlname.'" value="'.$fk_element.'" type="hidden"/>'."\n";
396
			$out.= '<input id="loadmethod_'.$htmlname.'" value="'.$loadmethod.'" type="hidden"/>'."\n";
1 ignored issue
show
Bug introduced by
Are you sure $loadmethod of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

396
			$out.= '<input id="loadmethod_'.$htmlname.'" value="'./** @scrutinizer ignore-type */ $loadmethod.'" type="hidden"/>'."\n";
Loading history...
397
			if (! empty($savemethod))	$out.= '<input id="savemethod_'.$htmlname.'" value="'.$savemethod.'" type="hidden"/>'."\n";
398
			if (! empty($ext_element))	$out.= '<input id="ext_element_'.$htmlname.'" value="'.$ext_element.'" type="hidden"/>'."\n";
399
			if (! empty($custommsg))
400
			{
401
				if (is_array($custommsg))
402
				{
403
					if (!empty($custommsg['success']))
404
						$out.= '<input id="successmsg_'.$htmlname.'" value="'.$custommsg['success'].'" type="hidden"/>'."\n";
405
					if (!empty($custommsg['error']))
406
						$out.= '<input id="errormsg_'.$htmlname.'" value="'.$custommsg['error'].'" type="hidden"/>'."\n";
407
				}
408
				else
409
					$out.= '<input id="successmsg_'.$htmlname.'" value="'.$custommsg.'" type="hidden"/>'."\n";
410
			}
411
			if ($inputType == 'textarea') {
412
				$out.= '<input id="textarea_'.$htmlname.'_rows" value="'.$rows.'" type="hidden"/>'."\n";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $rows does not seem to be defined for all execution paths leading up to this point.
Loading history...
413
				$out.= '<input id="textarea_'.$htmlname.'_cols" value="'.$cols.'" type="hidden"/>'."\n";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $cols does not seem to be defined for all execution paths leading up to this point.
Loading history...
414
			}
415
			$out.= '<span id="viewval_'.$htmlname.'" class="viewval_'.$inputType.($button_only ? ' inactive' : ' active').'">'.$value.'</span>'."\n";
416
			$out.= '<span id="editval_'.$htmlname.'" class="editval_'.$inputType.($button_only ? ' inactive' : ' active').' hideobject">'.(! empty($editvalue) ? $editvalue : $value).'</span>'."\n";
417
		}
418
		else
419
		{
420
			$out = $value;
421
		}
422
423
		return $out;
424
	}
425
426
	/**
427
	 *	Show a text and picto with tooltip on text or picto.
428
	 *  Can be called by an instancied $form->textwithtooltip or by a static call Form::textwithtooltip
429
	 *
430
	 *	@param	string		$text				Text to show
431
	 *	@param	string		$htmltext			HTML content of tooltip. Must be HTML/UTF8 encoded.
432
	 *	@param	int			$tooltipon			1=tooltip on text, 2=tooltip on image, 3=tooltip sur les 2
433
	 *	@param	int			$direction			-1=image is before, 0=no image, 1=image is after
434
	 *	@param	string		$img				Html code for image (use img_xxx() function to get it)
435
	 *	@param	string		$extracss			Add a CSS style to td tags
436
	 *	@param	int			$notabs				0=Include table and tr tags, 1=Do not include table and tr tags, 2=use div, 3=use span
437
	 *	@param	string		$incbefore			Include code before the text
438
	 *	@param	int			$noencodehtmltext	Do not encode into html entity the htmltext
439
	 *  @param  string      $tooltiptrigger		''=Tooltip on hover, 'abc'=Tooltip on click (abc is a unique key)
440
	 *  @param	int			$forcenowrap		Force no wrap between text and picto (works with notabs=2 only)
441
	 *	@return	string							Code html du tooltip (texte+picto)
442
	 *	@see	textwithpicto() Use thisfunction if you can.
443
	 *  TODO Move this as static as soon as everybody use textwithpicto or @Form::textwithtooltip
444
	 */
445
    public function textwithtooltip($text, $htmltext, $tooltipon = 1, $direction = 0, $img = '', $extracss = '', $notabs = 2, $incbefore = '', $noencodehtmltext = 0, $tooltiptrigger = '', $forcenowrap = 0)
446
	{
447
		global $conf;
448
449
		if ($incbefore) $text = $incbefore.$text;
450
		if (! $htmltext) return $text;
451
452
		$tag='td';
453
		if ($notabs == 2) $tag='div';
454
		if ($notabs == 3) $tag='span';
455
		// Sanitize tooltip
456
		//$htmltext=str_replace("\\","\\\\",$htmltext);
457
		$htmltext=str_replace("\r", "", $htmltext);
458
		$htmltext=str_replace("\n", "", $htmltext);
459
460
		$extrastyle='';
461
		if ($direction < 0) { $extracss=($extracss?$extracss.' ':'').'inline-block'; $extrastyle='padding: 0px; padding-left: 3px !important;'; }
462
		if ($direction > 0) { $extracss=($extracss?$extracss.' ':'').'inline-block'; $extrastyle='padding: 0px; padding-right: 3px !important;'; }
463
464
		$classfortooltip='classfortooltip';
465
466
		$s='';$textfordialog='';
467
468
		if ($tooltiptrigger == '')
469
		{
470
			$htmltext=str_replace('"', "&quot;", $htmltext);
471
		}
472
		else
473
		{
474
			$classfortooltip='classfortooltiponclick';
475
			$textfordialog.='<div style="display: none;" id="idfortooltiponclick_'.$tooltiptrigger.'" class="classfortooltiponclicktext">'.$htmltext.'</div>';
476
		}
477
		if ($tooltipon == 2 || $tooltipon == 3)
478
		{
479
			$paramfortooltipimg=' class="'.$classfortooltip.' inline-block'.($extracss?' '.$extracss:'').'" style="padding: 0px;'.($extrastyle?' '.$extrastyle:'').'"';
480
			if ($tooltiptrigger == '') $paramfortooltipimg.=' title="'.($noencodehtmltext?$htmltext:dol_escape_htmltag($htmltext, 1)).'"'; // Attribut to put on img tag to store tooltip
481
			else $paramfortooltipimg.=' dolid="'.$tooltiptrigger.'"';
482
		}
483
		else $paramfortooltipimg =($extracss?' class="'.$extracss.'"':'').($extrastyle?' style="'.$extrastyle.'"':''); // Attribut to put on td text tag
484
		if ($tooltipon == 1 || $tooltipon == 3)
485
		{
486
			$paramfortooltiptd=' class="'.($tooltipon == 3 ? 'cursorpointer ' : '').$classfortooltip.' inline-block'.($extracss?' '.$extracss:'').'" style="padding: 0px;'.($extrastyle?' '.$extrastyle:'').'" ';
487
			if ($tooltiptrigger == '') $paramfortooltiptd.=' title="'.($noencodehtmltext?$htmltext:dol_escape_htmltag($htmltext, 1)).'"'; // Attribut to put on td tag to store tooltip
488
			else $paramfortooltiptd.=' dolid="'.$tooltiptrigger.'"';
489
		}
490
		else $paramfortooltiptd =($extracss?' class="'.$extracss.'"':'').($extrastyle?' style="'.$extrastyle.'"':''); // Attribut to put on td text tag
491
		if (empty($notabs)) $s.='<table class="nobordernopadding"><tr style="height: auto;">';
492
		elseif ($notabs == 2) $s.='<div class="inline-block'.($forcenowrap?' nowrap':'').'">';
493
		// Define value if value is before
494
		if ($direction < 0) {
495
			$s.='<'.$tag.$paramfortooltipimg;
496
			if ($tag == 'td') {
497
				$s .= ' class=valigntop" width="14"';
498
			}
499
			$s.= '>'.$textfordialog.$img.'</'.$tag.'>';
500
		}
501
		// Use another method to help avoid having a space in value in order to use this value with jquery
502
		// Define label
503
		if ((string) $text != '') $s.='<'.$tag.$paramfortooltiptd.'>'.$text.'</'.$tag.'>';
504
		// Define value if value is after
505
		if ($direction > 0) {
506
			$s.='<'.$tag.$paramfortooltipimg;
507
			if ($tag == 'td') $s .= ' class="valignmiddle" width="14"';
508
			$s.= '>'.$textfordialog.$img.'</'.$tag.'>';
509
		}
510
		if (empty($notabs)) $s.='</tr></table>';
511
		elseif ($notabs == 2) $s.='</div>';
512
513
		return $s;
514
	}
515
516
	/**
517
	 *	Show a text with a picto and a tooltip on picto
518
	 *
519
	 *	@param	string	$text				Text to show
520
	 *	@param  string	$htmltext	     	Content of tooltip
521
	 *	@param	int		$direction			1=Icon is after text, -1=Icon is before text, 0=no icon
522
	 * 	@param	string	$type				Type of picto ('info', 'help', 'warning', 'superadmin', 'mypicto@mymodule', ...) or image filepath or 'none'
523
	 *  @param  string	$extracss           Add a CSS style to td, div or span tag
524
	 *  @param  int		$noencodehtmltext   Do not encode into html entity the htmltext
525
	 *  @param	int		$notabs				0=Include table and tr tags, 1=Do not include table and tr tags, 2=use div, 3=use span
526
	 *  @param  string  $tooltiptrigger     ''=Tooltip on hover, 'abc'=Tooltip on click (abc is a unique key)
527
	 *  @param	int		$forcenowrap		Force no wrap between text and picto (works with notabs=2 only)
528
	 * 	@return	string						HTML code of text, picto, tooltip
529
	 */
530
    public function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 2, $tooltiptrigger = '', $forcenowrap = 0)
531
	{
532
		global $conf, $langs;
533
534
		$alt = '';
535
		if ($tooltiptrigger) $alt=$langs->transnoentitiesnoconv("ClickToShowHelp");
536
537
		//For backwards compatibility
538
		if ($type == '0') $type = 'info';
539
		elseif ($type == '1') $type = 'help';
540
541
		// If info or help with no javascript, show only text
542
		if (empty($conf->use_javascript_ajax))
543
		{
544
			if ($type == 'info' || $type == 'help')	return $text;
545
			else
546
			{
547
				$alt = $htmltext;
548
				$htmltext = '';
549
			}
550
		}
551
552
		// If info or help with smartphone, show only text (tooltip hover can't works)
553
		if (! empty($conf->dol_no_mouse_hover) && empty($tooltiptrigger))
554
		{
555
			if ($type == 'info' || $type == 'help') return $text;
556
		}
557
		// If info or help with smartphone, show only text (tooltip on click does not works with dialog on smaprtphone)
558
		//if (! empty($conf->dol_no_mouse_hover) && ! empty($tooltiptrigger))
559
		//{
560
			//if ($type == 'info' || $type == 'help') return '<a href="'..'">'.$text.''</a>';
561
		//}
562
563
		$img='';
564
		if ($type == 'info') $img = img_help(0, $alt);
565
		elseif ($type == 'help') $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
566
		elseif ($type == 'superadmin') $img = img_picto($alt, 'redstar');
567
		elseif ($type == 'admin') $img = img_picto($alt, 'star');
568
		elseif ($type == 'warning') $img = img_warning($alt);
569
		elseif ($type != 'none') $img = img_picto($alt, $type);   // $type can be an image path
570
571
		return $this->textwithtooltip($text, $htmltext, (($tooltiptrigger && ! $img)?3:2), $direction, $img, $extracss, $notabs, '', $noencodehtmltext, $tooltiptrigger, $forcenowrap);
572
	}
573
574
	/**
575
	 * Generate select HTML to choose massaction
576
	 *
577
	 * @param	string	$selected		Value auto selected when at least one record is selected. Not a preselected value. Use '0' by default.
578
	 * @param	int		$arrayofaction	array('code'=>'label', ...). The code is the key stored into the GETPOST('massaction') when submitting action.
579
	 * @param   int     $alwaysvisible  1=select button always visible
580
	 * @return	string					Select list
581
	 */
582
    public function selectMassAction($selected, $arrayofaction, $alwaysvisible = 0)
583
	{
584
		global $conf,$langs,$hookmanager;
585
586
		if (count($arrayofaction) == 0) return;
587
588
		$disabled=0;
589
		$ret='<div class="centpercent center">';
590
		$ret.='<select class="flat'.(empty($conf->use_javascript_ajax)?'':' hideobject').' massaction massactionselect valignmiddle" name="massaction"'.($disabled?' disabled="disabled"':'').'>';
591
592
		// 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.
593
		$parameters=array();
594
		$reshook=$hookmanager->executeHooks('addMoreMassActions', $parameters);    // Note that $action and $object may have been modified by hook
595
		if (empty($reshook))
596
		{
597
			$ret.='<option value="0"'.($disabled?' disabled="disabled"':'').'>-- '.$langs->trans("SelectAction").' --</option>';
598
			foreach($arrayofaction as $code => $label)
0 ignored issues
show
Bug introduced by
The expression $arrayofaction of type integer is not traversable.
Loading history...
599
			{
600
				$ret.='<option value="'.$code.'"'.($disabled?' disabled="disabled"':'').' data-html="'.dol_escape_htmltag($label).'">'.$label.'</option>';
601
			}
602
		}
603
		$ret.=$hookmanager->resPrint;
604
605
		$ret.='</select>';
606
607
		if (empty($conf->dol_optimize_smallscreen)) $ret.=ajax_combobox('.massactionselect');
608
609
		// 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
610
		$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.
611
		$ret.='<input type="submit" disabled name="confirmmassaction" class="button'.(empty($conf->use_javascript_ajax)?'':' hideobject').' massaction massactionconfirmed" value="'.dol_escape_htmltag($langs->trans("Confirm")).'">';
612
		$ret.='</div>';
613
614
		if (! empty($conf->use_javascript_ajax))
615
		{
616
			$ret.='<!-- JS CODE TO ENABLE mass action select -->
617
    		<script>
618
        		function initCheckForSelect(mode)	/* mode is 0 during init of page or click all, 1 when we click on 1 checkbox */
619
        		{
620
        			atleastoneselected=0;
621
    	    		jQuery(".checkforselect").each(function( index ) {
622
    	  				/* console.log( index + ": " + $( this ).text() ); */
623
    	  				if ($(this).is(\':checked\')) atleastoneselected++;
624
    	  			});
625
					console.log("initCheckForSelect mode="+mode+" atleastoneselected="+atleastoneselected);
626
    	  			if (atleastoneselected || '.$alwaysvisible.')
627
    	  			{
628
    	  				jQuery(".massaction").show();
629
        			    '.($selected ? 'if (atleastoneselected) { jQuery(".massactionselect").val("'.$selected.'"); jQuery(".massactionconfirmed").prop(\'disabled\', false); }' : '').'
630
        			    '.($selected ? 'if (! atleastoneselected) { jQuery(".massactionselect").val("0"); jQuery(".massactionconfirmed").prop(\'disabled\', true); } ' : '').'
631
    	  			}
632
    	  			else
633
    	  			{
634
    	  				jQuery(".massaction").hide();
635
    	            }
636
        		}
637
638
        	jQuery(document).ready(function () {
639
        		initCheckForSelect(0);
640
        		jQuery(".checkforselect").click(function() {
641
        			initCheckForSelect(1);
642
    	  		});
643
    	  		jQuery(".massactionselect").change(function() {
644
        			var massaction = $( this ).val();
645
        			var urlform = $( this ).closest("form").attr("action").replace("#show_files","");
646
        			if (massaction == "builddoc")
647
                    {
648
                        urlform = urlform + "#show_files";
649
    	            }
650
        			$( this ).closest("form").attr("action", urlform);
651
                    console.log("we select a mass action "+massaction+" - "+urlform);
652
        	        /* Warning: if you set submit button to disabled, post using Enter will no more work if there is no other button */
653
        			if ($(this).val() != \'0\')
654
    	  			{
655
    	  				jQuery(".massactionconfirmed").prop(\'disabled\', false);
656
    	  			}
657
    	  			else
658
    	  			{
659
    	  				jQuery(".massactionconfirmed").prop(\'disabled\', true);
660
    	  			}
661
    	        });
662
        	});
663
    		</script>
664
        	';
665
		}
666
667
		return $ret;
668
	}
669
670
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
671
	/**
672
	 *  Return combo list of activated countries, into language of user
673
	 *
674
	 *  @param	string	$selected       	Id or Code or Label of preselected country
675
	 *  @param  string	$htmlname       	Name of html select object
676
	 *  @param  string	$htmloption     	More html options on select object
677
	 *  @param	integer	$maxlength			Max length for labels (0=no limit)
678
	 *  @param	string	$morecss			More css class
679
	 *  @param	string	$usecodeaskey		''=Use id as key (default), 'code3'=Use code on 3 alpha as key, 'code2"=Use code on 2 alpha as key
680
	 *  @param	int		$showempty			Show empty choice
681
	 *  @param	int		$disablefavorites	1=Disable favorites,
682
	 *  @param	int		$addspecialentries	1=Add dedicated entries for group of countries (like 'European Economic Community', ...)
683
	 *  @return string           			HTML string with select
684
	 */
685
    public function select_country($selected = '', $htmlname = 'country_id', $htmloption = '', $maxlength = 0, $morecss = 'minwidth300', $usecodeaskey = '', $showempty = 1, $disablefavorites = 0, $addspecialentries = 0)
686
	{
687
        // phpcs:enable
688
		global $conf,$langs,$mysoc;
689
690
		$langs->load("dict");
691
692
		$out='';
693
		$countryArray=array();
694
		$favorite=array();
695
		$label=array();
696
		$atleastonefavorite=0;
697
698
		$sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite";
699
		$sql.= " FROM ".MAIN_DB_PREFIX."c_country";
700
		$sql.= " WHERE active > 0";
701
		//$sql.= " ORDER BY code ASC";
702
703
		dol_syslog(get_class($this)."::select_country", LOG_DEBUG);
704
		$resql=$this->db->query($sql);
705
		if ($resql)
706
		{
707
			$out.= '<select id="select'.$htmlname.'" class="flat maxwidth200onsmartphone selectcountry'.($morecss?' '.$morecss:'').'" name="'.$htmlname.'" '.$htmloption.'>';
708
			$num = $this->db->num_rows($resql);
709
			$i = 0;
710
			if ($num)
711
			{
712
				$foundselected=false;
713
714
				while ($i < $num)
715
				{
716
					$obj = $this->db->fetch_object($resql);
717
					$countryArray[$i]['rowid'] 		= $obj->rowid;
718
					$countryArray[$i]['code_iso'] 	= $obj->code_iso;
719
					$countryArray[$i]['code_iso3'] 	= $obj->code_iso3;
720
					$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:''));
721
					$countryArray[$i]['favorite']   = $obj->favorite;
722
					$favorite[$i]					= $obj->favorite;
723
					$label[$i] = dol_string_unaccent($countryArray[$i]['label']);
724
					$i++;
725
				}
726
727
				if (empty($disablefavorites)) array_multisort($favorite, SORT_DESC, $label, SORT_ASC, $countryArray);
728
				else $countryArray = dol_sort_array($countryArray, 'label');
729
730
				if ($showempty)
731
				{
732
					$out.='<option value="">&nbsp;</option>'."\n";
733
				}
734
735
				if ($addspecialentries)	// Add dedicated entries for groups of countries
736
				{
737
					//if ($showempty) $out.= '<option value="" disabled class="selectoptiondisabledwhite">--------------</option>';
738
					$out.= '<option value="special_allnotme"'.($selected == 'special_allnotme' ? ' selected' : '').'>'.$langs->trans("CountriesExceptMe", $langs->transnoentitiesnoconv("Country".$mysoc->country_code)).'</option>';
739
					$out.= '<option value="special_eec"'.($selected == 'special_eec' ? ' selected' : '').'>'.$langs->trans("CountriesInEEC").'</option>';
740
					if ($mysoc->isInEEC()) $out.= '<option value="special_eecnotme"'.($selected == 'special_eecnotme' ? ' selected' : '').'>'.$langs->trans("CountriesInEECExceptMe", $langs->transnoentitiesnoconv("Country".$mysoc->country_code)).'</option>';
741
					$out.= '<option value="special_noteec"'.($selected == 'special_noteec' ? ' selected' : '').'>'.$langs->trans("CountriesNotInEEC").'</option>';
742
					$out.= '<option value="" disabled class="selectoptiondisabledwhite">--------------</option>';
743
				}
744
745
				foreach ($countryArray as $row)
746
				{
747
					//if (empty($showempty) && empty($row['rowid'])) continue;
748
					if (empty($row['rowid'])) continue;
749
750
					if (empty($disablefavorites) && $row['favorite'] && $row['code_iso']) $atleastonefavorite++;
751
					if (empty($row['favorite']) && $atleastonefavorite)
752
					{
753
						$atleastonefavorite=0;
754
						$out.= '<option value="" disabled class="selectoptiondisabledwhite">--------------</option>';
755
					}
756
					if ($selected && $selected != '-1' && ($selected == $row['rowid'] || $selected == $row['code_iso'] || $selected == $row['code_iso3'] || $selected == $row['label']) )
757
					{
758
						$foundselected=true;
759
						$out.= '<option value="'.($usecodeaskey?($usecodeaskey=='code2'?$row['code_iso']:$row['code_iso3']):$row['rowid']).'" selected>';
760
					}
761
					else
762
					{
763
						$out.= '<option value="'.($usecodeaskey?($usecodeaskey=='code2'?$row['code_iso']:$row['code_iso3']):$row['rowid']).'">';
764
					}
765
					if ($row['label']) $out.= dol_trunc($row['label'], $maxlength, 'middle');
766
					else $out.= '&nbsp;';
767
					if ($row['code_iso']) $out.= ' ('.$row['code_iso'] . ')';
768
					$out.= '</option>';
769
				}
770
			}
771
			$out.= '</select>';
772
		}
773
		else
774
		{
775
			dol_print_error($this->db);
776
		}
777
778
		// Make select dynamic
779
		include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
780
		$out .= ajax_combobox('select'.$htmlname);
781
782
		return $out;
783
	}
784
785
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
786
	/**
787
	 *  Return select list of incoterms
788
	 *
789
	 *  @param	string	$selected       		Id or Code of preselected incoterm
790
	 *  @param	string	$location_incoterms     Value of input location
791
	 *  @param	string	$page       			Defined the form action
792
	 *  @param  string	$htmlname       		Name of html select object
793
	 *  @param  string	$htmloption     		Options html on select object
794
	 * 	@param	int		$forcecombo				Force to load all values and output a standard combobox (with no beautification)
795
	 *  @param	array	$events					Event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
796
	 *  @return string           				HTML string with select and input
797
	 */
798
    public function select_incoterms($selected = '', $location_incoterms = '', $page = '', $htmlname = 'incoterm_id', $htmloption = '', $forcecombo = 1, $events = array())
799
	{
800
        // phpcs:enable
801
		global $conf,$langs;
802
803
		$langs->load("dict");
804
805
		$out='';
806
		$incotermArray=array();
807
808
		$sql = "SELECT rowid, code";
809
		$sql.= " FROM ".MAIN_DB_PREFIX."c_incoterms";
810
		$sql.= " WHERE active > 0";
811
		$sql.= " ORDER BY code ASC";
812
813
		dol_syslog(get_class($this)."::select_incoterm", LOG_DEBUG);
814
		$resql=$this->db->query($sql);
815
		if ($resql)
816
		{
817
			if ($conf->use_javascript_ajax && ! $forcecombo)
818
			{
819
				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
820
				$out .= ajax_combobox($htmlname, $events);
821
			}
822
823
			if (!empty($page))
824
			{
825
				$out .= '<form method="post" action="'.$page.'">';
826
				$out .= '<input type="hidden" name="action" value="set_incoterms">';
827
				$out .= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
828
			}
829
830
			$out.= '<select id="'.$htmlname.'" class="flat selectincoterm minwidth100imp noenlargeonsmartphone" name="'.$htmlname.'" '.$htmloption.'>';
831
			$out.= '<option value="0">&nbsp;</option>';
832
			$num = $this->db->num_rows($resql);
833
			$i = 0;
834
			if ($num)
835
			{
836
				$foundselected=false;
837
838
				while ($i < $num)
839
				{
840
					$obj = $this->db->fetch_object($resql);
841
					$incotermArray[$i]['rowid'] = $obj->rowid;
842
					$incotermArray[$i]['code'] = $obj->code;
843
					$i++;
844
				}
845
846
				foreach ($incotermArray as $row)
847
				{
848
					if ($selected && ($selected == $row['rowid'] || $selected == $row['code']))
849
					{
850
						$out.= '<option value="'.$row['rowid'].'" selected>';
851
					}
852
					else
853
					{
854
						$out.= '<option value="'.$row['rowid'].'">';
855
					}
856
857
					if ($row['code']) $out.= $row['code'];
858
859
					$out.= '</option>';
860
				}
861
			}
862
			$out.= '</select>';
863
864
			$out .= '<input id="location_incoterms" class="maxwidth100onsmartphone" name="location_incoterms" value="'.$location_incoterms.'">';
865
866
			if (!empty($page))
867
			{
868
				$out .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'"></form>';
869
			}
870
		}
871
		else
872
		{
873
			dol_print_error($this->db);
874
		}
875
876
		return $out;
877
	}
878
879
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
880
	/**
881
	 *	Return list of types of lines (product or service)
882
	 * 	Example: 0=product, 1=service, 9=other (for external module)
883
	 *
884
	 *	@param  string	$selected       Preselected type
885
	 *	@param  string	$htmlname       Name of field in html form
886
	 * 	@param	int		$showempty		Add an empty field
887
	 * 	@param	int		$hidetext		Do not show label 'Type' before combo box (used only if there is at least 2 choices to select)
888
	 * 	@param	integer	$forceall		1=Force to show products and services in combo list, whatever are activated modules, 0=No force, 2=Force to show only Products, 3=Force to show only services, -1=Force none (and set hidden field to 'service')
889
	 *  @return	void
890
	 */
891
    public function select_type_of_lines($selected = '', $htmlname = 'type', $showempty = 0, $hidetext = 0, $forceall = 0)
892
	{
893
        // phpcs:enable
894
		global $db,$langs,$user,$conf;
895
896
		// If product & services are enabled or both disabled.
897
		if ($forceall == 1 || (empty($forceall) && ! empty($conf->product->enabled) && ! empty($conf->service->enabled))
898
		|| (empty($forceall) && empty($conf->product->enabled) && empty($conf->service->enabled)) )
899
		{
900
			if (empty($hidetext)) print $langs->trans("Type").': ';
901
			print '<select class="flat" id="select_'.$htmlname.'" name="'.$htmlname.'">';
902
			if ($showempty)
903
			{
904
				print '<option value="-1"';
905
				if ($selected == -1) print ' selected';
906
				print '>&nbsp;</option>';
907
			}
908
909
			print '<option value="0"';
910
			if (0 == $selected) print ' selected';
911
			print '>'.$langs->trans("Product");
912
913
			print '<option value="1"';
914
			if (1 == $selected) print ' selected';
915
			print '>'.$langs->trans("Service");
916
917
			print '</select>';
918
			//if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
919
		}
920
		if ((empty($forceall) && empty($conf->product->enabled) && ! empty($conf->service->enabled)) || $forceall == 3)
921
		{
922
			print $langs->trans("Service");
923
			print '<input type="hidden" name="'.$htmlname.'" value="1">';
924
		}
925
		if ((empty($forceall) && ! empty($conf->product->enabled) && empty($conf->service->enabled)) || $forceall == 2)
926
		{
927
			print $langs->trans("Product");
928
			print '<input type="hidden" name="'.$htmlname.'" value="0">';
929
		}
930
		if ($forceall < 0)	// This should happened only for contracts when both predefined product and service are disabled.
931
		{
932
			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
933
		}
934
	}
935
936
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
937
	/**
938
	 *	Load into cache cache_types_fees, array of types of fees
939
	 *
940
	 *	@return     int             Nb of lines loaded, <0 if KO
941
	 */
942
    public function load_cache_types_fees()
943
	{
944
        // phpcs:enable
945
		global $langs;
946
947
		$num = count($this->cache_types_fees);
948
		if ($num > 0) return 0;    // Cache already loaded
949
950
		dol_syslog(__METHOD__, LOG_DEBUG);
951
952
		$langs->load("trips");
953
954
		$sql = "SELECT c.code, c.label";
955
		$sql.= " FROM ".MAIN_DB_PREFIX."c_type_fees as c";
956
		$sql.= " WHERE active > 0";
957
958
		$resql=$this->db->query($sql);
959
		if ($resql)
960
		{
961
			$num = $this->db->num_rows($resql);
962
			$i = 0;
963
964
			while ($i < $num)
965
			{
966
				$obj = $this->db->fetch_object($resql);
967
968
				// Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
969
				$label=($obj->code != $langs->trans($obj->code) ? $langs->trans($obj->code) : $langs->trans($obj->label));
970
				$this->cache_types_fees[$obj->code] = $label;
971
				$i++;
972
			}
973
974
			asort($this->cache_types_fees);
975
976
			return $num;
977
		}
978
		else
979
		{
980
			dol_print_error($this->db);
981
			return -1;
982
		}
983
	}
984
985
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
986
	/**
987
	 *	Return list of types of notes
988
	 *
989
	 *	@param	string		$selected		Preselected type
990
	 *	@param  string		$htmlname		Name of field in form
991
	 * 	@param	int			$showempty		Add an empty field
992
	 * 	@return	void
993
	 */
994
    public function select_type_fees($selected = '', $htmlname = 'type', $showempty = 0)
995
	{
996
        // phpcs:enable
997
		global $user, $langs;
998
999
		dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG);
1000
1001
		$this->load_cache_types_fees();
1002
1003
		print '<select id="select_'.$htmlname.'" class="flat" name="'.$htmlname.'">';
1004
		if ($showempty)
1005
		{
1006
			print '<option value="-1"';
1007
			if ($selected == -1) print ' selected';
1008
			print '>&nbsp;</option>';
1009
		}
1010
1011
		foreach($this->cache_types_fees as $key => $value)
1012
		{
1013
			print '<option value="'.$key.'"';
1014
			if ($key == $selected) print ' selected';
1015
			print '>';
1016
			print $value;
1017
			print '</option>';
1018
		}
1019
1020
		print '</select>';
1021
		if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1022
	}
1023
1024
1025
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1026
	/**
1027
	 *  Return HTML code to select a company.
1028
	 *
1029
	 *  @param		int			$selected				Preselected products
1030
	 *  @param		string		$htmlname				Name of HTML select field (must be unique in page)
1031
	 *  @param		int			$filter					Filter on thirdparty
1032
	 *  @param		int			$limit					Limit on number of returned lines
1033
	 *  @param		array		$ajaxoptions			Options for ajax_autocompleter
1034
	 * 	@param		int			$forcecombo				Force to load all values and output a standard combobox (with no beautification)
1035
	 *  @return		string								Return select box for thirdparty.
1036
	 *  @deprecated	3.8 Use select_company instead. For exemple $form->select_thirdparty(GETPOST('socid'),'socid','',0) => $form->select_company(GETPOST('socid'),'socid','',1,0,0,array(),0)
1037
	 */
1038
    public function select_thirdparty($selected = '', $htmlname = 'socid', $filter = '', $limit = 20, $ajaxoptions = array(), $forcecombo = 0)
1039
	{
1040
        // phpcs:enable
1041
   		return $this->select_thirdparty_list($selected, $htmlname, $filter, 1, 0, $forcecombo, array(), '', 0, $limit);
1042
	}
1043
1044
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1045
	/**
1046
	 *  Output html form to select a third party
1047
	 *
1048
	 *	@param	string	$selected       		Preselected type
1049
	 *	@param  string	$htmlname       		Name of field in form
1050
	 *  @param  string	$filter         		Optional filters criteras. WARNING: To avoid SQL injection, only few chars [.a-z0-9 =<>] are allowed here (example: 's.rowid <> x', 's.client IN (1,3)')
1051
	 *	@param	string	$showempty				Add an empty field (Can be '1' or text key to use on empty line like 'SelectThirdParty')
1052
	 * 	@param	int		$showtype				Show third party type in combolist (customer, prospect or supplier)
1053
	 * 	@param	int		$forcecombo				Force to load all values and output a standard combobox (with no beautification)
1054
	 *  @param	array	$events					Ajax event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
1055
	 *	@param	int		$limit					Maximum number of elements
1056
	 *  @param	string	$morecss				Add more css styles to the SELECT component
1057
	 *	@param  string	$moreparam      		Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
1058
	 *	@param	string	$selected_input_value	Value of preselected input text (for use with ajax)
1059
	 *  @param	int		$hidelabel				Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after)
1060
	 *  @param	array	$ajaxoptions			Options for ajax_autocompleter
1061
	 * 	@param  bool	$multiple				add [] in the name of element and add 'multiple' attribut (not working with ajax_autocompleter)
1062
	 * 	@return	string							HTML string with select box for thirdparty.
1063
	 */
1064
    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)
1065
	{
1066
        // phpcs:enable
1067
		global $conf,$user,$langs;
1068
1069
		$out='';
1070
1071
		if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT) && ! $forcecombo)
1072
		{
1073
			// No immediate load of all database
1074
			$placeholder='';
1075
			if ($selected && empty($selected_input_value))
1076
			{
1077
				require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1078
				$societetmp = new Societe($this->db);
1079
				$societetmp->fetch($selected);
1080
				$selected_input_value=$societetmp->name;
1081
				unset($societetmp);
1082
			}
1083
			// mode 1
1084
			$urloption='htmlname='.urlencode($htmlname).'&outjson=1&filter='.urlencode($filter).($showtype?'&showtype='.urlencode($showtype):'');
1085
			$out.=  ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/societe/ajax/company.php', $urloption, $conf->global->COMPANY_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
1086
			$out.='<style type="text/css">.ui-autocomplete { z-index: 250; }</style>';
1087
			if (empty($hidelabel)) print $langs->trans("RefOrLabel").' : ';
1088
			elseif ($hidelabel > 1) {
1089
				$placeholder=' placeholder="'.$langs->trans("RefOrLabel").'"';
1090
				if ($hidelabel == 2) {
1091
					$out.=  img_picto($langs->trans("Search"), 'search');
1092
				}
1093
			}
1094
			$out.= '<input type="text" class="'.$morecss.'" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' '.(!empty($conf->global->THIRDPARTY_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />';
1095
			if ($hidelabel == 3) {
1096
				$out.=  img_picto($langs->trans("Search"), 'search');
1097
			}
1098
		}
1099
		else
1100
		{
1101
			// Immediate load of all database
1102
			$out.=$this->select_thirdparty_list($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, '', 0, $limit, $morecss, $moreparam, $multiple);
1103
		}
1104
1105
		return $out;
1106
	}
1107
1108
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1109
	/**
1110
	 *  Output html form to select a third party.
1111
	 *  Note, you must use the select_company to get the component to select a third party. This function must only be called by select_company.
1112
	 *
1113
	 *	@param	string	$selected       Preselected type
1114
	 *	@param  string	$htmlname       Name of field in form
1115
	 *  @param  string	$filter         Optional filters criteras (example: 's.rowid <> x', 's.client in (1,3)')
1116
	 *	@param	string	$showempty		Add an empty field (Can be '1' or text to use on empty line like 'SelectThirdParty')
1117
	 * 	@param	int		$showtype		Show third party type in combolist (customer, prospect or supplier)
1118
	 * 	@param	int		$forcecombo		Force to use standard HTML select component without beautification
1119
	 *  @param	array	$events			Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
1120
	 *  @param	string	$filterkey		Filter on key value
1121
	 *  @param	int		$outputmode		0=HTML select string, 1=Array
1122
	 *  @param	int		$limit			Limit number of answers
1123
	 *  @param	string	$morecss		Add more css styles to the SELECT component
1124
	 *	@param  string	$moreparam      Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
1125
	 *	@param  bool	$multiple       add [] in the name of element and add 'multiple' attribut
1126
	 * 	@return	string					HTML string with
1127
	 */
1128
    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)
1129
	{
1130
        // phpcs:enable
1131
		global $conf,$user,$langs;
1132
1133
		$out='';
1134
		$num=0;
1135
		$outarray=array();
1136
1137
		if ($selected === '') $selected = array();
1138
		elseif (!is_array($selected)) $selected = array($selected);
0 ignored issues
show
introduced by
The condition is_array($selected) is always false.
Loading history...
1139
1140
		// Clean $filter that may contains sql conditions so sql code
1141
		if (function_exists('testSqlAndScriptInject')) {
1142
			if (testSqlAndScriptInject($filter, 3) > 0) {
1143
				$filter ='';
1144
			}
1145
		}
1146
1147
		// On recherche les societes
1148
		$sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.client, s.fournisseur, s.code_client, s.code_fournisseur";
1149
1150
		if ($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST) {
1151
			$sql .= ", s.address, s.zip, s.town";
1152
		 	$sql .= ", dictp.code as country_code";
1153
		}
1154
1155
		$sql.= " FROM (".MAIN_DB_PREFIX ."societe as s";
1156
		if (!$user->rights->societe->client->voir && !$user->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
1157
		$sql.= " )";
1158
		if ($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST) {
1159
			$sql.= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."c_country as dictp ON dictp.rowid=s.fk_pays";
1160
		}
1161
		$sql.= " WHERE s.entity IN (".getEntity('societe').")";
1162
		if (! empty($user->socid)) $sql.= " AND s.rowid = ".$user->socid;
1163
		if ($filter) $sql.= " AND (".$filter.")";
1164
		if (!$user->rights->societe->client->voir && !$user->socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
1165
		if (! empty($conf->global->COMPANY_HIDE_INACTIVE_IN_COMBOBOX)) $sql.= " AND s.status <> 0";
1166
		// Add criteria
1167
		if ($filterkey && $filterkey != '')
1168
		{
1169
			$sql.=" AND (";
1170
			$prefix=empty($conf->global->COMPANY_DONOTSEARCH_ANYWHERE)?'%':'';	// Can use index if COMPANY_DONOTSEARCH_ANYWHERE is on
1171
			// For natural search
1172
			$scrit = explode(' ', $filterkey);
1173
			$i=0;
1174
			if (count($scrit) > 1) $sql.="(";
1175
			foreach ($scrit as $crit) {
1176
				if ($i > 0) $sql.=" AND ";
1177
				$sql.="(s.nom LIKE '".$this->db->escape($prefix.$crit)."%')";
1178
				$i++;
1179
			}
1180
			if (count($scrit) > 1) $sql.=")";
1181
			if (! empty($conf->barcode->enabled))
1182
			{
1183
				$sql .= " OR s.barcode LIKE '".$this->db->escape($prefix.$filterkey)."%'";
1184
			}
1185
			$sql.= " OR s.code_client LIKE '".$this->db->escape($prefix.$filterkey)."%' OR s.code_fournisseur LIKE '".$this->db->escape($prefix.$filterkey)."%'";
1186
			$sql.=")";
1187
		}
1188
		$sql.=$this->db->order("nom", "ASC");
1189
		$sql.=$this->db->plimit($limit, 0);
1190
1191
		// Build output string
1192
		dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
1193
		$resql=$this->db->query($sql);
1194
		if ($resql)
1195
		{
1196
		   	if (! $forcecombo)
1197
			{
1198
				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1199
				$out .= ajax_combobox($htmlname, $events, $conf->global->COMPANY_USE_SEARCH_TO_SELECT);
1200
			}
1201
1202
			// Construct $out and $outarray
1203
			$out.= '<select id="'.$htmlname.'" class="flat'.($morecss?' '.$morecss:'').'"'.($moreparam?' '.$moreparam:'').' name="'.$htmlname.($multiple ? '[]' : '').'" '.($multiple ? 'multiple' : '').'>'."\n";
1204
1205
			$textifempty='';
1206
			// Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
1207
			//if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
1208
			if (! empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT))
1209
			{
1210
				if ($showempty && ! is_numeric($showempty)) $textifempty=$langs->trans($showempty);
1211
				else $textifempty.=$langs->trans("All");
1212
			}
1213
			if ($showempty) $out.= '<option value="-1">'.$textifempty.'</option>'."\n";
1214
1215
			$num = $this->db->num_rows($resql);
1216
			$i = 0;
1217
			if ($num)
1218
			{
1219
				while ($i < $num)
1220
				{
1221
					$obj = $this->db->fetch_object($resql);
1222
					$label='';
1223
					if ($conf->global->SOCIETE_ADD_REF_IN_LIST) {
1224
						if (($obj->client) && (!empty($obj->code_client))) {
1225
							$label = $obj->code_client. ' - ';
1226
						}
1227
						if (($obj->fournisseur) && (!empty($obj->code_fournisseur))) {
1228
							$label .= $obj->code_fournisseur. ' - ';
1229
						}
1230
						$label.=' '.$obj->name;
1231
					}
1232
					else
1233
					{
1234
						$label=$obj->name;
1235
					}
1236
1237
					if(!empty($obj->name_alias)) {
1238
						$label.=' ('.$obj->name_alias.')';
1239
					}
1240
1241
					if ($showtype)
1242
					{
1243
						if ($obj->client || $obj->fournisseur) $label.=' (';
1244
						if ($obj->client == 1 || $obj->client == 3) $label.=$langs->trans("Customer");
1245
						if ($obj->client == 2 || $obj->client == 3) $label.=($obj->client==3?', ':'').$langs->trans("Prospect");
1246
						if ($obj->fournisseur) $label.=($obj->client?', ':'').$langs->trans("Supplier");
1247
						if ($obj->client || $obj->fournisseur) $label.=')';
1248
					}
1249
1250
					if ($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST) {
1251
						$label.='-'.$obj->address.'-'. $obj->zip.' '. $obj->town;
1252
						if (!empty($obj->country_code)) {
1253
							$label.= ' '. $langs->trans('Country'.$obj->country_code);
1254
						}
1255
					}
1256
1257
					if (empty($outputmode))
1258
					{
1259
						if (in_array($obj->rowid, $selected))
1260
						{
1261
							$out.= '<option value="'.$obj->rowid.'" selected>'.$label.'</option>';
1262
						}
1263
						else
1264
						{
1265
							$out.= '<option value="'.$obj->rowid.'">'.$label.'</option>';
1266
						}
1267
					}
1268
					else
1269
					{
1270
						array_push($outarray, array('key'=>$obj->rowid, 'value'=>$label, 'label'=>$label));
1271
					}
1272
1273
					$i++;
1274
					if (($i % 10) == 0) $out.="\n";
1275
				}
1276
			}
1277
			$out.= '</select>'."\n";
1278
		}
1279
		else
1280
		{
1281
			dol_print_error($this->db);
1282
		}
1283
1284
		$this->result=array('nbofthirdparties'=>$num);
1285
1286
		if ($outputmode) return $outarray;
1287
		return $out;
1288
	}
1289
1290
1291
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1292
	/**
1293
	 *  Return HTML combo list of absolute discounts
1294
	 *
1295
	 *  @param	string	$selected       Id remise fixe pre-selectionnee
1296
	 *  @param  string	$htmlname       Nom champ formulaire
1297
	 *  @param  string	$filter         Criteres optionnels de filtre
1298
	 *  @param	int		$socid			Id of thirdparty
1299
	 *  @param	int		$maxvalue		Max value for lines that can be selected
1300
	 *  @return	int						Return number of qualifed lines in list
1301
	 */
1302
    public function select_remises($selected, $htmlname, $filter, $socid, $maxvalue = 0)
1303
	{
1304
        // phpcs:enable
1305
		global $langs,$conf;
1306
1307
		// On recherche les remises
1308
		$sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
1309
		$sql.= " re.description, re.fk_facture_source";
1310
		$sql.= " FROM ".MAIN_DB_PREFIX ."societe_remise_except as re";
1311
		$sql.= " WHERE re.fk_soc = ".(int) $socid;
1312
		$sql.= " AND re.entity = " . $conf->entity;
1313
		if ($filter) $sql.= " AND ".$filter;
1314
		$sql.= " ORDER BY re.description ASC";
1315
1316
		dol_syslog(get_class($this)."::select_remises", LOG_DEBUG);
1317
		$resql=$this->db->query($sql);
1318
		if ($resql)
1319
		{
1320
			print '<select id="select_'.$htmlname.'" class="flat maxwidthonsmartphone" name="'.$htmlname.'">';
1321
			$num = $this->db->num_rows($resql);
1322
1323
			$qualifiedlines=$num;
1324
1325
			$i = 0;
1326
			if ($num)
1327
			{
1328
				print '<option value="0">&nbsp;</option>';
1329
				while ($i < $num)
1330
				{
1331
					$obj = $this->db->fetch_object($resql);
1332
					$desc=dol_trunc($obj->description, 40);
1333
					if (preg_match('/\(CREDIT_NOTE\)/', $desc)) $desc=preg_replace('/\(CREDIT_NOTE\)/', $langs->trans("CreditNote"), $desc);
1334
					if (preg_match('/\(DEPOSIT\)/', $desc)) $desc=preg_replace('/\(DEPOSIT\)/', $langs->trans("Deposit"), $desc);
1335
					if (preg_match('/\(EXCESS RECEIVED\)/', $desc)) $desc=preg_replace('/\(EXCESS RECEIVED\)/', $langs->trans("ExcessReceived"), $desc);
1336
					if (preg_match('/\(EXCESS PAID\)/', $desc)) $desc=preg_replace('/\(EXCESS PAID\)/', $langs->trans("ExcessPaid"), $desc);
1337
1338
					$selectstring='';
1339
					if ($selected > 0 && $selected == $obj->rowid) $selectstring=' selected';
1340
1341
					$disabled='';
1342
					if ($maxvalue > 0 && $obj->amount_ttc > $maxvalue)
1343
					{
1344
						$qualifiedlines--;
1345
						$disabled=' disabled';
1346
					}
1347
1348
					if (!empty($conf->global->MAIN_SHOW_FACNUMBER_IN_DISCOUNT_LIST) && !empty($obj->fk_facture_source))
1349
					{
1350
						$tmpfac = new Facture($this->db);
1351
						if ($tmpfac->fetch($obj->fk_facture_source) > 0) $desc=$desc.' - '.$tmpfac->ref;
1352
					}
1353
1354
					print '<option value="'.$obj->rowid.'"'.$selectstring.$disabled.'>'.$desc.' ('.price($obj->amount_ht).' '.$langs->trans("HT").' - '.price($obj->amount_ttc).' '.$langs->trans("TTC").')</option>';
1355
					$i++;
1356
				}
1357
			}
1358
			print '</select>';
1359
			return $qualifiedlines;
1360
		}
1361
		else
1362
		{
1363
			dol_print_error($this->db);
1364
			return -1;
1365
		}
1366
	}
1367
1368
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1369
	/**
1370
	 *  Return list of all contacts (for a third party or all)
1371
	 *
1372
	 *  @param	int		$socid      	Id ot third party or 0 for all
1373
	 *  @param  string	$selected   	Id contact pre-selectionne
1374
	 *  @param  string	$htmlname  	    Name of HTML field ('none' for a not editable field)
1375
	 *  @param  int		$showempty      0=no empty value, 1=add an empty value, 2=add line 'Internal' (used by user edit), 3=add an empty value only if more than one record into list
1376
	 *  @param  string	$exclude        List of contacts id to exclude
1377
	 *  @param	string	$limitto		Disable answers that are not id in this array list
1378
	 *  @param	integer	$showfunction   Add function into label
1379
	 *  @param	string	$moreclass		Add more class to class style
1380
	 *  @param	integer	$showsoc	    Add company into label
1381
	 *  @param	int		$forcecombo		Force to use combo box
1382
	 *  @param	array	$events			Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
1383
	 *  @param	bool	$options_only	Return options only (for ajax treatment)
1384
	 *  @param	string	$moreparam		Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
1385
	 *  @param	string	$htmlid			Html id to use instead of htmlname
1386
	 *  @return	int						<0 if KO, Nb of contact in list if OK
1387
	 *  @deprected						You can use selectcontacts directly (warning order of param was changed)
1388
	 */
1389
    public function select_contacts($socid, $selected = '', $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $moreclass = '', $showsoc = 0, $forcecombo = 0, $events = array(), $options_only = false, $moreparam = '', $htmlid = '')
1390
    {
1391
        // phpcs:enable
1392
		print $this->selectcontacts($socid, $selected, $htmlname, $showempty, $exclude, $limitto, $showfunction, $moreclass, $options_only, $showsoc, $forcecombo, $events, $moreparam, $htmlid);
1393
		return $this->num;
1394
    }
1395
1396
	/**
1397
	 *	Return HTML code of the SELECT of list of all contacts (for a third party or all).
1398
	 *  This also set the number of contacts found into $this->num
1399
	 *
1400
	 * @since 9.0 Add afterSelectContactOptions hook
1401
	 *
1402
	 *	@param	int			$socid      	Id ot third party or 0 for all or -1 for empty list
1403
	 *	@param  array|int	$selected   	Array of ID of pre-selected contact id
1404
	 *	@param  string		$htmlname  	    Name of HTML field ('none' for a not editable field)
1405
	 *	@param  int			$showempty     	0=no empty value, 1=add an empty value, 2=add line 'Internal' (used by user edit), 3=add an empty value only if more than one record into list
1406
	 *	@param  string		$exclude        List of contacts id to exclude
1407
	 *	@param	string		$limitto		Disable answers that are not id in this array list
1408
	 *	@param	integer		$showfunction   Add function into label
1409
	 *	@param	string		$moreclass		Add more class to class style
1410
	 *	@param	bool		$options_only	Return options only (for ajax treatment)
1411
	 *	@param	integer		$showsoc	    Add company into label
1412
	 * 	@param	int			$forcecombo		Force to use combo box (so no ajax beautify effect)
1413
	 *  @param	array		$events			Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
1414
	 *  @param	string		$moreparam		Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
1415
	 *  @param	string		$htmlid			Html id to use instead of htmlname
1416
	 *  @param	bool		$multiple		add [] in the name of element and add 'multiple' attribut
1417
	 *	@return	 int						<0 if KO, Nb of contact in list if OK
1418
	 */
1419
    public function selectcontacts($socid, $selected = '', $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $moreclass = '', $options_only = false, $showsoc = 0, $forcecombo = 0, $events = array(), $moreparam = '', $htmlid = '', $multiple = false)
1420
    {
1421
		global $conf,$langs,$hookmanager,$action;
1422
1423
		$langs->load('companies');
1424
1425
		if (empty($htmlid)) $htmlid = $htmlname;
1426
1427
		if ($selected === '') $selected = array();
1428
		elseif (!is_array($selected)) $selected = array($selected);
1429
		$out='';
1430
1431
		if (! is_object($hookmanager))
1432
		{
1433
			include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
1434
			$hookmanager=new HookManager($this->db);
1435
		}
1436
1437
		// We search third parties
1438
		$sql = "SELECT sp.rowid, sp.lastname, sp.statut, sp.firstname, sp.poste";
1439
		if ($showsoc > 0) $sql.= " , s.nom as company";
1440
		$sql.= " FROM ".MAIN_DB_PREFIX ."socpeople as sp";
1441
		if ($showsoc > 0) $sql.= " LEFT OUTER JOIN  ".MAIN_DB_PREFIX ."societe as s ON s.rowid=sp.fk_soc";
1442
		$sql.= " WHERE sp.entity IN (".getEntity('socpeople').")";
1443
		if ($socid > 0 || $socid == -1) $sql.= " AND sp.fk_soc=".$socid;
1444
		if (! empty($conf->global->CONTACT_HIDE_INACTIVE_IN_COMBOBOX)) $sql.= " AND sp.statut <> 0";
1445
		$sql.= " ORDER BY sp.lastname ASC";
1446
1447
		dol_syslog(get_class($this)."::select_contacts", LOG_DEBUG);
1448
		$resql=$this->db->query($sql);
1449
		if ($resql)
1450
		{
1451
			$num=$this->db->num_rows($resql);
1452
1453
			if ($conf->use_javascript_ajax && ! $forcecombo && ! $options_only)
1454
			{
1455
				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1456
				$out .= ajax_combobox($htmlid, $events, $conf->global->CONTACT_USE_SEARCH_TO_SELECT);
1457
			}
1458
1459
			if ($htmlname != 'none' && ! $options_only) $out.= '<select class="flat'.($moreclass?' '.$moreclass:'').'" id="'.$htmlid.'" name="'.$htmlname.($multiple ? '[]' : '').'" '.($multiple ? 'multiple' : '').' '.(!empty($moreparam) ? $moreparam : '').'>';
1460
			if (($showempty == 1 || ($showempty == 3 && $num > 1)) && !$multiple) $out.= '<option value="0"'.(in_array(0, $selected)?' selected':'').'>&nbsp;</option>';
1 ignored issue
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ($showempty == 1 || $sho...num > 1) && ! $multiple, Probably Intended Meaning: $showempty == 1 || ($sho...num > 1 && ! $multiple)
Loading history...
1461
			if ($showempty == 2) $out.= '<option value="0"'.(in_array(0, $selected)?' selected':'').'>'.$langs->trans("Internal").'</option>';
1462
1463
			$num = $this->db->num_rows($resql);
1464
			$i = 0;
1465
			if ($num)
1466
			{
1467
				include_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
1468
				$contactstatic=new Contact($this->db);
1469
1470
				while ($i < $num)
1471
				{
1472
					$obj = $this->db->fetch_object($resql);
1473
1474
					$contactstatic->id=$obj->rowid;
1475
					$contactstatic->lastname=$obj->lastname;
1476
					$contactstatic->firstname=$obj->firstname;
1477
					if ($obj->statut == 1) {
1478
					    if ($htmlname != 'none')
1479
					    {
1480
						    $disabled=0;
1481
						    if (is_array($exclude) && count($exclude) && in_array($obj->rowid, $exclude)) $disabled=1;
1482
						    if (is_array($limitto) && count($limitto) && ! in_array($obj->rowid, $limitto)) $disabled=1;
1483
						    if (!empty($selected) && in_array($obj->rowid, $selected))
1484
						    {
1485
							    $out.= '<option value="'.$obj->rowid.'"';
1486
							    if ($disabled) $out.= ' disabled';
1487
							    $out.= ' selected>';
1488
							    $out.= $contactstatic->getFullName($langs);
1489
							    if ($showfunction && $obj->poste) $out.= ' ('.$obj->poste.')';
1490
							    if (($showsoc > 0) && $obj->company) $out.= ' - ('.$obj->company.')';
1491
							    $out.= '</option>';
1492
						    }
1493
						    else
1494
						    {
1495
							    $out.= '<option value="'.$obj->rowid.'"';
1496
							    if ($disabled) $out.= ' disabled';
1497
							    $out.= '>';
1498
							    $out.= $contactstatic->getFullName($langs);
1499
							    if ($showfunction && $obj->poste) $out.= ' ('.$obj->poste.')';
1500
							    if (($showsoc > 0) && $obj->company) $out.= ' - ('.$obj->company.')';
1501
							    $out.= '</option>';
1502
						    }
1503
					    }
1504
					    else
1505
					    {
1506
						    if (in_array($obj->rowid, $selected))
1507
						    {
1508
							    $out.= $contactstatic->getFullName($langs);
1509
							    if ($showfunction && $obj->poste) $out.= ' ('.$obj->poste.')';
1510
							    if (($showsoc > 0) && $obj->company) $out.= ' - ('.$obj->company.')';
1511
						    }
1512
					    }
1513
				    }
1514
					$i++;
1515
				}
1516
			}
1517
			else
1518
			{
1519
				$out.= '<option value="-1"'.(($showempty==2 || $multiple) ? '' : ' selected').' disabled>';
1520
				$out.= ($socid != -1) ? ($langs->trans($socid?"NoContactDefinedForThirdParty":"NoContactDefined")) : $langs->trans('SelectAThirdPartyFirst');
1521
				$out.= '</option>';
1522
			}
1523
1524
			$parameters = array(
1525
				'socid'=>$socid,
1526
				'htmlname'=>$htmlname,
1527
				'resql'=>$resql,
1528
				'out'=>&$out,
1529
				'showfunction'=>$showfunction,
1530
				'showsoc'=>$showsoc,
1531
			);
1532
1533
			$reshook = $hookmanager->executeHooks('afterSelectContactOptions', $parameters, $this, $action);    // Note that $action and $object may have been modified by some hooks
1534
1535
			if ($htmlname != 'none' && ! $options_only)
1536
			{
1537
				$out.= '</select>';
1538
			}
1539
1540
			$this->num = $num;
1541
			return $out;
1542
		}
1543
		else
1544
		{
1545
			dol_print_error($this->db);
1546
			return -1;
1547
		}
1548
	}
1549
1550
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1551
	/**
1552
	 *	Return select list of users
1553
	 *
1554
	 *  @param	string	$selected       Id user preselected
1555
	 *  @param  string	$htmlname       Field name in form
1556
	 *  @param  int		$show_empty     0=liste sans valeur nulle, 1=ajoute valeur inconnue
1557
	 *  @param  array	$exclude        Array list of users id to exclude
1558
	 * 	@param	int		$disabled		If select list must be disabled
1559
	 *  @param  array	$include        Array list of users id to include
1560
	 * 	@param	int		$enableonly		Array list of users id to be enabled. All other must be disabled
1561
	 *  @param	string	$force_entity	'0' or Ids of environment to force
1562
	 * 	@return	void
1563
	 *  @deprecated		Use select_dolusers instead
1564
	 *  @see select_dolusers()
1565
	 */
1566
    public function select_users($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '0')
1567
	{
1568
        // phpcs:enable
1569
		print $this->select_dolusers($selected, $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity);
1570
	}
1571
1572
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1573
	/**
1574
	 *	Return select list of users
1575
	 *
1576
	 *  @param	string	$selected       User id or user object of user preselected. If 0 or < -2, we use id of current user. If -1, keep unselected (if empty is allowed)
1577
	 *  @param  string	$htmlname       Field name in form
1578
	 *  @param  int		$show_empty     0=list with no empty value, 1=add also an empty value into list
1579
	 *  @param  array	$exclude        Array list of users id to exclude
1580
	 * 	@param	int		$disabled		If select list must be disabled
1581
	 *  @param  array|string	$include        Array list of users id to include or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me
1582
	 * 	@param	array	$enableonly		Array list of users id to be enabled. If defined, it means that others will be disabled
1583
	 *  @param	string	$force_entity	'0' or Ids of environment to force
1584
	 *  @param	int		$maxlength		Maximum length of string into list (0=no limit)
1585
	 *  @param	int		$showstatus		0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status
1586
	 *  @param	string	$morefilter		Add more filters into sql request (Example: 'employee = 1')
1587
	 *  @param	integer	$show_every		0=default list, 1=add also a value "Everybody" at beginning of list
1588
	 *  @param	string	$enableonlytext	If option $enableonlytext is set, we use this text to explain into label why record is disabled. Not used if enableonly is empty.
1589
	 *  @param	string	$morecss		More css
1590
	 *  @param  int     $noactive       Show only active users (this will also happened whatever is this option if USER_HIDE_INACTIVE_IN_COMBOBOX is on).
1591
	 *  @param  int		$outputmode     0=HTML select string, 1=Array
1592
	 *  @param  bool	$multiple       add [] in the name of element and add 'multiple' attribut
1593
	 * 	@return	string					HTML select string
1594
	 *  @see select_dolgroups()
1595
	 */
1596
    public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $show_every = 0, $enableonlytext = '', $morecss = '', $noactive = 0, $outputmode = 0, $multiple = false)
1597
	{
1598
        // phpcs:enable
1599
		global $conf,$user,$langs;
1600
1601
		// If no preselected user defined, we take current user
1602
		if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && empty($conf->global->SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE)) $selected=$user->id;
1603
1604
		if ($selected === '') $selected = array();
1605
		elseif (!is_array($selected)) $selected = array($selected);
1606
1607
		$excludeUsers=null;
1608
		$includeUsers=null;
1609
1610
		// Permettre l'exclusion d'utilisateurs
1611
		if (is_array($exclude))	$excludeUsers = implode(",", $exclude);
1612
		// Permettre l'inclusion d'utilisateurs
1613
		if (is_array($include))	$includeUsers = implode(",", $include);
1614
		elseif ($include == 'hierarchy')
1615
		{
1616
			// Build list includeUsers to have only hierarchy
1617
			$includeUsers = implode(",", $user->getAllChildIds(0));
1618
		}
1619
		elseif ($include == 'hierarchyme')
1620
		{
1621
			// Build list includeUsers to have only hierarchy and current user
1622
			$includeUsers = implode(",", $user->getAllChildIds(1));
1623
		}
1624
1625
		$out='';
1626
		$outarray = array();
1627
1628
		// Forge request to select users
1629
		$sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut, u.login, u.admin, u.entity";
1630
		if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
1631
		{
1632
			$sql.= ", e.label";
1633
		}
1634
		$sql.= " FROM ".MAIN_DB_PREFIX ."user as u";
1635
		if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
1636
		{
1637
			$sql.= " LEFT JOIN ".MAIN_DB_PREFIX ."entity as e ON e.rowid=u.entity";
1638
			if ($force_entity) $sql.= " WHERE u.entity IN (0,".$force_entity.")";
1639
			else $sql.= " WHERE u.entity IS NOT NULL";
1640
		}
1641
		else
1642
		{
1643
			if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))
1644
			{
1645
				$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."usergroup_user as ug";
1646
				$sql.= " ON ug.fk_user = u.rowid";
1647
				$sql.= " WHERE ug.entity = ".$conf->entity;
1648
			}
1649
			else
1650
			{
1651
				$sql.= " WHERE u.entity IN (0,".$conf->entity.")";
1652
			}
1653
		}
1654
		if (! empty($user->societe_id)) $sql.= " AND u.fk_soc = ".$user->societe_id;
1655
		if (is_array($exclude) && $excludeUsers) $sql.= " AND u.rowid NOT IN (".$excludeUsers.")";
1656
		if ($includeUsers) $sql.= " AND u.rowid IN (".$includeUsers.")";
1657
		if (! empty($conf->global->USER_HIDE_INACTIVE_IN_COMBOBOX) || $noactive) $sql.= " AND u.statut <> 0";
1658
		if (! empty($morefilter)) $sql.=" ".$morefilter;
1659
1660
		if (empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION))	// MAIN_FIRSTNAME_NAME_POSITION is 0 means firstname+lastname
1661
		{
1662
			$sql.= " ORDER BY u.firstname ASC";
1663
		}
1664
		else
1665
		{
1666
			$sql.= " ORDER BY u.lastname ASC";
1667
		}
1668
1669
		dol_syslog(get_class($this)."::select_dolusers", LOG_DEBUG);
1670
		$resql=$this->db->query($sql);
1671
		if ($resql)
1672
		{
1673
			$num = $this->db->num_rows($resql);
1674
			$i = 0;
1675
			if ($num)
1676
			{
1677
		   		// Enhance with select2
1678
				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1679
				$out .= ajax_combobox($htmlname);
1680
1681
				// do not use maxwidthonsmartphone by default. Set it by caller so auto size to 100% will work when not defined
1682
				$out.= '<select class="flat'.($morecss?' minwidth100imp '.$morecss:' minwidth200').'" id="'.$htmlname.'" name="'.$htmlname.($multiple ? '[]' : '').'" '.($multiple ? 'multiple' : '').' '.($disabled?' disabled':'').'>';
1683
				if ($show_empty && !$multiple) $out.= '<option value="-1"'.((empty($selected) || in_array(-1, $selected))?' selected':'').'>&nbsp;</option>'."\n";
1684
				if ($show_every) $out.= '<option value="-2"'.((in_array(-2, $selected))?' selected':'').'>-- '.$langs->trans("Everybody").' --</option>'."\n";
1685
1686
				$userstatic=new User($this->db);
1687
1688
				while ($i < $num)
1689
				{
1690
					$obj = $this->db->fetch_object($resql);
1691
1692
					$userstatic->id=$obj->rowid;
1693
					$userstatic->lastname=$obj->lastname;
1694
					$userstatic->firstname=$obj->firstname;
1695
1696
					$disableline='';
1697
					if (is_array($enableonly) && count($enableonly) && ! in_array($obj->rowid, $enableonly)) $disableline=($enableonlytext?$enableonlytext:'1');
1698
1699
					if ((is_object($selected) && $selected->id == $obj->rowid) || (! is_object($selected) && in_array($obj->rowid, $selected) ))
1700
					{
1701
						$out.= '<option value="'.$obj->rowid.'"';
1702
						if ($disableline) $out.= ' disabled';
1703
						$out.= ' selected>';
1704
					}
1705
					else
1706
					{
1707
						$out.= '<option value="'.$obj->rowid.'"';
1708
						if ($disableline) $out.= ' disabled';
1709
						$out.= '>';
1710
					}
1711
1712
					// $fullNameMode is 0=Lastname+Firstname (MAIN_FIRSTNAME_NAME_POSITION=1), 1=Firstname+Lastname (MAIN_FIRSTNAME_NAME_POSITION=0)
1713
					$fullNameMode = 0;
1714
					if (empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION))
1715
					{
1716
						$fullNameMode = 1; //Firstname+lastname
1717
					}
1718
					$out.= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
1719
1720
					// Complete name with more info
1721
					$moreinfo=0;
1722
					if (! empty($conf->global->MAIN_SHOW_LOGIN))
1723
					{
1724
						$out.= ($moreinfo?' - ':' (').$obj->login;
1725
						$moreinfo++;
1726
					}
1727
					if ($showstatus >= 0)
1728
					{
1729
						if ($obj->statut == 1 && $showstatus == 1)
1730
						{
1731
							$out.=($moreinfo?' - ':' (').$langs->trans('Enabled');
1732
							$moreinfo++;
1733
						}
1734
						if ($obj->statut == 0)
1735
						{
1736
							$out.=($moreinfo?' - ':' (').$langs->trans('Disabled');
1737
							$moreinfo++;
1738
						}
1739
					}
1740
					if (! empty($conf->multicompany->enabled) && empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $conf->entity == 1 && $user->admin && ! $user->entity)
1741
					{
1742
						if (! $obj->entity)
1743
						{
1744
							$out.=($moreinfo?' - ':' (').$langs->trans("AllEntities");
1745
							$moreinfo++;
1746
						}
1747
						else
1748
						{
1749
							$out.=($moreinfo?' - ':' (').($obj->label?$obj->label:$langs->trans("EntityNameNotDefined"));
1750
							$moreinfo++;
1751
					 	}
1752
					}
1753
					$out.=($moreinfo?')':'');
1754
					if ($disableline && $disableline != '1')
1755
					{
1756
						$out.=' - '.$disableline;	// This is text from $enableonlytext parameter
1757
					}
1758
					$out.= '</option>';
1759
					$outarray[$userstatic->id] = $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
1760
1761
					$i++;
1762
				}
1763
			}
1764
			else
1765
			{
1766
				$out.= '<select class="flat" id="'.$htmlname.'" name="'.$htmlname.'" disabled>';
1767
				$out.= '<option value="">'.$langs->trans("None").'</option>';
1768
			}
1769
			$out.= '</select>';
1770
		}
1771
		else
1772
		{
1773
			dol_print_error($this->db);
1774
		}
1775
1776
		if ($outputmode) return $outarray;
1777
		return $out;
1778
	}
1779
1780
1781
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1782
	/**
1783
	 *	Return select list of users. Selected users are stored into session.
1784
	 *  List of users are provided into $_SESSION['assignedtouser'].
1785
	 *
1786
	 *  @param  string	$action         Value for $action
1787
	 *  @param  string	$htmlname       Field name in form
1788
	 *  @param  int		$show_empty     0=list without the empty value, 1=add empty value
1789
	 *  @param  array	$exclude        Array list of users id to exclude
1790
	 * 	@param	int		$disabled		If select list must be disabled
1791
	 *  @param  array	$include        Array list of users id to include or 'hierarchy' to have only supervised users
1792
	 * 	@param	array	$enableonly		Array list of users id to be enabled. All other must be disabled
1793
	 *  @param	int		$force_entity	'0' or Ids of environment to force
1794
	 *  @param	int		$maxlength		Maximum length of string into list (0=no limit)
1795
	 *  @param	int		$showstatus		0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status
1796
	 *  @param	string	$morefilter		Add more filters into sql request
1797
	 *  @param	int		$showproperties		Show properties of each attendees
1798
	 *  @param	array	$listofuserid		Array with properties of each user
1799
	 *  @param	array	$listofcontactid	Array with properties of each contact
1800
	 *  @param	array	$listofotherid		Array with properties of each other contact
1801
	 * 	@return	string					HTML select string
1802
	 *  @see select_dolgroups()
1803
	 */
1804
    public function select_dolusers_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofuserid = array(), $listofcontactid = array(), $listofotherid = array())
1805
	{
1806
        // phpcs:enable
1807
		global $conf, $user, $langs;
1808
1809
		$userstatic=new User($this->db);
1810
		$out='';
1811
1812
		// Method with no ajax
1813
		//$out.='<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
1814
		if ($action == 'view')
1815
		{
1816
			$out.='';
1817
		}
1818
		else
1819
		{
1820
			$out.='<input type="hidden" class="removedassignedhidden" name="removedassigned" value="">';
1821
			$out.='<script type="text/javascript" language="javascript">jQuery(document).ready(function () {    jQuery(".removedassigned").click(function() {        jQuery(".removedassignedhidden").val(jQuery(this).val());    });})</script>';
1822
			$out.=$this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
1823
			$out.=' <input type="submit" class="button valignmiddle" name="'.$action.'assignedtouser" value="'.dol_escape_htmltag($langs->trans("Add")).'">';
1824
			$out.='<br>';
1825
		}
1826
		$assignedtouser=array();
1827
		if (!empty($_SESSION['assignedtouser']))
1828
		{
1829
			$assignedtouser=json_decode($_SESSION['assignedtouser'], true);
1830
		}
1831
		$nbassignetouser=count($assignedtouser);
1832
1833
		if ($nbassignetouser && $action != 'view') $out.='<br>';
1834
		if ($nbassignetouser) $out.='<ul class="attendees">';
1835
		$i=0; $ownerid=0;
1836
		foreach($assignedtouser as $key => $value)
1837
		{
1838
			if ($value['id'] == $ownerid) continue;
1839
1840
			$out.='<li>';
1841
			$userstatic->fetch($value['id']);
1842
			$out.= $userstatic->getNomUrl(-1);
1843
			if ($i == 0) { $ownerid = $value['id']; $out.=' ('.$langs->trans("Owner").')'; }
1844
			if ($nbassignetouser > 1 && $action != 'view')
1845
			{
1846
				$out.=' <input type="image" style="border: 0px;" src="'.img_picto($langs->trans("Remove"), 'delete', '', 0, 1).'" value="'.$userstatic->id.'" class="removedassigned" id="removedassigned_'.$userstatic->id.'" name="removedassigned_'.$userstatic->id.'">';
1847
			}
1848
			// Show my availability
1849
			if ($showproperties)
1850
			{
1851
				if ($ownerid == $value['id'] && is_array($listofuserid) && count($listofuserid) && in_array($ownerid, array_keys($listofuserid)))
1852
				{
1853
					$out.='<div class="myavailability inline-block">';
1854
					$out.='&nbsp;-&nbsp;<span class="opacitymedium">'.$langs->trans("Availability").':</span>  <input id="transparency" class="marginleftonly marginrightonly" '.($action == 'view'?'disabled':'').' type="checkbox" name="transparency"'.($listofuserid[$ownerid]['transparency']?' checked':'').'>'.$langs->trans("Busy");
1855
					$out.='</div>';
1856
				}
1857
			}
1858
			//$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
1859
			//$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
1860
1861
			$out.='</li>';
1862
			$i++;
1863
		}
1864
		if ($nbassignetouser) $out.='</ul>';
1865
1866
		//$out.='</form>';
1867
		return $out;
1868
	}
1869
1870
1871
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1872
	/**
1873
	 *  Return list of products for customer in Ajax if Ajax activated or go to select_produits_list
1874
	 *
1875
	 *  @param		int			$selected				Preselected products
1876
	 *  @param		string		$htmlname				Name of HTML select field (must be unique in page)
1877
	 *  @param		int			$filtertype				Filter on product type (''=nofilter, 0=product, 1=service)
1878
	 *  @param		int			$limit					Limit on number of returned lines
1879
	 *  @param		int			$price_level			Level of price to show
1880
	 *  @param		int			$status					Sell status -1=Return all products, 0=Products not on sell, 1=Products on sell
1881
	 *  @param		int			$finished				2=all, 1=finished, 0=raw material
1882
	 *  @param		string		$selected_input_value	Value of preselected input text (for use with ajax)
1883
	 *  @param		int			$hidelabel				Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after)
1884
	 *  @param		array		$ajaxoptions			Options for ajax_autocompleter
1885
	 *  @param      int			$socid					Thirdparty Id (to get also price dedicated to this customer)
1886
	 *  @param		string		$showempty				'' to not show empty line. Translation key to show an empty line. '1' show empty line with no text.
1887
	 * 	@param		int			$forcecombo				Force to use combo box
1888
	 *  @param      string      $morecss                Add more css on select
1889
	 *  @param      int         $hidepriceinlabel       1=Hide prices in label
1890
	 *  @param      string      $warehouseStatus        warehouse status filter, following comma separated filter options can be used
1891
	 *										            'warehouseopen' = select products from open warehouses,
1892
	 *										            'warehouseclosed' = select products from closed warehouses,
1893
	 *										            'warehouseinternal' = select products from warehouses for internal correct/transfer only
1894
	 *  @param 		array 		$selected_combinations 	Selected combinations. Format: array([attrid] => attrval, [...])
1895
	 *  @return		void
1896
	 */
1897
    public function select_produits($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $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 = array())
1898
	{
1899
        // phpcs:enable
1900
		global $langs,$conf;
1901
1902
		// check parameters
1903
		$price_level = (! empty($price_level) ? $price_level : 0);
1904
		if (is_null($ajaxoptions)) $ajaxoptions=array();
0 ignored issues
show
introduced by
The condition is_null($ajaxoptions) is always false.
Loading history...
1905
1906
		if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT))
1907
		{
1908
			$placeholder='';
1909
1910
			if ($selected && empty($selected_input_value))
1911
			{
1912
				require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1913
				$producttmpselect = new Product($this->db);
1914
				$producttmpselect->fetch($selected);
1915
				$selected_input_value=$producttmpselect->ref;
1916
				unset($producttmpselect);
1917
			}
1918
			// handle case where product or service module is disabled + no filter specified
1919
			if ($filtertype == '')
1920
			{
1921
				if (empty($conf->product->enabled)) { // when product module is disabled, show services only
1922
					$filtertype = 1;
1923
				}
1924
				elseif (empty($conf->service->enabled)) { // when service module is disabled, show products only
1925
					$filtertype = 0;
1926
				}
1927
			}
1928
			// mode=1 means customers products
1929
			$urloption='htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&finished='.$finished.'&hidepriceinlabel='.$hidepriceinlabel.'&warehousestatus='.$warehouseStatus;
1930
			//Price by customer
1931
			if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
1932
				$urloption.='&socid='.$socid;
1933
			}
1934
			print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
1935
1936
			if (!empty($conf->variants->enabled)) {
1937
				?>
1938
				<script>
1939
1940
					selected = <?php echo json_encode($selected_combinations) ?>;
1941
					combvalues = {};
1942
1943
					jQuery(document).ready(function () {
1944
1945
						jQuery("input[name='prod_entry_mode']").change(function () {
1946
							if (jQuery(this).val() == 'free') {
1947
								jQuery('div#attributes_box').empty();
1948
							}
1949
						});
1950
1951
						jQuery("input#<?php echo $htmlname ?>").change(function () {
1952
1953
							if (!jQuery(this).val()) {
1954
								jQuery('div#attributes_box').empty();
1955
								return;
1956
							}
1957
1958
							jQuery.getJSON("<?php echo dol_buildpath('/variants/ajax/getCombinations.php', 2) ?>", {
1959
								id: jQuery(this).val()
1960
							}, function (data) {
1961
								jQuery('div#attributes_box').empty();
1962
1963
								jQuery.each(data, function (key, val) {
1964
1965
									combvalues[val.id] = val.values;
1966
1967
									var span = jQuery(document.createElement('div')).css({
1968
										'display': 'table-row'
1969
									});
1970
1971
									span.append(
1972
										jQuery(document.createElement('div')).text(val.label).css({
1973
											'font-weight': 'bold',
1974
											'display': 'table-cell',
1975
											'text-align': 'right'
1976
										})
1977
									);
1978
1979
									var html = jQuery(document.createElement('select')).attr('name', 'combinations[' + val.id + ']').css({
1980
										'margin-left': '15px',
1981
										'white-space': 'pre'
1982
									}).append(
1983
										jQuery(document.createElement('option')).val('')
1984
									);
1985
1986
									jQuery.each(combvalues[val.id], function (key, val) {
1987
										var tag = jQuery(document.createElement('option')).val(val.id).html(val.value);
1988
1989
										if (selected[val.fk_product_attribute] == val.id) {
1990
											tag.attr('selected', 'selected');
1991
										}
1992
1993
										html.append(tag);
1994
									});
1995
1996
									span.append(html);
1997
									jQuery('div#attributes_box').append(span);
1998
								});
1999
							})
2000
						});
2001
2002
						<?php if ($selected): ?>
2003
						jQuery("input#<?php echo $htmlname ?>").change();
2004
						<?php endif ?>
2005
					});
2006
				</script>
2007
                <?php
2008
			}
2009
			if (empty($hidelabel)) print $langs->trans("RefOrLabel").' : ';
2010
			elseif ($hidelabel > 1) {
2011
				$placeholder=' placeholder="'.$langs->trans("RefOrLabel").'"';
2012
				if ($hidelabel == 2) {
2013
					print img_picto($langs->trans("Search"), 'search');
2014
				}
2015
			}
2016
			print '<input type="text" class="minwidth100" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' '.(!empty($conf->global->PRODUCT_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />';
2017
			if ($hidelabel == 3) {
2018
				print img_picto($langs->trans("Search"), 'search');
2019
			}
2020
		}
2021
		else
2022
		{
2023
			print $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus);
0 ignored issues
show
Bug introduced by
Are you sure $this->select_produits_l...abel, $warehouseStatus) of type array can be used in print()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2023
			print /** @scrutinizer ignore-type */ $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus);
Loading history...
2024
		}
2025
	}
2026
2027
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2028
	/**
2029
	 *	Return list of products for a customer
2030
	 *
2031
	 *	@param      int		$selected           Preselected product
2032
	 *	@param      string	$htmlname           Name of select html
2033
	 *  @param		string	$filtertype         Filter on product type (''=nofilter, 0=product, 1=service)
2034
	 *	@param      int		$limit              Limit on number of returned lines
2035
	 *	@param      int		$price_level        Level of price to show
2036
	 * 	@param      string	$filterkey          Filter on product
2037
	 *	@param		int		$status             -1=Return all products, 0=Products not on sell, 1=Products on sell
2038
	 *  @param      int		$finished           Filter on finished field: 2=No filter
2039
	 *  @param      int		$outputmode         0=HTML select string, 1=Array
2040
	 *  @param      int		$socid     		    Thirdparty Id (to get also price dedicated to this customer)
2041
	 *  @param		string	$showempty		    '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text.
2042
	 * 	@param		int		$forcecombo		    Force to use combo box
2043
	 *  @param      string  $morecss            Add more css on select
2044
	 *  @param      int     $hidepriceinlabel   1=Hide prices in label
2045
	 *  @param      string  $warehouseStatus    warehouse status filter, following comma separated filter options can be used
2046
	 *										    'warehouseopen' = select products from open warehouses,
2047
	 *										    'warehouseclosed' = select products from closed warehouses,
2048
	 *										    'warehouseinternal' = select products from warehouses for internal correct/transfer only
2049
	 *  @return     array    				    Array of keys for json
2050
	 */
2051
    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 = '')
2052
	{
2053
        // phpcs:enable
2054
		global $langs,$conf,$user,$db;
2055
2056
		$out='';
2057
		$outarray=array();
2058
2059
		$warehouseStatusArray = array();
2060
		if (! empty($warehouseStatus))
2061
		{
2062
			require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
2063
			if (preg_match('/warehouseclosed/', $warehouseStatus))
2064
			{
2065
				$warehouseStatusArray[] = Entrepot::STATUS_CLOSED;
2066
			}
2067
			if (preg_match('/warehouseopen/', $warehouseStatus))
2068
			{
2069
				$warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL;
2070
			}
2071
			if (preg_match('/warehouseinternal/', $warehouseStatus))
2072
			{
2073
				$warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL;
2074
			}
2075
		}
2076
2077
		$selectFields = " p.rowid, p.label, p.ref, p.description, p.barcode, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.duration, p.fk_price_expression";
2078
		(count($warehouseStatusArray)) ? $selectFieldsGrouped = ", sum(ps.reel) as stock" : $selectFieldsGrouped = ", p.stock";
2079
2080
		$sql = "SELECT ";
2081
		$sql.= $selectFields . $selectFieldsGrouped;
2082
2083
		if (! empty($conf->global->PRODUCT_SORT_BY_CATEGORY))
2084
		{
2085
			//Product category
2086
			$sql.= ", (SELECT ".MAIN_DB_PREFIX."categorie_product.fk_categorie
2087
						FROM ".MAIN_DB_PREFIX."categorie_product
2088
						WHERE ".MAIN_DB_PREFIX."categorie_product.fk_product=p.rowid
2089
						LIMIT 1
2090
				) AS categorie_product_id ";
2091
		}
2092
2093
		//Price by customer
2094
		if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid))
2095
		{
2096
			$sql.=', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
2097
			$sql.=' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx';
2098
			$selectFields.= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx";
2099
		}
2100
        // Units
2101
        if (! empty($conf->global->PRODUCT_USE_UNITS)) {
2102
            $sql .= ', u.label as unit_long, u.short_label as unit_short';
2103
            $selectFields .= ', unit_long, unit_short';
2104
        }
2105
2106
		// Multilang : we add translation
2107
		if (! empty($conf->global->MAIN_MULTILANGS))
2108
		{
2109
			$sql.= ", pl.label as label_translated";
2110
			$selectFields.= ", label_translated";
2111
		}
2112
		// Price by quantity
2113
		if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES))
2114
		{
2115
			$sql.= ", (SELECT pp.rowid FROM ".MAIN_DB_PREFIX."product_price as pp WHERE pp.fk_product = p.rowid";
2116
			if ($price_level >= 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) $sql.= " AND price_level=".$price_level;
2117
			$sql.= " ORDER BY date_price";
2118
			$sql.= " DESC LIMIT 1) as price_rowid";
2119
			$sql.= ", (SELECT pp.price_by_qty FROM ".MAIN_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
2120
			if ($price_level >= 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) $sql.= " AND price_level=".$price_level;
2121
			$sql.= " ORDER BY date_price";
2122
			$sql.= " DESC LIMIT 1) as price_by_qty";
2123
			$selectFields.= ", price_rowid, price_by_qty";
2124
		}
2125
		$sql.= " FROM ".MAIN_DB_PREFIX."product as p";
2126
		if (count($warehouseStatusArray))
2127
		{
2128
			$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps on ps.fk_product = p.rowid";
2129
			$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e on ps.fk_entrepot = e.rowid";
2130
		}
2131
2132
		// include search in supplier ref
2133
		if(!empty($conf->global->MAIN_SEARCH_PRODUCT_BY_FOURN_REF))
2134
		{
2135
            $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
2136
		}
2137
2138
		//Price by customer
2139
		if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
2140
			$sql.=" LEFT JOIN  ".MAIN_DB_PREFIX."product_customer_price as pcp ON pcp.fk_soc=".$socid." AND pcp.fk_product=p.rowid";
2141
		}
2142
        // Units
2143
        if (! empty($conf->global->PRODUCT_USE_UNITS)) {
2144
            $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_units u ON u.rowid = p.fk_unit";
2145
        }
2146
		// Multilang : we add translation
2147
		if (! empty($conf->global->MAIN_MULTILANGS))
2148
		{
2149
			$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND pl.lang='". $langs->getDefaultLang() ."'";
2150
		}
2151
2152
		if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) {
2153
			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination pac ON pac.fk_product_child = p.rowid";
2154
		}
2155
2156
		$sql.= ' WHERE p.entity IN ('.getEntity('product').')';
2157
		if (count($warehouseStatusArray))
2158
		{
2159
			$sql.= ' AND (p.fk_product_type = 1 OR e.statut IN ('.$this->db->escape(implode(',', $warehouseStatusArray)).'))';
2160
		}
2161
2162
		if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) {
2163
			$sql .= " AND pac.rowid IS NULL";
2164
		}
2165
2166
		if ($finished == 0)
2167
		{
2168
			$sql.= " AND p.finished = ".$finished;
2169
		}
2170
		elseif ($finished == 1)
2171
		{
2172
			$sql.= " AND p.finished = ".$finished;
2173
			if ($status >= 0)  $sql.= " AND p.tosell = ".$status;
2174
		}
2175
		elseif ($status >= 0)
2176
		{
2177
			$sql.= " AND p.tosell = ".$status;
2178
		}
2179
		// Filter by product type
2180
		if (strval($filtertype) != '') $sql.= " AND p.fk_product_type = ".$filtertype;
2181
		elseif (empty($conf->product->enabled)) { // when product module is disabled, show services only
2182
			$sql.= " AND p.fk_product_type = 1";
2183
		}
2184
		elseif (empty($conf->service->enabled)) { // when service module is disabled, show products only
2185
			$sql.= " AND p.fk_product_type = 0";
2186
		}
2187
		// Add criteria on ref/label
2188
		if ($filterkey != '')
2189
		{
2190
			$sql.=' AND (';
2191
			$prefix=empty($conf->global->PRODUCT_DONOTSEARCH_ANYWHERE)?'%':'';	// Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
2192
			// For natural search
2193
			$scrit = explode(' ', $filterkey);
2194
			$i=0;
2195
			if (count($scrit) > 1) $sql.="(";
2196
			foreach ($scrit as $crit)
2197
			{
2198
				if ($i > 0) $sql.=" AND ";
2199
				$sql.="(p.ref LIKE '".$db->escape($prefix.$crit)."%' OR p.label LIKE '".$db->escape($prefix.$crit)."%'";
2200
				if (! empty($conf->global->MAIN_MULTILANGS)) $sql.=" OR pl.label LIKE '".$db->escape($prefix.$crit)."%'";
2201
				if (!empty($conf->global->PRODUCT_AJAX_SEARCH_ON_DESCRIPTION))
2202
				{
2203
					$sql.=" OR p.description LIKE '".$db->escape($prefix.$crit)."%'";
2204
					if (! empty($conf->global->MAIN_MULTILANGS)) $sql.=" OR pl.description LIKE '".$db->escape($prefix.$crit)."%'";
2205
				}
2206
				if (! empty($conf->global->MAIN_SEARCH_PRODUCT_BY_FOURN_REF)) $sql.=" OR pfp.ref_fourn LIKE '".$db->escape($prefix.$crit)."%'";
2207
				$sql.=")";
2208
				$i++;
2209
			}
2210
			if (count($scrit) > 1) $sql.=")";
2211
		  	if (! empty($conf->barcode->enabled)) $sql.= " OR p.barcode LIKE '".$db->escape($prefix.$filterkey)."%'";
2212
			$sql.=')';
2213
		}
2214
		if (count($warehouseStatusArray))
2215
		{
2216
			$sql.= ' GROUP BY'.$selectFields;
2217
		}
2218
2219
		//Sort by category
2220
		if(! empty($conf->global->PRODUCT_SORT_BY_CATEGORY))
2221
		{
2222
			$sql .= " ORDER BY categorie_product_id ";
2223
			//ASC OR DESC order
2224
			($conf->global->PRODUCT_SORT_BY_CATEGORY == 1) ? $sql .="ASC" : $sql .="DESC";
2225
		}
2226
		else
2227
		{
2228
			$sql.= $db->order("p.ref");
2229
		}
2230
2231
		$sql.= $db->plimit($limit, 0);
2232
2233
		// Build output string
2234
		dol_syslog(get_class($this)."::select_produits_list search product", LOG_DEBUG);
2235
		$result=$this->db->query($sql);
2236
		if ($result)
2237
		{
2238
			require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
2239
			require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
2240
			$num = $this->db->num_rows($result);
2241
2242
			$events=null;
2243
2244
			if (! $forcecombo)
2245
			{
2246
				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2247
				$out .= ajax_combobox($htmlname, $events, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT);
2248
			}
2249
2250
			$out.='<select class="flat'.($morecss?' '.$morecss:'').'" name="'.$htmlname.'" id="'.$htmlname.'">';
2251
2252
			$textifempty='';
2253
			// Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
2254
			//if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
2255
			if (! empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT))
2256
			{
2257
				if ($showempty && ! is_numeric($showempty)) $textifempty=$langs->trans($showempty);
2258
				else $textifempty.=$langs->trans("All");
2259
			}
2260
			else
2261
			{
2262
			    if ($showempty && ! is_numeric($showempty)) $textifempty=$langs->trans($showempty);
2263
			}
2264
			if ($showempty) $out.='<option value="0" selected>'.$textifempty.'</option>';
2265
2266
			$i = 0;
2267
			while ($num && $i < $num)
2268
			{
2269
				$opt = '';
2270
				$optJson = array();
2271
				$objp = $this->db->fetch_object($result);
2272
2273
				if ((!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) && !empty($objp->price_by_qty) && $objp->price_by_qty == 1)
2274
				{ // Price by quantity will return many prices for the same product
2275
					$sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type";
2276
					$sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty";
2277
					$sql.= " WHERE fk_product_price=".$objp->price_rowid;
2278
					$sql.= " ORDER BY quantity ASC";
2279
2280
					dol_syslog(get_class($this)."::select_produits_list search price by qty", LOG_DEBUG);
2281
					$result2 = $this->db->query($sql);
2282
					if ($result2)
2283
					{
2284
						$nb_prices = $this->db->num_rows($result2);
2285
						$j = 0;
2286
						while ($nb_prices && $j < $nb_prices) {
2287
							$objp2 = $this->db->fetch_object($result2);
2288
2289
							$objp->price_by_qty_rowid = $objp2->rowid;
2290
							$objp->price_by_qty_price_base_type = $objp2->price_base_type;
2291
							$objp->price_by_qty_quantity = $objp2->quantity;
2292
							$objp->price_by_qty_unitprice = $objp2->unitprice;
2293
							$objp->price_by_qty_remise_percent = $objp2->remise_percent;
2294
							// For backward compatibility
2295
							$objp->quantity = $objp2->quantity;
2296
							$objp->price = $objp2->price;
2297
							$objp->unitprice = $objp2->unitprice;
2298
							$objp->remise_percent = $objp2->remise_percent;
2299
							$objp->remise = $objp2->remise;
2300
2301
							$this->constructProductListOption($objp, $opt, $optJson, 0, $selected, $hidepriceinlabel, $filterkey);
2302
2303
							$j++;
2304
2305
							// Add new entry
2306
							// "key" value of json key array is used by jQuery automatically as selected value
2307
							// "label" value of json key array is used by jQuery automatically as text for combo box
2308
							$out.=$opt;
2309
							array_push($outarray, $optJson);
2310
						}
2311
					}
2312
				}
2313
				else
2314
				{
2315
					if (!empty($conf->dynamicprices->enabled) && !empty($objp->fk_price_expression)) {
2316
						$price_product = new Product($this->db);
2317
						$price_product->fetch($objp->rowid, '', '', 1);
2318
						$priceparser = new PriceParser($this->db);
2319
						$price_result = $priceparser->parseProduct($price_product);
2320
						if ($price_result >= 0) {
2321
							$objp->price = $price_result;
2322
							$objp->unitprice = $price_result;
2323
							//Calculate the VAT
2324
							$objp->price_ttc = price2num($objp->price) * (1 + ($objp->tva_tx / 100));
2325
							$objp->price_ttc = price2num($objp->price_ttc, 'MU');
2326
						}
2327
					}
2328
					$this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected, $hidepriceinlabel, $filterkey);
2329
					// Add new entry
2330
					// "key" value of json key array is used by jQuery automatically as selected value
2331
					// "label" value of json key array is used by jQuery automatically as text for combo box
2332
					$out.=$opt;
2333
					array_push($outarray, $optJson);
2334
				}
2335
2336
				$i++;
2337
			}
2338
2339
			$out.='</select>';
2340
2341
			$this->db->free($result);
2342
2343
			if (empty($outputmode)) return $out;
2344
			return $outarray;
2345
		}
2346
		else
2347
		{
2348
			dol_print_error($db);
2349
		}
2350
	}
2351
2352
	/**
2353
	 * constructProductListOption.
2354
	 * This define value for &$opt and &$optJson.
2355
	 *
2356
	 * @param 	resource	$objp			    Resultset of fetch
2357
	 * @param 	string		$opt			    Option (var used for returned value in string option format)
2358
	 * @param 	string		$optJson		    Option (var used for returned value in json format)
2359
	 * @param 	int			$price_level	    Price level
2360
	 * @param 	string		$selected		    Preselected value
2361
	 * @param   int         $hidepriceinlabel   Hide price in label
2362
	 * @param   string      $filterkey          Filter key to highlight
2363
	 * @return	void
2364
	 */
2365
	private function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '')
2366
	{
2367
		global $langs, $conf, $user, $db;
2368
2369
		$outkey='';
2370
		$outval='';
2371
		$outref='';
2372
		$outlabel='';
2373
		$outdesc='';
2374
		$outbarcode='';
2375
		$outtype='';
2376
		$outprice_ht='';
2377
		$outprice_ttc='';
2378
		$outpricebasetype='';
2379
		$outtva_tx='';
2380
		$outqty=1;
2381
		$outdiscount=0;
2382
2383
		$maxlengtharticle=(empty($conf->global->PRODUCT_MAX_LENGTH_COMBO)?48:$conf->global->PRODUCT_MAX_LENGTH_COMBO);
2384
2385
		$label=$objp->label;
2386
		if (! empty($objp->label_translated)) $label=$objp->label_translated;
2387
		if (! empty($filterkey) && $filterkey != '') $label=preg_replace('/('.preg_quote($filterkey).')/i', '<strong>$1</strong>', $label, 1);
2388
2389
		$outkey=$objp->rowid;
2390
		$outref=$objp->ref;
2391
		$outlabel=$objp->label;
2392
		$outdesc=$objp->description;
2393
		$outbarcode=$objp->barcode;
2394
2395
		$outtype=$objp->fk_product_type;
2396
		$outdurationvalue=$outtype == Product::TYPE_SERVICE?substr($objp->duration, 0, dol_strlen($objp->duration)-1):'';
2397
		$outdurationunit=$outtype == Product::TYPE_SERVICE?substr($objp->duration, -1):'';
2398
2399
		$opt = '<option value="'.$objp->rowid.'"';
2400
		$opt.= ($objp->rowid == $selected)?' selected':'';
2401
		if (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0)
2402
		{
2403
			$opt.= ' pbq="'.$objp->price_by_qty_rowid.'" data-pbq="'.$objp->price_by_qty_rowid.'" data-pbqqty="'.$objp->price_by_qty_quantity.'" data-pbqpercent="'.$objp->price_by_qty_remise_percent.'"';
2404
		}
2405
		if (! empty($conf->stock->enabled) && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)))
2406
		{
2407
			if ($objp->stock > 0) $opt.= ' class="product_line_stock_ok"';
2408
			elseif ($objp->stock <= 0) $opt.= ' class="product_line_stock_too_low"';
2409
		}
2410
		$opt.= '>';
2411
		$opt.= $objp->ref;
2412
		if ($outbarcode) $opt.=' ('.$outbarcode.')';
2413
		$opt.=' - '.dol_trunc($label, $maxlengtharticle);
2414
        // Units
2415
        if (! empty($conf->global->PRODUCT_USE_UNITS)) {
2416
            $opt .= ' (' . $objp->unit_short . ')';
2417
        }
2418
2419
		$objRef = $objp->ref;
2420
		if (! empty($filterkey) && $filterkey != '') $objRef=preg_replace('/('.preg_quote($filterkey).')/i', '<strong>$1</strong>', $objRef, 1);
2421
		$outval.=$objRef;
2422
		if ($outbarcode) $outval.=' ('.$outbarcode.')';
2423
		$outval.=' - '.dol_trunc($label, $maxlengtharticle);
2424
2425
		$found=0;
2426
2427
		// Multiprice
2428
		// If we need a particular price level (from 1 to 6)
2429
		if (empty($hidepriceinlabel) && $price_level >= 1 && (! empty($conf->global->PRODUIT_MULTIPRICES) || ! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)))
2430
		{
2431
			$sql = "SELECT price, price_ttc, price_base_type, tva_tx";
2432
			$sql.= " FROM ".MAIN_DB_PREFIX."product_price";
2433
			$sql.= " WHERE fk_product='".$objp->rowid."'";
2434
			$sql.= " AND entity IN (".getEntity('productprice').")";
2435
			$sql.= " AND price_level=".$price_level;
2436
			$sql.= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid.
2437
			$sql.= " LIMIT 1";
2438
2439
			dol_syslog(get_class($this).'::constructProductListOption search price for level '.$price_level.'', LOG_DEBUG);
2440
			$result2 = $this->db->query($sql);
2441
			if ($result2)
2442
			{
2443
				$objp2 = $this->db->fetch_object($result2);
2444
				if ($objp2)
2445
				{
2446
					$found=1;
2447
					if ($objp2->price_base_type == 'HT')
2448
					{
2449
						$opt.= ' - '.price($objp2->price, 1, $langs, 0, 0, -1, $conf->currency).' '.$langs->trans("HT");
2450
						$outval.= ' - '.price($objp2->price, 0, $langs, 0, 0, -1, $conf->currency).' '.$langs->transnoentities("HT");
2451
					}
2452
					else
2453
					{
2454
						$opt.= ' - '.price($objp2->price_ttc, 1, $langs, 0, 0, -1, $conf->currency).' '.$langs->trans("TTC");
2455
						$outval.= ' - '.price($objp2->price_ttc, 0, $langs, 0, 0, -1, $conf->currency).' '.$langs->transnoentities("TTC");
2456
					}
2457
					$outprice_ht=price($objp2->price);
2458
					$outprice_ttc=price($objp2->price_ttc);
2459
					$outpricebasetype=$objp2->price_base_type;
2460
					$outtva_tx=$objp2->tva_tx;
2461
				}
2462
			}
2463
			else
2464
			{
2465
				dol_print_error($this->db);
2466
			}
2467
		}
2468
2469
		// Price by quantity
2470
		if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1 && (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)))
2471
		{
2472
			$found = 1;
2473
			$outqty=$objp->quantity;
2474
			$outdiscount=$objp->remise_percent;
2475
			if ($objp->quantity == 1)
2476
			{
2477
				$opt.= ' - '.price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency)."/";
2478
				$outval.= ' - '.price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency)."/";
2479
				$opt.= $langs->trans("Unit");	// Do not use strtolower because it breaks utf8 encoding
2480
				$outval.=$langs->transnoentities("Unit");
2481
			}
2482
			else
2483
			{
2484
				$opt.= ' - '.price($objp->price, 1, $langs, 0, 0, -1, $conf->currency)."/".$objp->quantity;
2485
				$outval.= ' - '.price($objp->price, 0, $langs, 0, 0, -1, $conf->currency)."/".$objp->quantity;
2486
				$opt.= $langs->trans("Units");	// Do not use strtolower because it breaks utf8 encoding
2487
				$outval.=$langs->transnoentities("Units");
2488
			}
2489
2490
			$outprice_ht=price($objp->unitprice);
2491
			$outprice_ttc=price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
2492
			$outpricebasetype=$objp->price_base_type;
2493
			$outtva_tx=$objp->tva_tx;
2494
		}
2495
		if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1)
2496
		{
2497
			$opt.=" (".price($objp->unitprice, 1, $langs, 0, 0, -1, $conf->currency)."/".$langs->trans("Unit").")";	// Do not use strtolower because it breaks utf8 encoding
2498
			$outval.=" (".price($objp->unitprice, 0, $langs, 0, 0, -1, $conf->currency)."/".$langs->transnoentities("Unit").")";	// Do not use strtolower because it breaks utf8 encoding
2499
		}
2500
		if (empty($hidepriceinlabel) && !empty($objp->remise_percent) && $objp->remise_percent >= 1)
2501
		{
2502
			$opt.=" - ".$langs->trans("Discount")." : ".vatrate($objp->remise_percent).' %';
2503
			$outval.=" - ".$langs->transnoentities("Discount")." : ".vatrate($objp->remise_percent).' %';
2504
		}
2505
2506
		// Price by customer
2507
		if (empty($hidepriceinlabel) && !empty($conf->global->PRODUIT_CUSTOMER_PRICES))
2508
		{
2509
			if (!empty($objp->idprodcustprice))
2510
			{
2511
				$found = 1;
2512
2513
				if ($objp->custprice_base_type == 'HT')
2514
				{
2515
					$opt.= ' - '.price($objp->custprice, 1, $langs, 0, 0, -1, $conf->currency).' '.$langs->trans("HT");
2516
					$outval.= ' - '.price($objp->custprice, 0, $langs, 0, 0, -1, $conf->currency).' '.$langs->transnoentities("HT");
2517
				}
2518
				else
2519
				{
2520
					$opt.= ' - '.price($objp->custprice_ttc, 1, $langs, 0, 0, -1, $conf->currency).' '.$langs->trans("TTC");
2521
					$outval.= ' - '.price($objp->custprice_ttc, 0, $langs, 0, 0, -1, $conf->currency).' '.$langs->transnoentities("TTC");
2522
				}
2523
2524
				$outprice_ht=price($objp->custprice);
2525
				$outprice_ttc=price($objp->custprice_ttc);
2526
				$outpricebasetype=$objp->custprice_base_type;
2527
				$outtva_tx=$objp->custtva_tx;
2528
			}
2529
		}
2530
2531
		// If level no defined or multiprice not found, we used the default price
2532
		if (empty($hidepriceinlabel) && ! $found)
2533
		{
2534
			if ($objp->price_base_type == 'HT')
2535
			{
2536
				$opt.= ' - '.price($objp->price, 1, $langs, 0, 0, -1, $conf->currency).' '.$langs->trans("HT");
2537
				$outval.= ' - '.price($objp->price, 0, $langs, 0, 0, -1, $conf->currency).' '.$langs->transnoentities("HT");
2538
			}
2539
			else
2540
			{
2541
				$opt.= ' - '.price($objp->price_ttc, 1, $langs, 0, 0, -1, $conf->currency).' '.$langs->trans("TTC");
2542
				$outval.= ' - '.price($objp->price_ttc, 0, $langs, 0, 0, -1, $conf->currency).' '.$langs->transnoentities("TTC");
2543
			}
2544
			$outprice_ht=price($objp->price);
2545
			$outprice_ttc=price($objp->price_ttc);
2546
			$outpricebasetype=$objp->price_base_type;
2547
			$outtva_tx=$objp->tva_tx;
2548
		}
2549
2550
		if (! empty($conf->stock->enabled) && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)))
2551
		{
2552
			$opt.= ' - '.$langs->trans("Stock").':'.$objp->stock;
2553
2554
			if ($objp->stock > 0) {
2555
				$outval.= ' - <span class="product_line_stock_ok">';
2556
			}elseif ($objp->stock <= 0) {
2557
				$outval.= ' - <span class="product_line_stock_too_low">';
2558
			}
2559
			$outval.= $langs->transnoentities("Stock").':'.$objp->stock;
2560
			$outval.= '</span>';
2561
			if (! empty($conf->global->STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO))  // Warning, this option may slow down combo list generation
2562
			{
2563
			    $langs->load("stocks");
2564
2565
			    $tmpproduct=new Product($this->db);
2566
			    $tmpproduct->fetch($objp->rowid);
2567
			    $tmpproduct->load_virtual_stock();
2568
			    $virtualstock = $tmpproduct->stock_theorique;
2569
2570
			    $opt.= ' - '.$langs->trans("VirtualStock").':'.$virtualstock;
2571
2572
			    $outval.=' - '.$langs->transnoentities("VirtualStock").':';
2573
			    if ($virtualstock > 0) {
2574
			        $outval.= ' - <span class="product_line_stock_ok">';
2575
			    }elseif ($virtualstock <= 0) {
2576
			        $outval.= ' - <span class="product_line_stock_too_low">';
2577
			    }
2578
			    $outval.=$virtualstock;
2579
			    $outval.='</span>';
2580
2581
			    unset($tmpproduct);
2582
			}
2583
		}
2584
2585
		if ($outdurationvalue && $outdurationunit)
2586
		{
2587
			$da=array("h"=>$langs->trans("Hour"),"d"=>$langs->trans("Day"),"w"=>$langs->trans("Week"),"m"=>$langs->trans("Month"),"y"=>$langs->trans("Year"));
2588
			if (isset($da[$outdurationunit]))
2589
			{
2590
				$key = $da[$outdurationunit].($outdurationvalue > 1?'s':'');
2591
				$opt.= ' - '.$outdurationvalue.' '.$langs->trans($key);
2592
				$outval.=' - '.$outdurationvalue.' '.$langs->transnoentities($key);
2593
			}
2594
		}
2595
2596
		$opt.= "</option>\n";
2597
		$optJson = array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'label2'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>price2num($outprice_ht), 'price_ttc'=>price2num($outprice_ttc), 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, 'discount'=>$outdiscount, 'duration_value'=>$outdurationvalue, 'duration_unit'=>$outdurationunit);
2598
	}
2599
2600
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2601
	/**
2602
	 *	Return list of products for customer (in Ajax if Ajax activated or go to select_produits_fournisseurs_list)
2603
	 *
2604
	 *	@param	int		$socid			Id third party
2605
	 *	@param  string	$selected       Preselected product
2606
	 *	@param  string	$htmlname       Name of HTML Select
2607
	 *  @param	string	$filtertype     Filter on product type (''=nofilter, 0=product, 1=service)
2608
	 *	@param  string	$filtre			For a SQL filter
2609
	 *	@param	array	$ajaxoptions	Options for ajax_autocompleter
2610
	 *  @param	int		$hidelabel		Hide label (0=no, 1=yes)
2611
	 *  @param  int     $alsoproductwithnosupplierprice    1=Add also product without supplier prices
2612
	 *  @param	string	$morecss		More CSS
2613
	 *	@return	void
2614
	 */
2615
    public function select_produits_fournisseurs($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $ajaxoptions = array(), $hidelabel = 0, $alsoproductwithnosupplierprice = 0, $morecss = '')
2616
	{
2617
        // phpcs:enable
2618
		global $langs,$conf;
2619
		global $price_level, $status, $finished;
2620
2621
		$selected_input_value='';
2622
		if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT))
2623
		{
2624
			if ($selected > 0)
2625
			{
2626
				require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
2627
				$producttmpselect = new Product($this->db);
2628
				$producttmpselect->fetch($selected);
2629
				$selected_input_value=$producttmpselect->ref;
2630
				unset($producttmpselect);
2631
			}
2632
2633
			// mode=2 means suppliers products
2634
			$urloption=($socid > 0?'socid='.$socid.'&':'').'htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=2&status='.$status.'&finished='.$finished.'&alsoproductwithnosupplierprice='.$alsoproductwithnosupplierprice;
2635
			print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
2636
			print ($hidelabel?'':$langs->trans("RefOrLabel").' : ').'<input type="text" size="20" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'">';
2637
		}
2638
		else
2639
		{
2640
			print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', -1, 0, 0, $alsoproductwithnosupplierprice, $morecss);
0 ignored issues
show
Bug introduced by
Are you sure $this->select_produits_f...upplierprice, $morecss) of type array can be used in print()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2640
			print /** @scrutinizer ignore-type */ $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', -1, 0, 0, $alsoproductwithnosupplierprice, $morecss);
Loading history...
2641
		}
2642
	}
2643
2644
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2645
	/**
2646
	 *	Return list of suppliers products
2647
	 *
2648
	 *	@param	int		$socid   		Id societe fournisseur (0 pour aucun filtre)
2649
	 *	@param  int		$selected       Product price pre-selected (must be 'id' in product_fournisseur_price or 'idprod_IDPROD')
2650
	 *	@param  string	$htmlname       Nom de la zone select
2651
	 *  @param	string	$filtertype     Filter on product type (''=nofilter, 0=product, 1=service)
2652
	 *	@param  string	$filtre         Pour filtre sql
2653
	 *	@param  string	$filterkey      Filtre des produits
2654
	 *  @param  int		$statut         -1=Return all products, 0=Products not on sell, 1=Products on sell (not used here, a filter on tobuy is already hard coded in request)
2655
	 *  @param  int		$outputmode     0=HTML select string, 1=Array
2656
	 *  @param  int     $limit          Limit of line number
2657
	 *  @param  int     $alsoproductwithnosupplierprice    1=Add also product without supplier prices
2658
	 *  @param	string	$morecss		Add more CSS
2659
	 *  @return array           		Array of keys for json
2660
	 */
2661
    public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '')
2662
	{
2663
        // phpcs:enable
2664
		global $langs,$conf,$db;
2665
2666
		$out='';
2667
		$outarray=array();
2668
2669
		$langs->load('stocks');
2670
2671
		$sql = "SELECT p.rowid, p.label, p.ref, p.price, p.duration, p.fk_product_type,";
2672
		$sql.= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice,";
2673
		$sql.= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.fk_soc, s.nom as name,";
2674
		$sql.= " pfp.supplier_reputation";
2675
        if (! empty($conf->barcode->enabled)) $sql.= " ,pfp.barcode";
2676
		$sql.= " FROM ".MAIN_DB_PREFIX."product as p";
2677
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
2678
		if ($socid) $sql.= " AND pfp.fk_soc = ".$socid;
2679
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON pfp.fk_soc = s.rowid";
2680
		$sql.= " WHERE p.entity IN (".getEntity('product').")";
2681
		$sql.= " AND p.tobuy = 1";
2682
		if (strval($filtertype) != '') $sql.=" AND p.fk_product_type=".$this->db->escape($filtertype);
2683
		if (! empty($filtre)) $sql.=" ".$filtre;
2684
		// Add criteria on ref/label
2685
		if ($filterkey != '')
2686
		{
2687
			$sql.=' AND (';
2688
			$prefix=empty($conf->global->PRODUCT_DONOTSEARCH_ANYWHERE)?'%':'';	// Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
2689
			// For natural search
2690
			$scrit = explode(' ', $filterkey);
2691
			$i=0;
2692
			if (count($scrit) > 1) $sql.="(";
2693
			foreach ($scrit as $crit)
2694
			{
2695
				if ($i > 0) $sql.=" AND ";
2696
				$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)."%')";
2697
				$i++;
2698
			}
2699
			if (count($scrit) > 1) $sql.=")";
2700
			if (! empty($conf->barcode->enabled)){
2701
                $sql.= " OR p.barcode LIKE '".$this->db->escape($prefix.$filterkey)."%'";
2702
                $sql.= " OR pfp.barcode LIKE '".$this->db->escape($prefix.$filterkey)."%'";
2703
            }
2704
			$sql.=')';
2705
		}
2706
		$sql.= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC";
2707
		$sql.= $db->plimit($limit, 0);
2708
2709
		// Build output string
2710
2711
		dol_syslog(get_class($this)."::select_produits_fournisseurs_list", LOG_DEBUG);
2712
		$result=$this->db->query($sql);
2713
		if ($result)
2714
		{
2715
			require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
2716
2717
			$num = $this->db->num_rows($result);
2718
2719
			//$out.='<select class="flat" id="select'.$htmlname.'" name="'.$htmlname.'">';	// remove select to have id same with combo and ajax
2720
			$out.='<select class="flat maxwidthonsmartphone'.($morecss?' '.$morecss:'').'" id="'.$htmlname.'" name="'.$htmlname.'">';
2721
			if (! $selected) $out.='<option value="0" selected>&nbsp;</option>';
2722
			else $out.='<option value="0">&nbsp;</option>';
2723
2724
			$i = 0;
2725
			while ($i < $num)
2726
			{
2727
				$objp = $this->db->fetch_object($result);
2728
2729
				$outkey=$objp->idprodfournprice;                                                    // id in table of price
2730
				if (! $outkey && $alsoproductwithnosupplierprice) $outkey='idprod_'.$objp->rowid;   // id of product
2731
2732
				$outref=$objp->ref;
2733
				$outval='';
2734
				$outqty=1;
2735
				$outdiscount=0;
2736
				$outtype=$objp->fk_product_type;
2737
				$outdurationvalue=$outtype == Product::TYPE_SERVICE?substr($objp->duration, 0, dol_strlen($objp->duration)-1):'';
2738
				$outdurationunit=$outtype == Product::TYPE_SERVICE?substr($objp->duration, -1):'';
2739
2740
				$opt = '<option value="'.$outkey.'"';
2741
				if ($selected && $selected == $objp->idprodfournprice) $opt.= ' selected';
2742
				if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) $opt.=' disabled';
2743
				if (!empty($objp->idprodfournprice) && $objp->idprodfournprice > 0)
2744
				{
2745
					$opt.= ' pbq="'.$objp->idprodfournprice.'" data-pbq="'.$objp->idprodfournprice.'" data-pbqqty="'.$objp->quantity.'" data-pbqpercent="'.$objp->remise_percent.'"';
2746
				}
2747
				$opt.= '>';
2748
2749
				$objRef = $objp->ref;
2750
				if ($filterkey && $filterkey != '') $objRef=preg_replace('/('.preg_quote($filterkey).')/i', '<strong>$1</strong>', $objRef, 1);
2751
				$objRefFourn = $objp->ref_fourn;
2752
				if ($filterkey && $filterkey != '') $objRefFourn=preg_replace('/('.preg_quote($filterkey).')/i', '<strong>$1</strong>', $objRefFourn, 1);
2753
				$label = $objp->label;
2754
				if ($filterkey && $filterkey != '') $label=preg_replace('/('.preg_quote($filterkey).')/i', '<strong>$1</strong>', $label, 1);
2755
2756
				$opt.=$objp->ref;
2757
				if (! empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn))
2758
					$opt.=' ('.$objp->ref_fourn.')';
2759
				$opt.=' - ';
2760
				$outval.=$objRef;
2761
				if (! empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn))
2762
					$outval.=' ('.$objRefFourn.')';
2763
				$outval.=' - ';
2764
				$opt.=dol_trunc($label, 72).' - ';
2765
				$outval.=dol_trunc($label, 72).' - ';
2766
2767
				if (! empty($objp->idprodfournprice))
2768
				{
2769
					$outqty=$objp->quantity;
2770
					$outdiscount=$objp->remise_percent;
2771
					if (!empty($conf->dynamicprices->enabled) && !empty($objp->fk_supplier_price_expression)) {
2772
						$prod_supplier = new ProductFournisseur($this->db);
2773
						$prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
2774
						$prod_supplier->id = $objp->fk_product;
2775
						$prod_supplier->fourn_qty = $objp->quantity;
2776
						$prod_supplier->fourn_tva_tx = $objp->tva_tx;
2777
						$prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
2778
						$priceparser = new PriceParser($this->db);
2779
						$price_result = $priceparser->parseProductSupplier($prod_supplier);
2780
						if ($price_result >= 0) {
2781
							$objp->fprice = $price_result;
2782
							if ($objp->quantity >= 1)
2783
							{
2784
								$objp->unitprice = $objp->fprice / $objp->quantity;
2785
							}
2786
						}
2787
					}
2788
					if ($objp->quantity == 1)
2789
					{
2790
						$opt.= price($objp->fprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE)?(1 - $objp->remise_percent / 100):1), 1, $langs, 0, 0, -1, $conf->currency)."/";
2791
						$outval.= price($objp->fprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE)?(1 - $objp->remise_percent / 100):1), 0, $langs, 0, 0, -1, $conf->currency)."/";
2792
						$opt.= $langs->trans("Unit");	// Do not use strtolower because it breaks utf8 encoding
2793
						$outval.=$langs->transnoentities("Unit");
2794
					}
2795
					else
2796
					{
2797
						$opt.= price($objp->fprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE)?(1 - $objp->remise_percent / 100):1), 1, $langs, 0, 0, -1, $conf->currency)."/".$objp->quantity;
2798
						$outval.= price($objp->fprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE)?(1 - $objp->remise_percent / 100):1), 0, $langs, 0, 0, -1, $conf->currency)."/".$objp->quantity;
2799
						$opt.= ' '.$langs->trans("Units");	// Do not use strtolower because it breaks utf8 encoding
2800
						$outval.= ' '.$langs->transnoentities("Units");
2801
					}
2802
2803
					if ($objp->quantity >= 1)
2804
					{
2805
						$opt.=" (".price($objp->unitprice * (!empty($conf->global->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
2806
						$outval.=" (".price($objp->unitprice * (!empty($conf->global->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
2807
					}
2808
					if ($objp->remise_percent >= 1)
2809
					{
2810
						$opt.=" - ".$langs->trans("Discount")." : ".vatrate($objp->remise_percent).' %';
2811
						$outval.=" - ".$langs->transnoentities("Discount")." : ".vatrate($objp->remise_percent).' %';
2812
					}
2813
					if ($objp->duration)
2814
					{
2815
						$opt .= " - ".$objp->duration;
2816
						$outval.=" - ".$objp->duration;
2817
					}
2818
					if (! $socid)
2819
					{
2820
						$opt .= " - ".dol_trunc($objp->name, 8);
2821
						$outval.=" - ".dol_trunc($objp->name, 8);
2822
					}
2823
                    if (! empty($conf->barcode->enabled) && !empty($objp->barcode))
2824
                    {
2825
                        $opt .= " - ".$objp->barcode;
2826
                        $outval.=" - ".$objp->barcode;
2827
                    }
2828
					if ($objp->supplier_reputation)
2829
					{
2830
						//TODO dictionary
2831
						$reputations=array(''=>$langs->trans('Standard'),'FAVORITE'=>$langs->trans('Favorite'),'NOTTHGOOD'=>$langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER'=>$langs->trans('DoNotOrderThisProductToThisSupplier'));
2832
2833
						$opt .= " - ".$reputations[$objp->supplier_reputation];
2834
						$outval.=" - ".$reputations[$objp->supplier_reputation];
2835
					}
2836
				}
2837
				else
2838
				{
2839
					if (empty($alsoproductwithnosupplierprice))     // No supplier price defined for couple product/supplier
2840
					{
2841
						$opt.= $langs->trans("NoPriceDefinedForThisSupplier");
2842
						$outval.=$langs->transnoentities("NoPriceDefinedForThisSupplier");
2843
					}
2844
					else                                            // No supplier price defined for product, even on other suppliers
2845
					{
2846
						$opt.= $langs->trans("NoPriceDefinedForThisSupplier");
2847
						$outval.=$langs->transnoentities("NoPriceDefinedForThisSupplier");
2848
					}
2849
				}
2850
				$opt .= "</option>\n";
2851
2852
2853
				// Add new entry
2854
				// "key" value of json key array is used by jQuery automatically as selected value
2855
				// "label" value of json key array is used by jQuery automatically as text for combo box
2856
				$out.=$opt;
2857
				array_push($outarray, array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'qty'=>$outqty, 'discount'=>$outdiscount, 'type'=>$outtype, 'duration_value'=>$outdurationvalue, 'duration_unit'=>$outdurationunit, 'disabled'=>(empty($objp->idprodfournprice)?true:false)));
2858
				// Exemple of var_dump $outarray
2859
				// array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
2860
				//           ["label"]=>string(76) "ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
2861
				//      	 ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false)
2862
				//}
2863
				//var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
2864
				//$outval=array('label'=>'ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)');
2865
				//var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
2866
2867
				$i++;
2868
			}
2869
			$out.='</select>';
2870
2871
			$this->db->free($result);
2872
2873
			include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2874
			$out.=ajax_combobox($htmlname);
2875
2876
			if (empty($outputmode)) return $out;
2877
			return $outarray;
2878
		}
2879
		else
2880
		{
2881
			dol_print_error($this->db);
2882
		}
2883
	}
2884
2885
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2886
	/**
2887
	 *	Return list of suppliers prices for a product
2888
	 *
2889
	 *  @param	    int		$productid       	Id of product
2890
	 *  @param      string	$htmlname        	Name of HTML field
2891
	 *  @param      int		$selected_supplier  Pre-selected supplier if more than 1 result
2892
	 *  @return	    void
2893
	 */
2894
    public function select_product_fourn_price($productid, $htmlname = 'productfournpriceid', $selected_supplier = '')
2895
	{
2896
        // phpcs:enable
2897
		global $langs,$conf;
2898
2899
		$langs->load('stocks');
2900
2901
		$sql = "SELECT p.rowid, p.label, p.ref, p.price, p.duration, pfp.fk_soc,";
2902
		$sql.= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,";
2903
		$sql.= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name";
2904
		$sql.= " FROM ".MAIN_DB_PREFIX."product as p";
2905
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
2906
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON pfp.fk_soc = s.rowid";
2907
		$sql.= " WHERE pfp.entity IN (".getEntity('productsupplierprice').")";
2908
		$sql.= " AND p.tobuy = 1";
2909
		$sql.= " AND s.fournisseur = 1";
2910
		$sql.= " AND p.rowid = ".$productid;
2911
		$sql.= " ORDER BY s.nom, pfp.ref_fourn DESC";
2912
2913
		dol_syslog(get_class($this)."::select_product_fourn_price", LOG_DEBUG);
2914
		$result=$this->db->query($sql);
2915
2916
		if ($result)
2917
		{
2918
			$num = $this->db->num_rows($result);
2919
2920
			$form = '<select class="flat" id="select_'.$htmlname.'" name="'.$htmlname.'">';
2921
2922
			if (! $num)
2923
			{
2924
				$form.= '<option value="0">-- '.$langs->trans("NoSupplierPriceDefinedForThisProduct").' --</option>';
2925
			}
2926
			else
2927
			{
2928
				require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
2929
				$form.= '<option value="0">&nbsp;</option>';
2930
2931
				$i = 0;
2932
				while ($i < $num)
2933
				{
2934
					$objp = $this->db->fetch_object($result);
2935
2936
					$opt = '<option value="'.$objp->idprodfournprice.'"';
2937
					//if there is only one supplier, preselect it
2938
					if($num == 1 || ($selected_supplier > 0 && $objp->fk_soc == $selected_supplier)) {
2939
						$opt .= ' selected';
2940
					}
2941
					$opt.= '>'.$objp->name.' - '.$objp->ref_fourn.' - ';
2942
2943
					if (!empty($conf->dynamicprices->enabled) && !empty($objp->fk_supplier_price_expression)) {
2944
						$prod_supplier = new ProductFournisseur($this->db);
2945
						$prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
2946
						$prod_supplier->id = $productid;
2947
						$prod_supplier->fourn_qty = $objp->quantity;
2948
						$prod_supplier->fourn_tva_tx = $objp->tva_tx;
2949
						$prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
2950
						$priceparser = new PriceParser($this->db);
2951
						$price_result = $priceparser->parseProductSupplier($prod_supplier);
2952
						if ($price_result >= 0) {
2953
							$objp->fprice = $price_result;
2954
							if ($objp->quantity >= 1)
2955
							{
2956
								$objp->unitprice = $objp->fprice / $objp->quantity;
2957
							}
2958
						}
2959
					}
2960
					if ($objp->quantity == 1)
2961
					{
2962
						$opt.= price($objp->fprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE)?(1 - $objp->remise_percent / 100):1), 1, $langs, 0, 0, -1, $conf->currency)."/";
2963
					}
2964
2965
					$opt.= $objp->quantity.' ';
2966
2967
					if ($objp->quantity == 1)
2968
					{
2969
						$opt.= $langs->trans("Unit");
2970
					}
2971
					else
2972
					{
2973
						$opt.= $langs->trans("Units");
2974
					}
2975
					if ($objp->quantity > 1)
2976
					{
2977
						$opt.=" - ";
2978
						$opt.= price($objp->unitprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE)?(1 - $objp->remise_percent / 100):1), 1, $langs, 0, 0, -1, $conf->currency)."/".$langs->trans("Unit");
2979
					}
2980
					if ($objp->duration) $opt .= " - ".$objp->duration;
2981
					$opt .= "</option>\n";
2982
2983
					$form.= $opt;
2984
					$i++;
2985
				}
2986
			}
2987
2988
			$form.= '</select>';
2989
			$this->db->free($result);
2990
			return $form;
2991
		}
2992
		else
2993
		{
2994
			dol_print_error($this->db);
2995
		}
2996
	}
2997
2998
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2999
	/**
3000
	 *    Return list of delivery address
3001
	 *
3002
	 *    @param    string	$selected          	Id contact pre-selectionn
3003
	 *    @param    int		$socid				Id of company
3004
	 *    @param    string	$htmlname          	Name of HTML field
3005
	 *    @param    int		$showempty         	Add an empty field
3006
	 *    @return	integer|null
3007
	 */
3008
    public function select_address($selected, $socid, $htmlname = 'address_id', $showempty = 0)
3009
	{
3010
        // phpcs:enable
3011
		// looking for users
3012
		$sql = "SELECT a.rowid, a.label";
3013
		$sql .= " FROM ".MAIN_DB_PREFIX ."societe_address as a";
3014
		$sql .= " WHERE a.fk_soc = ".$socid;
3015
		$sql .= " ORDER BY a.label ASC";
3016
3017
		dol_syslog(get_class($this)."::select_address", LOG_DEBUG);
3018
		$resql=$this->db->query($sql);
3019
		if ($resql)
3020
		{
3021
			print '<select class="flat" id="select_'.$htmlname.'" name="'.$htmlname.'">';
3022
			if ($showempty) print '<option value="0">&nbsp;</option>';
3023
			$num = $this->db->num_rows($resql);
3024
			$i = 0;
3025
			if ($num)
3026
			{
3027
				while ($i < $num)
3028
				{
3029
					$obj = $this->db->fetch_object($resql);
3030
3031
					if ($selected && $selected == $obj->rowid)
3032
					{
3033
						print '<option value="'.$obj->rowid.'" selected>'.$obj->label.'</option>';
3034
					}
3035
					else
3036
					{
3037
						print '<option value="'.$obj->rowid.'">'.$obj->label.'</option>';
3038
					}
3039
					$i++;
3040
				}
3041
			}
3042
			print '</select>';
3043
			return $num;
3044
		}
3045
		else
3046
		{
3047
			dol_print_error($this->db);
3048
		}
3049
	}
3050
3051
3052
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3053
	/**
3054
	 *      Load into cache list of payment terms
3055
	 *
3056
	 *      @return     int             Nb of lines loaded, <0 if KO
3057
	 */
3058
    public function load_cache_conditions_paiements()
3059
	{
3060
        // phpcs:enable
3061
		global $langs;
3062
3063
		$num = count($this->cache_conditions_paiements);
3064
		if ($num > 0) return 0;    // Cache already loaded
3065
3066
		dol_syslog(__METHOD__, LOG_DEBUG);
3067
3068
		$sql = "SELECT rowid, code, libelle as label";
3069
		$sql.= " FROM ".MAIN_DB_PREFIX.'c_payment_term';
3070
		$sql.= " WHERE entity IN (".getEntity('c_payment_term').")";
3071
		$sql.= " AND active > 0";
3072
		$sql.= " ORDER BY sortorder";
3073
3074
		$resql = $this->db->query($sql);
3075
		if ($resql)
3076
		{
3077
			$num = $this->db->num_rows($resql);
3078
			$i = 0;
3079
			while ($i < $num)
3080
			{
3081
				$obj = $this->db->fetch_object($resql);
3082
3083
				// Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
3084
				$label=($langs->trans("PaymentConditionShort".$obj->code)!=("PaymentConditionShort".$obj->code)?$langs->trans("PaymentConditionShort".$obj->code):($obj->label!='-'?$obj->label:''));
3085
				$this->cache_conditions_paiements[$obj->rowid]['code'] =$obj->code;
3086
				$this->cache_conditions_paiements[$obj->rowid]['label']=$label;
3087
				$i++;
3088
			}
3089
3090
			//$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1);		// We use the field sortorder of table
3091
3092
			return $num;
3093
		}
3094
		else
3095
		{
3096
			dol_print_error($this->db);
3097
			return -1;
3098
		}
3099
	}
3100
3101
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3102
	/**
3103
	 *      Charge dans cache la liste des délais de livraison possibles
3104
	 *
3105
	 *      @return     int             Nb of lines loaded, <0 if KO
3106
	 */
3107
    public function load_cache_availability()
3108
	{
3109
        // phpcs:enable
3110
		global $langs;
3111
3112
		$num = count($this->cache_availability);
3113
		if ($num > 0) return 0;    // Cache already loaded
3114
3115
		dol_syslog(__METHOD__, LOG_DEBUG);
3116
3117
		$langs->load('propal');
3118
3119
		$sql = "SELECT rowid, code, label";
3120
		$sql.= " FROM ".MAIN_DB_PREFIX.'c_availability';
3121
		$sql.= " WHERE active > 0";
3122
3123
		$resql = $this->db->query($sql);
3124
		if ($resql)
3125
		{
3126
			$num = $this->db->num_rows($resql);
3127
			$i = 0;
3128
			while ($i < $num)
3129
			{
3130
				$obj = $this->db->fetch_object($resql);
3131
3132
				// Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
3133
				$label=($langs->trans("AvailabilityType".$obj->code)!=("AvailabilityType".$obj->code)?$langs->trans("AvailabilityType".$obj->code):($obj->label!='-'?$obj->label:''));
3134
				$this->cache_availability[$obj->rowid]['code'] =$obj->code;
3135
				$this->cache_availability[$obj->rowid]['label']=$label;
3136
				$i++;
3137
			}
3138
3139
			$this->cache_availability = dol_sort_array($this->cache_availability, 'label', 'asc', 0, 0, 1);
3140
3141
			return $num;
3142
		}
3143
		else
3144
		{
3145
			dol_print_error($this->db);
3146
			return -1;
3147
		}
3148
	}
3149
3150
	/**
3151
	 *      Retourne la liste des types de delais de livraison possibles
3152
	 *
3153
	 *      @param	int		$selected        Id du type de delais pre-selectionne
3154
	 *      @param  string	$htmlname        Nom de la zone select
3155
	 *      @param  string	$filtertype      To add a filter
3156
	 *		@param	int		$addempty		Add empty entry
3157
	 *		@return	void
3158
	 */
3159
    public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0)
3160
	{
3161
		global $langs,$user;
3162
3163
		$this->load_cache_availability();
3164
3165
		dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG);
3166
3167
		print '<select id="'.$htmlname.'" class="flat" name="'.$htmlname.'">';
3168
		if ($addempty) print '<option value="0">&nbsp;</option>';
3169
		foreach($this->cache_availability as $id => $arrayavailability)
3170
		{
3171
			if ($selected == $id)
3172
			{
3173
				print '<option value="'.$id.'" selected>';
3174
			}
3175
			else
3176
			{
3177
				print '<option value="'.$id.'">';
3178
			}
3179
			print $arrayavailability['label'];
3180
			print '</option>';
3181
		}
3182
		print '</select>';
3183
		if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
3184
	}
3185
3186
	/**
3187
	 *      Load into cache cache_demand_reason, array of input reasons
3188
	 *
3189
	 *      @return     int             Nb of lines loaded, <0 if KO
3190
	 */
3191
    public function loadCacheInputReason()
3192
	{
3193
		global $langs;
3194
3195
		$num = count($this->cache_demand_reason);
3196
		if ($num > 0) return 0;    // Cache already loaded
3197
3198
		$sql = "SELECT rowid, code, label";
3199
		$sql.= " FROM ".MAIN_DB_PREFIX.'c_input_reason';
3200
		$sql.= " WHERE active > 0";
3201
3202
		$resql = $this->db->query($sql);
3203
		if ($resql)
3204
		{
3205
			$num = $this->db->num_rows($resql);
3206
			$i = 0;
3207
			$tmparray=array();
3208
			while ($i < $num)
3209
			{
3210
				$obj = $this->db->fetch_object($resql);
3211
3212
				// Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
3213
				$label=($obj->label!='-'?$obj->label:'');
3214
				if ($langs->trans("DemandReasonType".$obj->code) != ("DemandReasonType".$obj->code)) $label = $langs->trans("DemandReasonType".$obj->code); // So translation key DemandReasonTypeSRC_XXX will work
3215
				if ($langs->trans($obj->code) != $obj->code) $label=$langs->trans($obj->code);																// So translation key SRC_XXX will work
3216
3217
				$tmparray[$obj->rowid]['id']   =$obj->rowid;
3218
				$tmparray[$obj->rowid]['code'] =$obj->code;
3219
				$tmparray[$obj->rowid]['label']=$label;
3220
				$i++;
3221
			}
3222
3223
			$this->cache_demand_reason=dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1);
3224
3225
			unset($tmparray);
3226
			return $num;
3227
		}
3228
		else
3229
		{
3230
			dol_print_error($this->db);
3231
			return -1;
3232
		}
3233
	}
3234
3235
	/**
3236
	 *	Return list of input reason (events that triggered an object creation, like after sending an emailing, making an advert, ...)
3237
	 *  List found into table c_input_reason loaded by loadCacheInputReason
3238
	 *
3239
	 *  @param	int		$selected        Id or code of type origin to select by default
3240
	 *  @param  string	$htmlname        Nom de la zone select
3241
	 *  @param  string	$exclude         To exclude a code value (Example: SRC_PROP)
3242
	 *	@param	int		$addempty		 Add an empty entry
3243
	 *	@return	void
3244
	 */
3245
    public function selectInputReason($selected = '', $htmlname = 'demandreasonid', $exclude = '', $addempty = 0)
3246
	{
3247
		global $langs,$user;
3248
3249
		$this->loadCacheInputReason();
3250
3251
		print '<select class="flat" id="select_'.$htmlname.'" name="'.$htmlname.'">';
3252
		if ($addempty) print '<option value="0"'.(empty($selected)?' selected':'').'>&nbsp;</option>';
3253
		foreach($this->cache_demand_reason as $id => $arraydemandreason)
3254
		{
3255
			if ($arraydemandreason['code']==$exclude) continue;
3256
3257
			if ($selected && ($selected == $arraydemandreason['id'] || $selected == $arraydemandreason['code']))
3258
			{
3259
				print '<option value="'.$arraydemandreason['id'].'" selected>';
3260
			}
3261
			else
3262
			{
3263
				print '<option value="'.$arraydemandreason['id'].'">';
3264
			}
3265
			$label=$arraydemandreason['label'];	// Translation of label was already done into the ->loadCacheInputReason
3266
			print $langs->trans($label);
3267
			print '</option>';
3268
		}
3269
		print '</select>';
3270
		if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
3271
	}
3272
3273
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3274
	/**
3275
	 *      Charge dans cache la liste des types de paiements possibles
3276
	 *
3277
	 *      @return     int                 Nb of lines loaded, <0 if KO
3278
	 */
3279
    public function load_cache_types_paiements()
3280
	{
3281
        // phpcs:enable
3282
		global $langs;
3283
3284
		$num=count($this->cache_types_paiements);
3285
		if ($num > 0) return $num;    // Cache already loaded
3286
3287
		dol_syslog(__METHOD__, LOG_DEBUG);
3288
3289
		$this->cache_types_paiements = array();
3290
3291
		$sql = "SELECT id, code, libelle as label, type, active";
3292
		$sql.= " FROM ".MAIN_DB_PREFIX."c_paiement";
3293
		$sql.= " WHERE entity IN (".getEntity('c_paiement').")";
3294
		//if ($active >= 0) $sql.= " AND active = ".$active;
3295
3296
		$resql = $this->db->query($sql);
3297
		if ($resql)
3298
		{
3299
			$num = $this->db->num_rows($resql);
3300
			$i = 0;
3301
			while ($i < $num)
3302
			{
3303
				$obj = $this->db->fetch_object($resql);
3304
3305
				// Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
3306
				$label=($langs->transnoentitiesnoconv("PaymentTypeShort".$obj->code)!=("PaymentTypeShort".$obj->code)?$langs->transnoentitiesnoconv("PaymentTypeShort".$obj->code):($obj->label!='-'?$obj->label:''));
3307
				$this->cache_types_paiements[$obj->id]['id'] =$obj->id;
3308
				$this->cache_types_paiements[$obj->id]['code'] =$obj->code;
3309
				$this->cache_types_paiements[$obj->id]['label']=$label;
3310
				$this->cache_types_paiements[$obj->id]['type'] =$obj->type;
3311
				$this->cache_types_paiements[$obj->id]['active'] =$obj->active;
3312
				$i++;
3313
			}
3314
3315
			$this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1);
3316
3317
			return $num;
3318
		}
3319
		else
3320
		{
3321
			dol_print_error($this->db);
3322
			return -1;
3323
		}
3324
	}
3325
3326
3327
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3328
	/**
3329
	 *      Return list of payment modes.
3330
	 *      Constant MAIN_DEFAULT_PAYMENT_TERM_ID can used to set default value but scope is all application, probably not what you want.
3331
	 *      See instead to force the default value by the caller.
3332
	 *
3333
	 *      @param	int		$selected		Id of payment term to preselect by default
3334
	 *      @param	string	$htmlname		Nom de la zone select
3335
	 *      @param	int		$filtertype		Not used
3336
	 *		@param	int		$addempty		Add an empty entry
3337
	 * 		@param	int		$noinfoadmin		0=Add admin info, 1=Disable admin info
3338
	 * 		@param	string	$morecss			Add more CSS on select tag
3339
	 *		@return	void
3340
	 */
3341
    public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '')
3342
	{
3343
        // phpcs:enable
3344
		global $langs, $user, $conf;
3345
3346
		dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG);
3347
3348
		$this->load_cache_conditions_paiements();
3349
3350
		// Set default value if not already set by caller
3351
		if (empty($selected) && ! empty($conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID)) $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID;
3352
3353
		print '<select id="'.$htmlname.'" class="flat selectpaymentterms'.($morecss?' '.$morecss:'').'" name="'.$htmlname.'">';
3354
		if ($addempty) print '<option value="0">&nbsp;</option>';
3355
		foreach($this->cache_conditions_paiements as $id => $arrayconditions)
3356
		{
3357
			if ($selected == $id)
3358
			{
3359
				print '<option value="'.$id.'" selected>';
3360
			}
3361
			else
3362
			{
3363
				print '<option value="'.$id.'">';
3364
			}
3365
			print $arrayconditions['label'];
3366
			print '</option>';
3367
		}
3368
		print '</select>';
3369
		if ($user->admin && empty($noinfoadmin)) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
3370
	}
3371
3372
3373
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3374
	/**
3375
	 *      Return list of payment methods
3376
	 *
3377
	 *      @param	string	$selected       Id du mode de paiement pre-selectionne
3378
	 *      @param  string	$htmlname       Nom de la zone select
3379
	 *      @param  string	$filtertype     To filter on field type in llx_c_paiement ('CRDT' or 'DBIT' or array('code'=>xx,'label'=>zz))
3380
	 *      @param  int		$format         0=id+libelle, 1=code+code, 2=code+libelle, 3=id+code
3381
	 *      @param  int		$empty			1=peut etre vide, 0 sinon
3382
	 * 		@param	int		$noadmininfo	0=Add admin info, 1=Disable admin info
3383
	 *      @param  int		$maxlength      Max length of label
3384
	 *      @param  int     $active         Active or not, -1 = all
3385
	 *      @param  string  $morecss        Add more CSS on select tag
3386
	 * 		@return	void
3387
	 */
3388
    public function select_types_paiements($selected = '', $htmlname = 'paiementtype', $filtertype = '', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '')
3389
	{
3390
        // phpcs:enable
3391
		global $langs,$user;
3392
3393
		dol_syslog(__METHOD__." ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
3394
3395
		$filterarray=array();
3396
		if ($filtertype == 'CRDT')  	$filterarray=array(0,2,3);
3397
		elseif ($filtertype == 'DBIT') 	$filterarray=array(1,2,3);
3398
		elseif ($filtertype != '' && $filtertype != '-1') $filterarray=explode(',', $filtertype);
3399
3400
		$this->load_cache_types_paiements();
3401
3402
		print '<select id="select'.$htmlname.'" class="flat selectpaymenttypes'.($morecss?' '.$morecss:'').'" name="'.$htmlname.'">';
3403
		if ($empty) print '<option value="">&nbsp;</option>';
3404
		foreach($this->cache_types_paiements as $id => $arraytypes)
3405
		{
3406
			// If not good status
3407
			if ($active >= 0 && $arraytypes['active'] != $active) continue;
3408
3409
			// On passe si on a demande de filtrer sur des modes de paiments particuliers
3410
			if (count($filterarray) && ! in_array($arraytypes['type'], $filterarray)) continue;
3411
3412
			// We discard empty line if showempty is on because an empty line has already been output.
3413
			if ($empty && empty($arraytypes['code'])) continue;
3414
3415
			if ($format == 0) print '<option value="'.$id.'"';
3416
			elseif ($format == 1) print '<option value="'.$arraytypes['code'].'"';
3417
			elseif ($format == 2) print '<option value="'.$arraytypes['code'].'"';
3418
			elseif ($format == 3) print '<option value="'.$id.'"';
3419
			// Si selected est text, on compare avec code, sinon avec id
3420
			if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) print ' selected';
3421
			elseif ($selected == $id) print ' selected';
3422
			print '>';
3423
			if ($format == 0) $value=($maxlength?dol_trunc($arraytypes['label'], $maxlength):$arraytypes['label']);
3424
			elseif ($format == 1) $value=$arraytypes['code'];
3425
			elseif ($format == 2) $value=($maxlength?dol_trunc($arraytypes['label'], $maxlength):$arraytypes['label']);
3426
			elseif ($format == 3) $value=$arraytypes['code'];
3427
			print $value?$value:'&nbsp;';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $value does not seem to be defined for all execution paths leading up to this point.
Loading history...
3428
			print '</option>';
3429
		}
3430
		print '</select>';
3431
		if ($user->admin && ! $noadmininfo) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
3432
	}
3433
3434
3435
	/**
3436
	 *  Selection HT or TTC
3437
	 *
3438
	 *  @param	string	$selected       Id pre-selectionne
3439
	 *  @param  string	$htmlname       Nom de la zone select
3440
	 * 	@return	string					Code of HTML select to chose tax or not
3441
	 */
3442
    public function selectPriceBaseType($selected = '', $htmlname = 'price_base_type')
3443
	{
3444
		global $langs;
3445
3446
		$return='';
3447
3448
		$return.= '<select class="flat" id="select_'.$htmlname.'" name="'.$htmlname.'">';
3449
		$options = array(
3450
			'HT'=>$langs->trans("HT"),
3451
			'TTC'=>$langs->trans("TTC")
3452
		);
3453
		foreach($options as $id => $value)
3454
		{
3455
			if ($selected == $id)
3456
			{
3457
				$return.= '<option value="'.$id.'" selected>'.$value;
3458
			}
3459
			else
3460
			{
3461
				$return.= '<option value="'.$id.'">'.$value;
3462
			}
3463
			$return.= '</option>';
3464
		}
3465
		$return.= '</select>';
3466
3467
		return $return;
3468
	}
3469
3470
	/**
3471
	 *  Return a HTML select list of shipping mode
3472
	 *
3473
	 *  @param	string	$selected          Id shipping mode pre-selected
3474
	 *  @param  string	$htmlname          Name of select zone
3475
	 *  @param  string	$filtre            To filter list
3476
	 *  @param  int		$useempty          1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries.
3477
	 *  @param  string	$moreattrib        To add more attribute on select
3478
	 * 	@return	void
3479
	 */
3480
    public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '')
3481
	{
3482
		global $langs, $conf, $user;
3483
3484
		$langs->load("admin");
3485
		$langs->load("deliveries");
3486
3487
		$sql = "SELECT rowid, code, libelle as label";
3488
		$sql.= " FROM ".MAIN_DB_PREFIX."c_shipment_mode";
3489
		$sql.= " WHERE active > 0";
3490
		if ($filtre) $sql.=" AND ".$filtre;
3491
		$sql.= " ORDER BY libelle ASC";
3492
3493
		dol_syslog(get_class($this)."::selectShippingMode", LOG_DEBUG);
3494
		$result = $this->db->query($sql);
3495
		if ($result) {
3496
			$num = $this->db->num_rows($result);
3497
			$i = 0;
3498
			if ($num) {
3499
				print '<select id="select'.$htmlname.'" class="flat selectshippingmethod" name="'.$htmlname.'"'.($moreattrib?' '.$moreattrib:'').'>';
3500
				if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
3501
					print '<option value="-1">&nbsp;</option>';
3502
				}
3503
				while ($i < $num) {
3504
					$obj = $this->db->fetch_object($result);
3505
					if ($selected == $obj->rowid) {
3506
						print '<option value="'.$obj->rowid.'" selected>';
3507
					} else {
3508
						print '<option value="'.$obj->rowid.'">';
3509
					}
3510
					print ($langs->trans("SendingMethod".strtoupper($obj->code)) != "SendingMethod".strtoupper($obj->code)) ? $langs->trans("SendingMethod".strtoupper($obj->code)) : $obj->label;
3511
					print '</option>';
3512
					$i++;
3513
				}
3514
				print "</select>";
3515
				if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
3516
			} else {
3517
				print $langs->trans("NoShippingMethodDefined");
3518
			}
3519
		} else {
3520
			dol_print_error($this->db);
3521
		}
3522
	}
3523
3524
	/**
3525
	 *    Display form to select shipping mode
3526
	 *
3527
	 *    @param	string	$page        Page
3528
	 *    @param    int		$selected    Id of shipping mode
3529
	 *    @param    string	$htmlname    Name of select html field
3530
	 *    @param    int		$addempty    1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries.
3531
	 *    @return	void
3532
	 */
3533
    public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0)
3534
	{
3535
		global $langs, $db;
3536
3537
		$langs->load("deliveries");
3538
3539
		if ($htmlname != "none") {
3540
			print '<form method="POST" action="'.$page.'">';
3541
			print '<input type="hidden" name="action" value="setshippingmethod">';
3542
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
3543
			$this->selectShippingMethod($selected, $htmlname, '', $addempty);
3544
			print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
3545
			print '</form>';
3546
		} else {
3547
			if ($selected) {
3548
				$code=$langs->getLabelFromKey($db, $selected, 'c_shipment_mode', 'rowid', 'code');
3549
				print $langs->trans("SendingMethod".strtoupper($code));
3550
			} else {
3551
				print "&nbsp;";
3552
			}
3553
		}
3554
	}
3555
3556
	/**
3557
	 * Creates HTML last in cycle situation invoices selector
3558
	 *
3559
	 * @param     string  $selected   		Preselected ID
3560
	 * @param     int     $socid      		Company ID
3561
	 *
3562
	 * @return    string                     HTML select
3563
	 */
3564
    public function selectSituationInvoices($selected = '', $socid = 0)
3565
	{
3566
		global $langs;
3567
3568
		$langs->load('bills');
3569
3570
		$opt = '<option value ="" selected></option>';
3571
		$sql = 'SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc';
3572
		$sql.= ' FROM ' . MAIN_DB_PREFIX . 'facture';
3573
		$sql.= ' WHERE entity IN ('.getEntity('invoice').')';
3574
		$sql.= ' AND situation_counter>=1';
3575
		$sql.= ' ORDER by situation_cycle_ref, situation_counter desc';
3576
		$resql = $this->db->query($sql);
3577
		if ($resql && $this->db->num_rows($resql) > 0) {
3578
			// Last seen cycle
3579
			$ref = 0;
3580
			while ($obj = $this->db->fetch_object($resql)){
3581
				//Same company ?
3582
			    if ($socid == $obj->fk_soc) {
3583
					//Same cycle ?
3584
			        if ($obj->situation_cycle_ref != $ref) {
3585
						// Just seen this cycle
3586
			            $ref = $obj->situation_cycle_ref;
3587
						//not final ?
3588
			            if ($obj->situation_final != 1) {
3589
							//Not prov?
3590
			                if (substr($obj->ref, 1, 4) != 'PROV') {
3591
			                    if ($selected == $obj->rowid) {
3592
			                        $opt .= '<option value="' . $obj->rowid . '" selected>' . $obj->ref . '</option>';
3593
								} else {
3594
								    $opt .= '<option value="' . $obj->rowid . '">' . $obj->ref . '</option>';
3595
								}
3596
							}
3597
						}
3598
					}
3599
				}
3600
			}
3601
		}
3602
		else
3603
		{
3604
				dol_syslog("Error sql=" . $sql . ", error=" . $this->error, LOG_ERR);
3605
		}
3606
		if ($opt == '<option value ="" selected></option>')
1 ignored issue
show
introduced by
The condition $opt == '<option value ="" selected></option>' is always true.
Loading history...
3607
		{
3608
			$opt = '<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>';
3609
		}
3610
		return $opt;
3611
	}
3612
3613
	/**
3614
	 *      Creates HTML units selector (code => label)
3615
	 *
3616
	 *      @param	string	$selected       Preselected Unit ID
3617
	 *      @param  string	$htmlname       Select name
3618
	 *      @param	int		$showempty		Add a nempty line
3619
	 * 		@return	string                  HTML select
3620
	 */
3621
    public function selectUnits($selected = '', $htmlname = 'units', $showempty = 0)
3622
	{
3623
		global $langs;
3624
3625
		$langs->load('products');
3626
3627
		$return= '<select class="flat" id="'.$htmlname.'" name="'.$htmlname.'">';
3628
3629
		$sql = 'SELECT rowid, label, code from '.MAIN_DB_PREFIX.'c_units';
3630
		$sql.= ' WHERE active > 0';
3631
3632
		$resql = $this->db->query($sql);
3633
		if($resql && $this->db->num_rows($resql) > 0)
3634
		{
3635
			if ($showempty) $return .= '<option value="none"></option>';
3636
3637
			while($res = $this->db->fetch_object($resql))
3638
			{
3639
			    $unitLabel = $res->label;
3640
			    if (! empty($langs->tab_translate['unit'.$res->code]))	// check if Translation is available before
3641
			    {
3642
			        $unitLabel = $langs->trans('unit'.$res->code)!=$res->label?$langs->trans('unit'.$res->code):$res->label;
3643
			    }
3644
3645
				if ($selected == $res->rowid)
3646
				{
3647
				    $return.='<option value="'.$res->rowid.'" selected>'.$unitLabel.'</option>';
3648
				}
3649
				else
3650
				{
3651
				    $return.='<option value="'.$res->rowid.'">'.$unitLabel.'</option>';
3652
				}
3653
			}
3654
			$return.='</select>';
3655
		}
3656
		return $return;
3657
	}
3658
3659
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3660
	/**
3661
	 *  Return a HTML select list of bank accounts
3662
	 *
3663
	 *  @param	string	$selected           Id account pre-selected
3664
	 *  @param  string	$htmlname           Name of select zone
3665
	 *  @param  int		$statut             Status of searched accounts (0=open, 1=closed, 2=both)
3666
	 *  @param  string	$filtre             To filter list
3667
	 *  @param  int		$useempty           1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries.
3668
	 *  @param  string	$moreattrib         To add more attribute on select
3669
	 *  @param	int		$showcurrency		Show currency in label
3670
	 *  @param	string	$morecss			More CSS
3671
	 * 	@return	int							<0 if error, Num of bank account found if OK (0, 1, 2, ...)
3672
	 */
3673
    public function select_comptes($selected = '', $htmlname = 'accountid', $statut = 0, $filtre = '', $useempty = 0, $moreattrib = '', $showcurrency = 0, $morecss = '')
3674
	{
3675
        // phpcs:enable
3676
		global $langs, $conf;
3677
3678
		$langs->load("admin");
3679
		$num = 0;
3680
3681
		$sql = "SELECT rowid, label, bank, clos as status, currency_code";
3682
		$sql.= " FROM ".MAIN_DB_PREFIX."bank_account";
3683
		$sql.= " WHERE entity IN (".getEntity('bank_account').")";
3684
		if ($statut != 2) $sql.= " AND clos = '".$statut."'";
3685
		if ($filtre) $sql.=" AND ".$filtre;
3686
		$sql.= " ORDER BY label";
3687
3688
		dol_syslog(get_class($this)."::select_comptes", LOG_DEBUG);
3689
		$result = $this->db->query($sql);
3690
		if ($result)
3691
		{
3692
			$num = $this->db->num_rows($result);
3693
			$i = 0;
3694
			if ($num)
3695
			{
3696
				print '<select id="select'.$htmlname.'" class="flat selectbankaccount'.($morecss?' '.$morecss:'').'" name="'.$htmlname.'"'.($moreattrib?' '.$moreattrib:'').'>';
3697
				if ($useempty == 1 || ($useempty == 2 && $num > 1))
3698
				{
3699
					print '<option value="-1">&nbsp;</option>';
3700
				}
3701
3702
				while ($i < $num)
3703
				{
3704
					$obj = $this->db->fetch_object($result);
3705
					if ($selected == $obj->rowid)
3706
					{
3707
						print '<option value="'.$obj->rowid.'" selected>';
3708
					}
3709
					else
3710
					{
3711
						print '<option value="'.$obj->rowid.'">';
3712
					}
3713
					print trim($obj->label);
3714
					if ($showcurrency) print ' ('.$obj->currency_code.')';
3715
					if ($statut == 2 && $obj->status == 1) print ' ('.$langs->trans("Closed").')';
3716
					print '</option>';
3717
					$i++;
3718
				}
3719
				print "</select>";
3720
			}
3721
			else
3722
			{
3723
				if ($statut == 0) print '<span class="opacitymedium">'.$langs->trans("NoActiveBankAccountDefined").'</span>';
3724
				else print '<span class="opacitymedium">'.$langs->trans("NoBankAccountFound").'</span>';
3725
			}
3726
		}
3727
		else {
3728
			dol_print_error($this->db);
3729
		}
3730
3731
		return $num;
3732
	}
3733
3734
	/**
3735
	 *  Return a HTML select list of establishment
3736
	 *
3737
	 *  @param	string	$selected           Id establishment pre-selected
3738
	 *  @param  string	$htmlname           Name of select zone
3739
	 *  @param  int		$statut             Status of searched establishment (0=open, 1=closed, 2=both)
3740
	 *  @param  string	$filtre             To filter list
3741
	 *  @param  int		$useempty           1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries.
3742
	 *  @param  string	$moreattrib         To add more attribute on select
3743
	 * 	@return	int							<0 if error, Num of establishment found if OK (0, 1, 2, ...)
3744
	 */
3745
	public function selectEstablishments($selected = '', $htmlname = 'entity', $statut = 0, $filtre = '', $useempty = 0, $moreattrib = '')
3746
	{
3747
        // phpcs:enable
3748
		global $langs, $conf;
3749
3750
		$langs->load("admin");
3751
		$num = 0;
3752
3753
		$sql = "SELECT rowid, name, fk_country, status, entity";
3754
		$sql.= " FROM ".MAIN_DB_PREFIX."establishment";
3755
		$sql.= " WHERE 1=1";
3756
		if ($statut != 2) $sql.= " AND status = '".$statut."'";
3757
		if ($filtre) $sql.=" AND ".$filtre;
3758
		$sql.= " ORDER BY name";
3759
3760
		dol_syslog(get_class($this)."::select_establishment", LOG_DEBUG);
3761
		$result = $this->db->query($sql);
3762
		if ($result)
3763
		{
3764
			$num = $this->db->num_rows($result);
3765
			$i = 0;
3766
			if ($num)
3767
			{
3768
				print '<select id="select'.$htmlname.'" class="flat selectestablishment" name="'.$htmlname.'"'.($moreattrib?' '.$moreattrib:'').'>';
3769
				if ($useempty == 1 || ($useempty == 2 && $num > 1))
3770
				{
3771
					print '<option value="-1">&nbsp;</option>';
3772
				}
3773
3774
				while ($i < $num)
3775
				{
3776
					$obj = $this->db->fetch_object($result);
3777
					if ($selected == $obj->rowid)
3778
					{
3779
						print '<option value="'.$obj->rowid.'" selected>';
3780
					}
3781
					else
3782
					{
3783
						print '<option value="'.$obj->rowid.'">';
3784
					}
3785
					print trim($obj->name);
3786
					if ($statut == 2 && $obj->status == 1) print ' ('.$langs->trans("Closed").')';
3787
					print '</option>';
3788
					$i++;
3789
				}
3790
				print "</select>";
3791
			}
3792
			else
3793
			{
3794
				if ($statut == 0) print '<span class="opacitymedium">'.$langs->trans("NoActiveEstablishmentDefined").'</span>';
3795
				else print '<span class="opacitymedium">'.$langs->trans("NoEstablishmentFound").'</span>';
3796
			}
3797
		}
3798
		else {
3799
			dol_print_error($this->db);
3800
		}
3801
	}
3802
3803
	/**
3804
	 *    Display form to select bank account
3805
	 *
3806
	 *    @param	string	$page        Page
3807
	 *    @param    int		$selected    Id of bank account
3808
	 *    @param    string	$htmlname    Name of select html field
3809
	 *    @param    int		$addempty    1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries.
3810
	 *    @return	void
3811
	 */
3812
    public function formSelectAccount($page, $selected = '', $htmlname = 'fk_account', $addempty = 0)
3813
	{
3814
		global $langs;
3815
		if ($htmlname != "none") {
3816
			print '<form method="POST" action="'.$page.'">';
3817
			print '<input type="hidden" name="action" value="setbankaccount">';
3818
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
3819
			$nbaccountfound = $this->select_comptes($selected, $htmlname, 0, '', $addempty);
3820
			if ($nbaccountfound > 0) print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
3821
			print '</form>';
3822
		} else {
3823
3824
			$langs->load('banks');
3825
3826
			if ($selected) {
3827
				require_once DOL_DOCUMENT_ROOT .'/compta/bank/class/account.class.php';
3828
				$bankstatic=new Account($this->db);
3829
				$result = $bankstatic->fetch($selected);
3830
				if ($result) print $bankstatic->getNomUrl(1);
3831
			} else {
3832
				print "&nbsp;";
3833
			}
3834
		}
3835
	}
3836
3837
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3838
	/**
3839
	 *    Return list of categories having choosed type
3840
	 *
3841
	 *    @param	string|int	            $type				Type of category ('customer', 'supplier', 'contact', 'product', 'member'). Old mode (0, 1, 2, ...) is deprecated.
3842
	 *    @param    string		            $selected    		Id of category preselected or 'auto' (autoselect category if there is only one element)
3843
	 *    @param    string		            $htmlname			HTML field name
3844
	 *    @param    int			            $maxlength      	Maximum length for labels
3845
     *    @param    int|string|array    	$markafterid        Keep only or removed all categories including the leaf $markafterid in category tree (exclude) or Keep only of category is inside the leaf starting with this id.
3846
     *                                                          $markafterid can be an :
3847
     *                                                          - int (id of category)
3848
     *                                                          - string (categories ids seprated by comma)
3849
     *                                                          - array (list of categories ids)
3850
	 *    @param	int			            $outputmode			0=HTML select string, 1=Array
3851
     *    @param	int			            $include			[=0] Removed or 1=Keep only
3852
	 *    @return	string
3853
	 *    @see select_categories()
3854
	 */
3855
    public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $markafterid = 0, $outputmode = 0, $include = 0)
3856
	{
3857
        // phpcs:enable
3858
		global $conf, $langs;
3859
		$langs->load("categories");
3860
3861
		include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
3862
3863
		// For backward compatibility
3864
		if (is_numeric($type))
3865
		{
3866
			dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING);
3867
		}
3868
3869
		if ($type === Categorie::TYPE_BANK_LINE)
3870
		{
3871
			// TODO Move this into common category feature
3872
			$categids=array();
3873
			$sql = "SELECT c.label, c.rowid";
3874
			$sql.= " FROM ".MAIN_DB_PREFIX."bank_categ as c";
3875
			$sql.= " WHERE entity = ".$conf->entity;
3876
			$sql.= " ORDER BY c.label";
3877
			$result = $this->db->query($sql);
3878
			if ($result)
3879
			{
3880
				$num = $this->db->num_rows($result);
3881
				$i = 0;
3882
				while ($i < $num)
3883
				{
3884
					$objp = $this->db->fetch_object($result);
3885
					if ($objp) $cate_arbo[$objp->rowid]=array('id'=>$objp->rowid, 'fulllabel'=>$objp->label);
3886
					$i++;
3887
				}
3888
				$this->db->free($result);
3889
			}
3890
			else dol_print_error($this->db);
3891
		}
3892
		else
3893
		{
3894
			$cat = new Categorie($this->db);
3895
            $cate_arbo = $cat->get_full_arbo($type, $markafterid, $include);
3896
		}
3897
3898
		$output = '<select class="flat" name="'.$htmlname.'" id="'.$htmlname.'">';
3899
		$outarray=array();
3900
		if (is_array($cate_arbo))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $cate_arbo does not seem to be defined for all execution paths leading up to this point.
Loading history...
3901
		{
3902
			if (! count($cate_arbo)) $output.= '<option value="-1" disabled>'.$langs->trans("NoCategoriesDefined").'</option>';
3903
			else
3904
			{
3905
				$output.= '<option value="-1">&nbsp;</option>';
3906
				foreach($cate_arbo as $key => $value)
3907
				{
3908
					if ($cate_arbo[$key]['id'] == $selected || ($selected == 'auto' && count($cate_arbo) == 1))
3909
					{
3910
						$add = 'selected ';
3911
					}
3912
					else
3913
					{
3914
						$add = '';
3915
					}
3916
					$output.= '<option '.$add.'value="'.$cate_arbo[$key]['id'].'">'.dol_trunc($cate_arbo[$key]['fulllabel'], $maxlength, 'middle').'</option>';
3917
3918
					$outarray[$cate_arbo[$key]['id']] = $cate_arbo[$key]['fulllabel'];
3919
				}
3920
			}
3921
		}
3922
		$output.= '</select>';
3923
		$output.= "\n";
3924
3925
		if ($outputmode) return $outarray;
3926
		return $output;
3927
	}
3928
3929
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3930
	/**
3931
	 *     Show a confirmation HTML form or AJAX popup
3932
	 *
3933
	 *     @param	string		$page        	   	Url of page to call if confirmation is OK
3934
	 *     @param	string		$title       	   	Title
3935
	 *     @param	string		$question    	   	Question
3936
	 *     @param 	string		$action      	   	Action
3937
	 *	   @param	array		$formquestion	   	An array with forms complementary inputs
3938
	 * 	   @param	string		$selectedchoice		"" or "no" or "yes"
3939
	 * 	   @param	int			$useajax		   	0=No, 1=Yes, 2=Yes but submit page with &confirm=no if choice is No, 'xxx'=preoutput confirm box with div id=dialog-confirm-xxx
3940
	 *     @param	int			$height          	Force height of box
3941
	 *     @param	int			$width				Force width of box
3942
	 *     @return 	void
3943
	 *     @deprecated
3944
	 *     @see formconfirm()
3945
	 */
3946
    public function form_confirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = "", $useajax = 0, $height = 170, $width = 500)
3947
	{
3948
        // phpcs:enable
3949
        dol_syslog(__METHOD__ . ': using form_confirm is deprecated. Use formconfim instead.', LOG_WARNING);
3950
		print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width);
3951
	}
3952
3953
	/**
3954
	 *     Show a confirmation HTML form or AJAX popup.
3955
	 *     Easiest way to use this is with useajax=1.
3956
	 *     If you use useajax='xxx', you must also add jquery code to trigger opening of box (with correct parameters)
3957
	 *     just after calling this method. For example:
3958
	 *       print '<script type="text/javascript">'."\n";
3959
	 *       print 'jQuery(document).ready(function() {'."\n";
3960
	 *       print 'jQuery(".xxxlink").click(function(e) { jQuery("#aparamid").val(jQuery(this).attr("rel")); jQuery("#dialog-confirm-xxx").dialog("open"); return false; });'."\n";
3961
	 *       print '});'."\n";
3962
	 *       print '</script>'."\n";
3963
	 *
3964
	 *     @param  	string		$page        	   	Url of page to call if confirmation is OK. Can contains parameters (param 'action' and 'confirm' will be reformated)
3965
	 *     @param	string		$title       	   	Title
3966
	 *     @param	string		$question    	   	Question
3967
	 *     @param 	string		$action      	   	Action
3968
	 *	   @param  	array		$formquestion	   	An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , ))
3969
	 *												type can be 'hidden', 'text', 'password', 'checkbox', 'radio', 'date', 'morecss', ...
3970
	 * 	   @param  	string		$selectedchoice  	'' or 'no', or 'yes' or '1' or '0'
3971
	 * 	   @param  	int			$useajax		   	0=No, 1=Yes, 2=Yes but submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx
3972
	 *     @param  	int			$height          	Force height of box
3973
	 *     @param	int			$width				Force width of box ('999' or '90%'). Ignored and forced to 90% on smartphones.
3974
	 *     @param	int			$disableformtag		1=Disable form tag. Can be used if we are already inside a <form> section.
3975
	 *     @return 	string      	    			HTML ajax code if a confirm ajax popup is required, Pure HTML code if it's an html form
3976
	 */
3977
    public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 210, $width = 500, $disableformtag = 0)
3978
	{
3979
		global $langs,$conf;
3980
		global $useglobalvars;
3981
3982
		$more='<!-- formconfirm -->';
3983
		$formconfirm='';
3984
		$inputok=array();
3985
		$inputko=array();
3986
3987
		// Clean parameters
3988
		$newselectedchoice=empty($selectedchoice)?"no":$selectedchoice;
3989
		if ($conf->browser->layout == 'phone') $width='95%';
3990
3991
		if (is_array($formquestion) && ! empty($formquestion))
3992
		{
3993
			// First add hidden fields and value
3994
			foreach ($formquestion as $key => $input)
3995
			{
3996
				if (is_array($input) && ! empty($input))
3997
				{
3998
					if ($input['type'] == 'hidden')
3999
					{
4000
						$more.='<input type="hidden" id="'.$input['name'].'" name="'.$input['name'].'" value="'.dol_escape_htmltag($input['value']).'">'."\n";
4001
					}
4002
				}
4003
			}
4004
4005
			// Now add questions
4006
			$more.='<table class="paddingtopbottomonly centpercent">'."\n";
4007
			if (! empty($formquestion['text'])) $more.='<tr><td colspan="2">'.$formquestion['text'].'</td></tr>'."\n";
4008
			foreach ($formquestion as $key => $input)
4009
			{
4010
				if (is_array($input) && ! empty($input))
4011
				{
4012
					$size=(! empty($input['size'])?' size="'.$input['size'].'"':'');
4013
					$moreattr=(! empty($input['moreattr'])?' '.$input['moreattr']:'');
4014
					$morecss=(! empty($input['morecss'])?' '.$input['morecss']:'');
4015
4016
					if ($input['type'] == 'text')
4017
					{
4018
						$more.='<tr><td'.(empty($input['tdclass'])?'':(' class="'.$input['tdclass'].'"')).'>'.$input['label'].'</td><td class="left"><input type="text" class="flat'.$morecss.'" id="'.$input['name'].'" name="'.$input['name'].'"'.$size.' value="'.$input['value'].'"'.$moreattr.' /></td></tr>'."\n";
4019
					}
4020
					elseif ($input['type'] == 'password')
4021
					{
4022
						$more.='<tr><td'.(empty($input['tdclass'])?'':(' class="'.$input['tdclass'].'"')).'>'.$input['label'].'</td><td class="left"><input type="password" class="flat'.$morecss.'" id="'.$input['name'].'" name="'.$input['name'].'"'.$size.' value="'.$input['value'].'"'.$moreattr.' /></td></tr>'."\n";
4023
					}
4024
					elseif ($input['type'] == 'select')
4025
					{
4026
						$more.='<tr><td'.(empty($input['tdclass'])?'':(' class="'.$input['tdclass'].'"')).'>';
4027
						if (! empty($input['label'])) $more.=$input['label'].'</td><td class="tdtop left">';
4028
						$more.=$this->selectarray($input['name'], $input['values'], $input['default'], 1, 0, 0, $moreattr, 0, 0, 0, '', $morecss);
4029
						$more.='</td></tr>'."\n";
4030
					}
4031
					elseif ($input['type'] == 'checkbox')
4032
					{
4033
						$more.='<tr>';
4034
						$more.='<td'.(empty($input['tdclass'])?'':(' class="'.$input['tdclass'].'"')).'>'.$input['label'].' </td><td class="left">';
4035
						$more.='<input type="checkbox" class="flat'.$morecss.'" id="'.$input['name'].'" name="'.$input['name'].'"'.$moreattr;
4036
						if (! is_bool($input['value']) && $input['value'] != 'false' && $input['value'] != '0') $more.=' checked';
4037
						if (is_bool($input['value']) && $input['value']) $more.=' checked';
4038
						if (isset($input['disabled'])) $more.=' disabled';
4039
						$more.=' /></td>';
4040
						$more.='</tr>'."\n";
4041
					}
4042
					elseif ($input['type'] == 'radio')
4043
					{
4044
						$i=0;
4045
						foreach($input['values'] as $selkey => $selval)
4046
						{
4047
							$more.='<tr>';
4048
							if ($i==0) $more.='<td'.(empty($input['tdclass'])?' class="tdtop"':(' class="tdtop '.$input['tdclass'].'"')).'>'.$input['label'].'</td>';
4049
							else $more.='<td'.(empty($input['tdclass'])?'':(' class="'.$input['tdclass'].'"')).'>&nbsp;</td>';
4050
							$more.='<td><input type="radio" class="flat'.$morecss.'" id="'.$input['name'].'" name="'.$input['name'].'" value="'.$selkey.'"'.$moreattr;
4051
							if ($input['disabled']) $more.=' disabled';
4052
							$more.=' /> ';
4053
							$more.=$selval;
4054
							$more.='</td></tr>'."\n";
4055
							$i++;
4056
						}
4057
					}
4058
					elseif ($input['type'] == 'date')
4059
					{
4060
						$more.='<tr><td'.(empty($input['tdclass'])?'':(' class="'.$input['tdclass'].'"')).'>'.$input['label'].'</td>';
4061
						$more.='<td class="left">';
4062
						$more.=$this->selectDate($input['value'], $input['name'], 0, 0, 0, '', 1, 0);
4063
						$more.='</td></tr>'."\n";
4064
						$formquestion[] = array('name'=>$input['name'].'day');
4065
						$formquestion[] = array('name'=>$input['name'].'month');
4066
						$formquestion[] = array('name'=>$input['name'].'year');
4067
						$formquestion[] = array('name'=>$input['name'].'hour');
4068
						$formquestion[] = array('name'=>$input['name'].'min');
4069
					}
4070
					elseif ($input['type'] == 'other')
4071
					{
4072
						$more.='<tr><td'.(empty($input['tdclass'])?'':(' class="'.$input['tdclass'].'"')).'>';
4073
						if (! empty($input['label'])) $more.=$input['label'].'</td><td class="left">';
4074
						$more.=$input['value'];
4075
						$more.='</td></tr>'."\n";
4076
					}
4077
4078
					elseif ($input['type'] == 'onecolumn')
4079
					{
4080
						$more.='<tr><td colspan="2" class="left">';
4081
						$more.=$input['value'];
4082
						$more.='</td></tr>'."\n";
4083
					}
4084
				}
4085
			}
4086
			$more.='</table>'."\n";
4087
		}
4088
4089
		// JQUI method dialog is broken with jmobile, we use standard HTML.
4090
		// 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
4091
		// See page product/card.php for example
4092
		if (! empty($conf->dol_use_jmobile)) $useajax=0;
4093
		if (empty($conf->use_javascript_ajax)) $useajax=0;
4094
4095
		if ($useajax)
4096
		{
4097
			$autoOpen=true;
4098
			$dialogconfirm='dialog-confirm';
4099
			$button='';
4100
			if (! is_numeric($useajax))
1 ignored issue
show
introduced by
The condition is_numeric($useajax) is always true.
Loading history...
4101
			{
4102
				$button=$useajax;
4103
				$useajax=1;
4104
				$autoOpen=false;
4105
				$dialogconfirm.='-'.$button;
4106
			}
4107
			$pageyes=$page.(preg_match('/\?/', $page)?'&':'?').'action='.$action.'&confirm=yes';
4108
			$pageno=($useajax == 2 ? $page.(preg_match('/\?/', $page)?'&':'?').'confirm=no':'');
4109
			// Add input fields into list of fields to read during submit (inputok and inputko)
4110
			if (is_array($formquestion))
4111
			{
4112
				foreach ($formquestion as $key => $input)
4113
				{
4114
					//print "xx ".$key." rr ".is_array($input)."<br>\n";
4115
					if (is_array($input) && isset($input['name'])) array_push($inputok, $input['name']);
4116
					if (isset($input['inputko']) && $input['inputko'] == 1) array_push($inputko, $input['name']);
4117
				}
4118
			}
4119
			// Show JQuery confirm box. Note that global var $useglobalvars is used inside this template
4120
			$formconfirm.= '<div id="'.$dialogconfirm.'" title="'.dol_escape_htmltag($title).'" style="display: none;">';
4121
			if (! empty($more)) {
4122
				$formconfirm.= '<div class="confirmquestions">'.$more.'</div>';
4123
			}
4124
			$formconfirm.= ($question ? '<div class="confirmmessage">'.img_help('', '').' '.$question . '</div>': '');
4125
			$formconfirm.= '</div>'."\n";
4126
4127
			$formconfirm.= "\n<!-- begin ajax formconfirm page=".$page." -->\n";
4128
			$formconfirm.= '<script type="text/javascript">'."\n";
4129
			$formconfirm.= 'jQuery(document).ready(function() {
4130
            $(function() {
4131
            	$( "#'.$dialogconfirm.'" ).dialog(
4132
            	{
4133
                    autoOpen: '.($autoOpen ? "true" : "false").',';
1 ignored issue
show
introduced by
The condition $autoOpen is always true.
Loading history...
4134
			if ($newselectedchoice == 'no')
4135
			{
4136
				$formconfirm.='
4137
						open: function() {
4138
            				$(this).parent().find("button.ui-button:eq(2)").focus();
4139
						},';
4140
			}
4141
			$formconfirm.='
4142
                    resizable: false,
4143
                    height: "'.$height.'",
4144
                    width: "'.$width.'",
4145
                    modal: true,
4146
                    closeOnEscape: false,
4147
                    buttons: {
4148
                        "'.dol_escape_js($langs->transnoentities("Yes")).'": function() {
4149
                        	var options = "&token='.urlencode($_SESSION['newtoken']).'";
4150
                        	var inputok = '.json_encode($inputok).';
4151
                         	var pageyes = "'.dol_escape_js(! empty($pageyes)?$pageyes:'').'";
4152
                         	if (inputok.length>0) {
4153
                         		$.each(inputok, function(i, inputname) {
4154
                         			var more = "";
4155
                         			if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
4156
                         		    if ($("#" + inputname).attr("type") == "radio") { more = ":checked"; }
4157
                         			var inputvalue = $("#" + inputname + more).val();
4158
                         			if (typeof inputvalue == "undefined") { inputvalue=""; }
4159
                         			options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
4160
                         		});
4161
                         	}
4162
                         	var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "") + options;
4163
                         	//alert(urljump);
4164
            				if (pageyes.length > 0) { location.href = urljump; }
4165
                            $(this).dialog("close");
4166
                        },
4167
                        "'.dol_escape_js($langs->transnoentities("No")).'": function() {
4168
                        	var options = "&token='.urlencode($_SESSION['newtoken']).'";
4169
                         	var inputko = '.json_encode($inputko).';
4170
                         	var pageno="'.dol_escape_js(! empty($pageno)?$pageno:'').'";
4171
                         	if (inputko.length>0) {
4172
                         		$.each(inputko, function(i, inputname) {
4173
                         			var more = "";
4174
                         			if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
4175
                         			var inputvalue = $("#" + inputname + more).val();
4176
                         			if (typeof inputvalue == "undefined") { inputvalue=""; }
4177
                         			options += "&" + inputname + "=" + encodeURIComponent(inputvalue);
4178
                         		});
4179
                         	}
4180
                         	var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "") + options;
4181
                         	//alert(urljump);
4182
            				if (pageno.length > 0) { location.href = urljump; }
4183
                            $(this).dialog("close");
4184
                        }
4185
                    }
4186
                }
4187
                );
4188
4189
            	var button = "'.$button.'";
4190
            	if (button.length > 0) {
4191
                	$( "#" + button ).click(function() {
4192
                		$("#'.$dialogconfirm.'").dialog("open");
4193
        			});
4194
                }
4195
            });
4196
            });
4197
            </script>';
4198
			$formconfirm.= "<!-- end ajax formconfirm -->\n";
4199
		}
4200
		else
4201
		{
4202
			$formconfirm.= "\n<!-- begin formconfirm page=".$page." -->\n";
4203
4204
			if (empty($disableformtag)) $formconfirm.= '<form method="POST" action="'.$page.'" class="notoptoleftroright">'."\n";
4205
4206
			$formconfirm.= '<input type="hidden" name="action" value="'.$action.'">'."\n";
4207
			$formconfirm.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'."\n";
4208
4209
			$formconfirm.= '<table class="valid centpercent">'."\n";
4210
4211
			// Line title
4212
			$formconfirm.= '<tr class="validtitre"><td class="validtitre" colspan="3">'.img_picto('', 'recent').' '.$title.'</td></tr>'."\n";
4213
4214
			// Line form fields
4215
			if ($more)
4216
			{
4217
				$formconfirm.='<tr class="valid"><td class="valid" colspan="3">'."\n";
4218
				$formconfirm.=$more;
4219
				$formconfirm.='</td></tr>'."\n";
4220
			}
4221
4222
			// Line with question
4223
			$formconfirm.= '<tr class="valid">';
4224
			$formconfirm.= '<td class="valid">'.$question.'</td>';
4225
			$formconfirm.= '<td class="valid">';
4226
			$formconfirm.= $this->selectyesno("confirm", $newselectedchoice);
4227
			$formconfirm.= '</td>';
4228
			$formconfirm.= '<td class="valid center"><input class="button valignmiddle" type="submit" onclick="this.disabled=\'disabled\' value="'.$langs->trans("Validate").'"></td>';
4229
			$formconfirm.= '</tr>'."\n";
4230
4231
			$formconfirm.= '</table>'."\n";
4232
4233
			if (empty($disableformtag)) $formconfirm.= "</form>\n";
4234
			$formconfirm.= '<br>';
4235
4236
			$formconfirm.= "<!-- end formconfirm -->\n";
4237
		}
4238
4239
		return $formconfirm;
4240
	}
4241
4242
4243
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4244
	/**
4245
	 *    Show a form to select a project
4246
	 *
4247
	 *    @param	int		$page        		Page
4248
	 *    @param	int		$socid       		Id third party (-1=all, 0=only projects not linked to a third party, id=projects not linked or linked to third party id)
4249
	 *    @param    int		$selected    		Id pre-selected project
4250
	 *    @param    string	$htmlname    		Name of select field
4251
	 *    @param	int		$discard_closed		Discard closed projects (0=Keep,1=hide completely except $selected,2=Disable)
4252
	 *    @param	int		$maxlength			Max length
4253
	 *    @param	int		$forcefocus			Force focus on field (works with javascript only)
4254
	 *    @param    int     $nooutput           No print is done. String is returned.
4255
	 *    @return	string                      Return html content
4256
	 */
4257
    public function form_project($page, $socid, $selected = '', $htmlname = 'projectid', $discard_closed = 0, $maxlength = 20, $forcefocus = 0, $nooutput = 0)
4258
	{
4259
        // phpcs:enable
4260
		global $langs;
4261
4262
		require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
4263
		require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
4264
4265
		$out='';
4266
4267
		$formproject=new FormProjets($this->db);
4268
4269
		$langs->load("project");
4270
		if ($htmlname != "none")
4271
		{
4272
			$out.="\n";
4273
			$out.='<form method="post" action="'.$page.'">';
4274
			$out.='<input type="hidden" name="action" value="classin">';
4275
			$out.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4276
			$out.=$formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1);
4277
			$out.='<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
4278
			$out.='</form>';
4279
		}
4280
		else
4281
		{
4282
			if ($selected)
4283
			{
4284
				$projet = new Project($this->db);
4285
				$projet->fetch($selected);
4286
				//print '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$selected.'">'.$projet->title.'</a>';
4287
				$out.=$projet->getNomUrl(0, '', 1);
4288
			}
4289
			else
4290
			{
4291
				$out.="&nbsp;";
4292
			}
4293
		}
4294
4295
		if (empty($nooutput))
4296
		{
4297
			print $out;
4298
			return '';
4299
		}
4300
		return $out;
4301
	}
4302
4303
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4304
	/**
4305
	 *	Show a form to select payment conditions
4306
	 *
4307
	 *  @param	int		$page        	Page
4308
	 *  @param  string	$selected    	Id condition pre-selectionne
4309
	 *  @param  string	$htmlname    	Name of select html field
4310
	 *	@param	int		$addempty		Add empty entry
4311
	 *  @return	void
4312
	 */
4313
    public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0)
4314
	{
4315
        // phpcs:enable
4316
		global $langs;
4317
		if ($htmlname != "none")
4318
		{
4319
			print '<form method="post" action="'.$page.'">';
4320
			print '<input type="hidden" name="action" value="setconditions">';
4321
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4322
			$this->select_conditions_paiements($selected, $htmlname, -1, $addempty);
4323
			print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4324
			print '</form>';
4325
		}
4326
		else
4327
		{
4328
			if ($selected)
4329
			{
4330
				$this->load_cache_conditions_paiements();
4331
				print $this->cache_conditions_paiements[$selected]['label'];
4332
			} else {
4333
				print "&nbsp;";
4334
			}
4335
		}
4336
	}
4337
4338
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4339
	/**
4340
	 *  Show a form to select a delivery delay
4341
	 *
4342
	 *  @param  int		$page        	Page
4343
	 *  @param  string	$selected    	Id condition pre-selectionne
4344
	 *  @param  string	$htmlname    	Name of select html field
4345
	 *	@param	int		$addempty		Ajoute entree vide
4346
	 *  @return	void
4347
	 */
4348
    public function form_availability($page, $selected = '', $htmlname = 'availability', $addempty = 0)
4349
	{
4350
        // phpcs:enable
4351
		global $langs;
4352
		if ($htmlname != "none")
4353
		{
4354
			print '<form method="post" action="'.$page.'">';
4355
			print '<input type="hidden" name="action" value="setavailability">';
4356
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4357
			$this->selectAvailabilityDelay($selected, $htmlname, -1, $addempty);
4358
			print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
4359
			print '</form>';
4360
		}
4361
		else
4362
		{
4363
			if ($selected)
4364
			{
4365
				$this->load_cache_availability();
4366
				print $this->cache_availability[$selected]['label'];
4367
			} else {
4368
				print "&nbsp;";
4369
			}
4370
		}
4371
	}
4372
4373
	/**
4374
	 *  Output HTML form to select list of input reason (events that triggered an object creation, like after sending an emailing, making an advert, ...)
4375
	 *  List found into table c_input_reason loaded by loadCacheInputReason
4376
	 *
4377
	 *  @param  string	$page        	Page
4378
	 *  @param  string	$selected    	Id condition pre-selectionne
4379
	 *  @param  string	$htmlname    	Name of select html field
4380
	 *  @param	int		$addempty		Add empty entry
4381
	 *  @return	void
4382
     */
4383
    public function formInputReason($page, $selected = '', $htmlname = 'demandreason', $addempty = 0)
4384
    {
4385
		global $langs;
4386
		if ($htmlname != "none")
4387
		{
4388
			print '<form method="post" action="'.$page.'">';
4389
			print '<input type="hidden" name="action" value="setdemandreason">';
4390
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4391
			$this->selectInputReason($selected, $htmlname, -1, $addempty);
4392
			print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
4393
			print '</form>';
4394
		}
4395
		else
4396
		{
4397
			if ($selected)
4398
			{
4399
				$this->loadCacheInputReason();
4400
				foreach ($this->cache_demand_reason as $key => $val)
4401
				{
4402
					if ($val['id'] == $selected)
4403
					{
4404
						print $val['label'];
4405
						break;
4406
					}
4407
				}
4408
			} else {
4409
				print "&nbsp;";
4410
			}
4411
		}
4412
	}
4413
4414
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4415
	/**
4416
	 *    Show a form + html select a date
4417
	 *
4418
	 *    @param	string		$page        	Page
4419
	 *    @param	string		$selected    	Date preselected
4420
	 *    @param    string		$htmlname    	Html name of date input fields or 'none'
4421
	 *    @param    int			$displayhour 	Display hour selector
4422
	 *    @param    int			$displaymin		Display minutes selector
4423
	 *    @param	int			$nooutput		1=No print output, return string
4424
	 *    @return	string
4425
	 *    @see		selectDate()
4426
	 */
4427
    public function form_date($page, $selected, $htmlname, $displayhour = 0, $displaymin = 0, $nooutput = 0)
4428
	{
4429
        // phpcs:enable
4430
		global $langs;
4431
4432
		$ret='';
4433
4434
		if ($htmlname != "none")
4435
		{
4436
			$ret.='<form method="post" action="'.$page.'" name="form'.$htmlname.'">';
4437
			$ret.='<input type="hidden" name="action" value="set'.$htmlname.'">';
4438
			$ret.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4439
			$ret.='<table class="nobordernopadding" cellpadding="0" cellspacing="0">';
4440
			$ret.='<tr><td>';
4441
			$ret.=$this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form'.$htmlname, 1, 0);
4442
			$ret.='</td>';
4443
			$ret.='<td class="left"><input type="submit" class="button" value="'.$langs->trans("Modify").'"></td>';
4444
			$ret.='</tr></table></form>';
4445
		}
4446
		else
4447
		{
4448
			if ($displayhour) $ret.=dol_print_date($selected, 'dayhour');
4449
			else $ret.=dol_print_date($selected, 'day');
4450
		}
4451
4452
		if (empty($nooutput)) print $ret;
4453
		return $ret;
4454
	}
4455
4456
4457
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4458
	/**
4459
	 *  Show a select form to choose a user
4460
	 *
4461
	 *  @param	string	$page        	Page
4462
	 *  @param  string	$selected    	Id of user preselected
4463
	 *  @param  string	$htmlname    	Name of input html field. If 'none', we just output the user link.
4464
	 *  @param  array	$exclude		List of users id to exclude
4465
	 *  @param  array	$include        List of users id to include
4466
	 *  @return	void
4467
	 */
4468
    public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = '', $include = '')
4469
	{
4470
        // phpcs:enable
4471
		global $langs;
4472
4473
		if ($htmlname != "none")
4474
		{
4475
			print '<form method="POST" action="'.$page.'" name="form'.$htmlname.'">';
4476
			print '<input type="hidden" name="action" value="set'.$htmlname.'">';
4477
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4478
			print $this->select_dolusers($selected, $htmlname, 1, $exclude, 0, $include);
4479
			print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4480
			print '</form>';
4481
		}
4482
		else
4483
		{
4484
			if ($selected)
4485
			{
4486
				require_once DOL_DOCUMENT_ROOT .'/user/class/user.class.php';
4487
				$theuser=new User($this->db);
4488
				$theuser->fetch($selected);
4489
				print $theuser->getNomUrl(1);
4490
			} else {
4491
				print "&nbsp;";
4492
			}
4493
		}
4494
	}
4495
4496
4497
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4498
	/**
4499
	 *    Show form with payment mode
4500
	 *
4501
	 *    @param	string	$page        	Page
4502
	 *    @param    int		$selected    	Id mode pre-selectionne
4503
	 *    @param    string	$htmlname    	Name of select html field
4504
	 *    @param  	string	$filtertype		To filter on field type in llx_c_paiement (array('code'=>xx,'label'=>zz))
4505
	 *    @param    int     $active         Active or not, -1 = all
4506
	 *    @param   int     $addempty       1=Add empty entry
4507
	 *    @return	void
4508
	 */
4509
    public function form_modes_reglement($page, $selected = '', $htmlname = 'mode_reglement_id', $filtertype = '', $active = 1, $addempty = 0)
4510
	{
4511
        // phpcs:enable
4512
		global $langs;
4513
		if ($htmlname != "none")
4514
		{
4515
			print '<form method="POST" action="'.$page.'">';
4516
			print '<input type="hidden" name="action" value="setmode">';
4517
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4518
			$this->select_types_paiements($selected, $htmlname, $filtertype, 0, $addempty, 0, 0, $active);
4519
			print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4520
			print '</form>';
4521
		}
4522
		else
4523
		{
4524
			if ($selected)
4525
			{
4526
				$this->load_cache_types_paiements();
4527
				print $this->cache_types_paiements[$selected]['label'];
4528
			} else {
4529
				print "&nbsp;";
4530
			}
4531
		}
4532
	}
4533
4534
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4535
	/**
4536
	 *    Show form with multicurrency code
4537
	 *
4538
	 *    @param	string	$page        	Page
4539
	 *    @param    string	$selected    	code pre-selectionne
4540
	 *    @param    string	$htmlname    	Name of select html field
4541
	 *    @return	void
4542
	 */
4543
    public function form_multicurrency_code($page, $selected = '', $htmlname = 'multicurrency_code')
4544
	{
4545
        // phpcs:enable
4546
		global $langs;
4547
		if ($htmlname != "none")
4548
		{
4549
			print '<form method="POST" action="'.$page.'">';
4550
			print '<input type="hidden" name="action" value="setmulticurrencycode">';
4551
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4552
			print $this->selectMultiCurrency($selected, $htmlname, 0);
4553
			print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4554
			print '</form>';
4555
		}
4556
		else
4557
		{
4558
			dol_include_once('/core/lib/company.lib.php');
4559
			print !empty($selected) ? currency_name($selected, 1) : '&nbsp;';
4560
		}
4561
	}
4562
4563
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4564
	/**
4565
	 *    Show form with multicurrency rate
4566
	 *
4567
	 *    @param	string	$page        	Page
4568
	 *    @param    double	$rate	    	Current rate
4569
	 *    @param    string	$htmlname    	Name of select html field
4570
	 *    @param    string  $currency       Currency code to explain the rate
4571
	 *    @return	void
4572
	 */
4573
    public function form_multicurrency_rate($page, $rate = '', $htmlname = 'multicurrency_tx', $currency = '')
4574
	{
4575
        // phpcs:enable
4576
		global $langs, $mysoc, $conf;
4577
4578
		if ($htmlname != "none")
4579
		{
4580
			print '<form method="POST" action="'.$page.'">';
4581
			print '<input type="hidden" name="action" value="setmulticurrencyrate">';
4582
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4583
			print '<input type="text" name="'.$htmlname.'" value="'.(!empty($rate) ? price($rate) : 1).'" size="10" /> ';
4584
			print '<select name="calculation_mode">';
4585
			print '<option value="1">'.$currency.' > '.$conf->currency.'</option>';
4586
			print '<option value="2">'.$conf->currency.' > '.$currency.'</option>';
4587
			print '</select> ';
4588
			print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4589
			print '</form>';
4590
		}
4591
		else
4592
		{
4593
			if (! empty($rate))
4594
			{
4595
				print price($rate, 1, $langs, 1, 0);
4596
				if ($currency && $rate != 1) print ' &nbsp; ('.price($rate, 1, $langs, 1, 0).' '.$currency.' = 1 '.$conf->currency.')';
4597
			}
4598
			else
4599
			{
4600
				print 1;
4601
			}
4602
		}
4603
	}
4604
4605
4606
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4607
	/**
4608
	 *	Show a select box with available absolute discounts
4609
	 *
4610
	 *  @param  string	$page        	Page URL where form is shown
4611
	 *  @param  int		$selected    	Value pre-selected
4612
	 *	@param  string	$htmlname    	Name of SELECT component. If 'none', not changeable. Example 'remise_id'.
4613
	 *	@param	int		$socid			Third party id
4614
	 * 	@param	float	$amount			Total amount available
4615
	 * 	@param	string	$filter			SQL filter on discounts
4616
	 * 	@param	int		$maxvalue		Max value for lines that can be selected
4617
	 *  @param  string	$more           More string to add
4618
	 *  @param  int     $hidelist       1=Hide list
4619
	 *  @param	int		$discount_type	0 => customer discount, 1 => supplier discount
4620
	 *  @return	void
4621
	 */
4622
    public function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter = '', $maxvalue = 0, $more = '', $hidelist = 0, $discount_type = 0)
4623
	{
4624
        // phpcs:enable
4625
		global $conf,$langs;
4626
		if ($htmlname != "none")
4627
		{
4628
			print '<form method="post" action="'.$page.'">';
4629
			print '<input type="hidden" name="action" value="setabsolutediscount">';
4630
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4631
			print '<div class="inline-block">';
4632
			if(! empty($discount_type)) {
4633
				if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS))
4634
				{
4635
					if (! $filter || $filter=="fk_invoice_supplier_source IS NULL") $translationKey = 'HasAbsoluteDiscountFromSupplier';    // If we want deposit to be substracted to payments only and not to total of final invoice
4636
					else $translationKey = 'HasCreditNoteFromSupplier';
4637
				}
4638
				else
4639
				{
4640
					if (! $filter || $filter=="fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") $translationKey = 'HasAbsoluteDiscountFromSupplier';
4641
					else $translationKey = 'HasCreditNoteFromSupplier';
4642
				}
4643
			} else {
4644
				if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS))
4645
				{
4646
					if (! $filter || $filter=="fk_facture_source IS NULL") $translationKey = 'CompanyHasAbsoluteDiscount';    // If we want deposit to be substracted to payments only and not to total of final invoice
4647
					else $translationKey = 'CompanyHasCreditNote';
4648
				}
4649
				else
4650
				{
4651
					if (! $filter || $filter=="fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") $translationKey = 'CompanyHasAbsoluteDiscount';
4652
					else $translationKey = 'CompanyHasCreditNote';
4653
				}
4654
			}
4655
			print $langs->trans($translationKey, price($amount, 0, $langs, 0, 0, -1, $conf->currency));
4656
			if (empty($hidelist)) print ': ';
4657
			print '</div>';
4658
			if (empty($hidelist))
4659
			{
4660
				print '<div class="inline-block" style="padding-right: 10px">';
4661
				$newfilter = 'discount_type='.intval($discount_type);
4662
				if(! empty($discount_type)) {
4663
					$newfilter.= ' AND fk_invoice_supplier IS NULL AND fk_invoice_supplier_line IS NULL'; // Supplier discounts available
4664
				} else {
4665
					$newfilter.= ' AND fk_facture IS NULL AND fk_facture_line IS NULL'; // Customer discounts available
4666
				}
4667
				if ($filter) $newfilter.=' AND ('.$filter.')';
4668
				$nbqualifiedlines=$this->select_remises($selected, $htmlname, $newfilter, $socid, $maxvalue);
4669
				if ($nbqualifiedlines > 0)
4670
				{
4671
					print ' &nbsp; <input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("UseLine")).'"';
4672
					if(! empty($discount_type) && $filter && $filter != "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')")
4673
						print ' title="'.$langs->trans("UseCreditNoteInInvoicePayment").'"';
4674
					if(empty($discount_type) && $filter && $filter != "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')")
4675
						print ' title="'.$langs->trans("UseCreditNoteInInvoicePayment").'"';
4676
4677
					print '>';
4678
				}
4679
				print '</div>';
4680
			}
4681
			if ($more)
4682
			{
4683
				print '<div class="inline-block">';
4684
				print $more;
4685
				print '</div>';
4686
			}
4687
			print '</form>';
4688
		}
4689
		else
4690
		{
4691
			if ($selected)
4692
			{
4693
				print $selected;
4694
			}
4695
			else
4696
			{
4697
				print "0";
4698
			}
4699
		}
4700
	}
4701
4702
4703
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4704
    /**
4705
     *  Show forms to select a contact
4706
     *
4707
     *  @param	string		$page        	Page
4708
     *  @param	Societe		$societe		Filter on third party
4709
     *  @param    int			$selected    	Id contact pre-selectionne
4710
     *  @param    string		$htmlname    	Name of HTML select. If 'none', we just show contact link.
4711
     *  @return	void
4712
     */
4713
    public function form_contacts($page, $societe, $selected = '', $htmlname = 'contactid')
4714
    {
4715
        // phpcs:enable
4716
		global $langs, $conf;
4717
4718
		if ($htmlname != "none")
4719
		{
4720
			print '<form method="post" action="'.$page.'">';
4721
			print '<input type="hidden" name="action" value="set_contact">';
4722
			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4723
			print '<table class="nobordernopadding" cellpadding="0" cellspacing="0">';
4724
			print '<tr><td>';
4725
			$num=$this->select_contacts($societe->id, $selected, $htmlname);
4726
			if ($num==0)
4727
			{
4728
				$addcontact = (! empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("AddContact") : $langs->trans("AddContactAddress"));
4729
				print '<a href="'.DOL_URL_ROOT.'/contact/card.php?socid='.$societe->id.'&amp;action=create&amp;backtoreferer=1">'.$addcontact.'</a>';
4730
			}
4731
			print '</td>';
4732
			print '<td class="left"><input type="submit" class="button" value="'.$langs->trans("Modify").'"></td>';
4733
			print '</tr></table></form>';
4734
		}
4735
		else
4736
		{
4737
			if ($selected)
4738
			{
4739
				require_once DOL_DOCUMENT_ROOT .'/contact/class/contact.class.php';
4740
				$contact=new Contact($this->db);
4741
				$contact->fetch($selected);
4742
				print $contact->getFullName($langs);
4743
			} else {
4744
				print "&nbsp;";
4745
			}
4746
		}
4747
	}
4748
4749
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4750
	/**
4751
	 *  Output html select to select thirdparty
4752
	 *
4753
	 *  @param	string	$page       	Page
4754
	 *  @param  string	$selected   	Id preselected
4755
	 *  @param  string	$htmlname		Name of HTML select
4756
	 *  @param  string	$filter         optional filters criteras
4757
	 *	@param	int		$showempty		Add an empty field
4758
	 * 	@param	int		$showtype		Show third party type in combolist (customer, prospect or supplier)
4759
	 * 	@param	int		$forcecombo		Force to use combo box
4760
	 *  @param	array	$events			Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
4761
	 *  @param  int     $nooutput       No print output. Return it only.
4762
	 *  @return	void
4763
	 */
4764
    public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0)
4765
	{
4766
        // phpcs:enable
4767
		global $langs;
4768
4769
		$out = '';
4770
		if ($htmlname != "none")
4771
		{
4772
			$out.='<form method="post" action="'.$page.'">';
4773
			$out.= '<input type="hidden" name="action" value="set_thirdparty">';
4774
			$out.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4775
			$out.= $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events);
4776
			$out.= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4777
			$out.= '</form>';
4778
		}
4779
		else
4780
		{
4781
			if ($selected)
4782
			{
4783
				require_once DOL_DOCUMENT_ROOT .'/societe/class/societe.class.php';
4784
				$soc = new Societe($this->db);
4785
				$soc->fetch($selected);
4786
				$out.= $soc->getNomUrl($langs);
4787
			}
4788
			else
4789
			{
4790
				$out.= "&nbsp;";
4791
			}
4792
		}
4793
4794
		if ($nooutput) return $out;
4795
		else print $out;
4796
	}
4797
4798
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4799
	/**
4800
	 *    Retourne la liste des devises, dans la langue de l'utilisateur
4801
	 *
4802
	 *    @param	string	$selected    preselected currency code
4803
	 *    @param    string	$htmlname    name of HTML select list
4804
     *    @deprecated
4805
	 *    @return	void
4806
	 */
4807
    public function select_currency($selected = '', $htmlname = 'currency_id')
4808
	{
4809
        // phpcs:enable
4810
		print $this->selectCurrency($selected, $htmlname);
4811
	}
4812
4813
	/**
4814
	 *  Retourne la liste des devises, dans la langue de l'utilisateur
4815
	 *
4816
	 *  @param	string	$selected    preselected currency code
4817
	 *  @param  string	$htmlname    name of HTML select list
4818
	 *  @param  string  $mode        0 = Add currency symbol into label, 1 = Add 3 letter iso code
4819
	 * 	@return	string
4820
	 */
4821
    public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0)
4822
	{
4823
		global $conf,$langs,$user;
4824
4825
		$langs->loadCacheCurrencies('');
4826
4827
		$out='';
4828
4829
		if ($selected=='euro' || $selected=='euros') $selected='EUR';   // Pour compatibilite
4830
4831
		$out.= '<select class="flat maxwidth200onsmartphone minwidth300" name="'.$htmlname.'" id="'.$htmlname.'">';
4832
		foreach ($langs->cache_currencies as $code_iso => $currency)
4833
		{
4834
			if ($selected && $selected == $code_iso)
4835
			{
4836
				$out.= '<option value="'.$code_iso.'" selected>';
4837
			}
4838
			else
4839
			{
4840
				$out.= '<option value="'.$code_iso.'">';
4841
			}
4842
			$out.= $currency['label'];
4843
			if ($mode == 1)
4844
			{
4845
			    $out.= ' ('.$code_iso.')';
4846
			}
4847
			else
4848
			{
4849
                $out.= ' ('.$langs->getCurrencySymbol($code_iso).')';
4850
			}
4851
			$out.= '</option>';
4852
		}
4853
		$out.= '</select>';
4854
		if ($user->admin) $out.= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
4855
4856
		// Make select dynamic
4857
		include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
4858
		$out .= ajax_combobox($htmlname);
4859
4860
		return $out;
4861
	}
4862
4863
	/**
4864
	 *	Return array of currencies in user language
4865
	 *
4866
	 *  @param	string	$selected    preselected currency code
4867
	 *  @param  string	$htmlname    name of HTML select list
4868
	 *  @param  integer	$useempty    1=Add empty line
4869
	 * 	@return	string
4870
	 */
4871
    public function selectMultiCurrency($selected = '', $htmlname = 'multicurrency_code', $useempty = 0)
4872
	{
4873
		global $db,$conf,$langs,$user;
4874
4875
		$langs->loadCacheCurrencies('');        // Load ->cache_currencies
4876
4877
		$TCurrency = array();
4878
4879
		$sql = 'SELECT code FROM '.MAIN_DB_PREFIX.'multicurrency';
4880
		$sql.= " WHERE entity IN ('".getEntity('mutlicurrency')."')";
4881
		$resql = $db->query($sql);
4882
		if ($resql)
4883
		{
4884
			while ($obj = $db->fetch_object($resql)) $TCurrency[$obj->code] = $obj->code;
4885
		}
4886
4887
		$out='';
4888
		$out.= '<select class="flat" name="'.$htmlname.'" id="'.$htmlname.'">';
4889
		if ($useempty) $out .= '<option value="">&nbsp;</option>';
4890
		// If company current currency not in table, we add it into list. Should always be available.
4891
		if (! in_array($conf->currency, $TCurrency))
4892
		{
4893
			$TCurrency[$conf->currency] = $conf->currency;
4894
		}
4895
		if (count($TCurrency) > 0)
4896
		{
4897
			foreach ($langs->cache_currencies as $code_iso => $currency)
4898
			{
4899
				if (isset($TCurrency[$code_iso]))
4900
				{
4901
					if (!empty($selected) && $selected == $code_iso) $out.= '<option value="'.$code_iso.'" selected="selected">';
4902
					else $out.= '<option value="'.$code_iso.'">';
4903
4904
					$out.= $currency['label'];
4905
					$out.= ' ('.$langs->getCurrencySymbol($code_iso).')';
4906
					$out.= '</option>';
4907
				}
4908
			}
4909
		}
4910
4911
		$out.= '</select>';
4912
		// Make select dynamic
4913
		include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
4914
		$out.= ajax_combobox($htmlname);
4915
4916
		return $out;
4917
	}
4918
4919
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4920
	/**
4921
	 *  Load into the cache vat rates of a country
4922
	 *
4923
	 *  @param	string	$country_code		Country code with quotes ("'CA'", or "'CA,IN,...'")
4924
	 *  @return	int							Nb of loaded lines, 0 if already loaded, <0 if KO
4925
	 */
4926
    public function load_cache_vatrates($country_code)
4927
	{
4928
        // phpcs:enable
4929
		global $langs;
4930
4931
		$num = count($this->cache_vatrates);
4932
		if ($num > 0) return $num;    // Cache already loaded
4933
4934
		dol_syslog(__METHOD__, LOG_DEBUG);
4935
4936
		$sql  = "SELECT DISTINCT t.rowid, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
4937
		$sql.= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
4938
		$sql.= " WHERE t.fk_pays = c.rowid";
4939
		$sql.= " AND t.active > 0";
4940
		$sql.= " AND c.code IN (".$country_code.")";
4941
		$sql.= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC";
4942
4943
		$resql=$this->db->query($sql);
4944
		if ($resql)
4945
		{
4946
			$num = $this->db->num_rows($resql);
4947
			if ($num)
4948
			{
4949
				for ($i = 0; $i < $num; $i++)
4950
				{
4951
					$obj = $this->db->fetch_object($resql);
4952
					$this->cache_vatrates[$i]['rowid']	= $obj->rowid;
4953
					$this->cache_vatrates[$i]['code']	= $obj->code;
4954
					$this->cache_vatrates[$i]['txtva']	= $obj->taux;
4955
					$this->cache_vatrates[$i]['nprtva']	= $obj->recuperableonly;
4956
					$this->cache_vatrates[$i]['localtax1']	    = $obj->localtax1;
4957
					$this->cache_vatrates[$i]['localtax1_type']	= $obj->localtax1_type;
4958
					$this->cache_vatrates[$i]['localtax2']	    = $obj->localtax2;
4959
					$this->cache_vatrates[$i]['localtax2_type']	= $obj->localtax1_type;
4960
4961
					$this->cache_vatrates[$i]['label']	= $obj->taux.'%'.($obj->code?' ('.$obj->code.')':'');   // Label must contains only 0-9 , . % or *
4962
					$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
4963
					$positiverates='';
4964
					if ($obj->taux) $positiverates.=($positiverates?'/':'').$obj->taux;
4965
					if ($obj->localtax1) $positiverates.=($positiverates?'/':'').$obj->localtax1;
4966
					if ($obj->localtax2) $positiverates.=($positiverates?'/':'').$obj->localtax2;
4967
					if (empty($positiverates)) $positiverates='0';
4968
					$this->cache_vatrates[$i]['labelpositiverates'] = $positiverates.($obj->code?' ('.$obj->code.')':'');	// Must never be used as key, only label
4969
				}
4970
4971
				return $num;
4972
			}
4973
			else
4974
			{
4975
				$this->error = '<font class="error">'.$langs->trans("ErrorNoVATRateDefinedForSellerCountry", $country_code).'</font>';
4976
				return -1;
4977
			}
4978
		}
4979
		else
4980
		{
4981
			$this->error = '<font class="error">'.$this->db->error().'</font>';
4982
			return -2;
4983
		}
4984
	}
4985
4986
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4987
	/**
4988
	 *  Output an HTML select vat rate.
4989
	 *  The name of this function should be selectVat. We keep bad name for compatibility purpose.
4990
	 *
4991
	 *  @param	string	      $htmlname           Name of HTML select field
4992
	 *  @param  float|string  $selectedrate       Force preselected vat rate. Can be '8.5' or '8.5 (NOO)' for example. Use '' for no forcing.
4993
	 *  @param  Societe	      $societe_vendeuse   Thirdparty seller
4994
	 *  @param  Societe	      $societe_acheteuse  Thirdparty buyer
4995
	 *  @param  int		      $idprod             Id product. O if unknown of NA.
4996
	 *  @param  int		      $info_bits          Miscellaneous information on line (1 for NPR)
4997
	 *  @param  int|string    $type               ''=Unknown, 0=Product, 1=Service (Used if idprod not defined)
4998
	 *                  		                  Si vendeur non assujeti a TVA, TVA par defaut=0. Fin de regle.
4999
	 *                  					      Si le (pays vendeur = pays acheteur) alors la TVA par defaut=TVA du produit vendu. Fin de regle.
5000
	 *                  					      Si (vendeur et acheteur dans Communaute europeenne) et bien vendu = moyen de transports neuf (auto, bateau, avion), TVA par defaut=0 (La TVA doit etre paye par l'acheteur au centre d'impots de son pays et non au vendeur). Fin de regle.
5001
	 *                                            Si vendeur et acheteur dans Communauté européenne et acheteur= particulier alors TVA par défaut=TVA du produit vendu. Fin de règle.
5002
	 *                                            Si vendeur et acheteur dans Communauté européenne et acheteur= entreprise alors TVA par défaut=0. Fin de règle.
5003
	 *                  					      Sinon la TVA proposee par defaut=0. Fin de regle.
5004
	 *  @param	bool	     $options_only		  Return HTML options lines only (for ajax treatment)
5005
	 *  @param  int          $mode                0=Use vat rate as key in combo list, 1=Add VAT code after vat rate into key, -1=Use id of vat line as key
5006
	 *  @return	string
5007
	 */
5008
    public function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = '', $societe_acheteuse = '', $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0)
5009
	{
5010
        // phpcs:enable
5011
		global $langs,$conf,$mysoc;
5012
5013
		$langs->load('errors');
5014
5015
		$return='';
5016
5017
		// Define defaultnpr, defaultttx and defaultcode
5018
		$defaultnpr=($info_bits & 0x01);
5019
		$defaultnpr=(preg_match('/\*/', $selectedrate) ? 1 : $defaultnpr);
5020
		$defaulttx=str_replace('*', '', $selectedrate);
5021
		$defaultcode='';
5022
		if (preg_match('/\((.*)\)/', $defaulttx, $reg))
5023
		{
5024
			$defaultcode=$reg[1];
5025
			$defaulttx=preg_replace('/\s*\(.*\)/', '', $defaulttx);
5026
		}
5027
		//var_dump($selectedrate.'-'.$defaulttx.'-'.$defaultnpr.'-'.$defaultcode);
5028
5029
		// Check parameters
5030
		if (is_object($societe_vendeuse) && ! $societe_vendeuse->country_code)
5031
		{
5032
			if ($societe_vendeuse->id == $mysoc->id)
5033
			{
5034
				$return.= '<font class="error">'.$langs->trans("ErrorYourCountryIsNotDefined").'</div>';
5035
			}
5036
			else
5037
			{
5038
				$return.= '<font class="error">'.$langs->trans("ErrorSupplierCountryIsNotDefined").'</div>';
5039
			}
5040
			return $return;
5041
		}
5042
5043
		//var_dump($societe_acheteuse);
5044
		//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";
5045
		//exit;
5046
5047
		// Define list of countries to use to search VAT rates to show
5048
		// First we defined code_country to use to find list
5049
		if (is_object($societe_vendeuse))
5050
		{
5051
			$code_country="'".$societe_vendeuse->country_code."'";
5052
		}
5053
		else
5054
		{
5055
			$code_country="'".$mysoc->country_code."'";   // Pour compatibilite ascendente
5056
		}
5057
		if (! empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC))    // If option to have vat for end customer for services is on
5058
		{
5059
			require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
5060
			if (! isInEEC($societe_vendeuse) && (! is_object($societe_acheteuse) || (isInEEC($societe_acheteuse) && ! $societe_acheteuse->isACompany())))
5061
			{
5062
				// We also add the buyer
5063
				if (is_numeric($type))
5064
				{
5065
					if ($type == 1) // We know product is a service
5066
					{
5067
						$code_country.=",'".$societe_acheteuse->country_code."'";
5068
					}
5069
				}
5070
				elseif (! $idprod)  // We don't know type of product
5071
				{
5072
					$code_country.=",'".$societe_acheteuse->country_code."'";
5073
				}
5074
				else
5075
				{
5076
					$prodstatic=new Product($this->db);
5077
					$prodstatic->fetch($idprod);
5078
					if ($prodstatic->type == Product::TYPE_SERVICE)   // We know product is a service
5079
					{
5080
						$code_country.=",'".$societe_acheteuse->country_code."'";
5081
					}
5082
				}
5083
			}
5084
		}
5085
5086
		// Now we get list
5087
		$num = $this->load_cache_vatrates($code_country);   // If no vat defined, return -1 with message into this->error
5088
5089
		if ($num > 0)
5090
		{
5091
			// Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '')
5092
			if ($defaulttx < 0 || dol_strlen($defaulttx) == 0)
5093
			{
5094
				$tmpthirdparty=new Societe($this->db);
5095
				$defaulttx=get_default_tva($societe_vendeuse, (is_object($societe_acheteuse)?$societe_acheteuse:$tmpthirdparty), $idprod);
5096
				$defaultnpr=get_default_npr($societe_vendeuse, (is_object($societe_acheteuse)?$societe_acheteuse:$tmpthirdparty), $idprod);
5097
		        if (preg_match('/\((.*)\)/', $defaulttx, $reg)) {
5098
			        $defaultcode=$reg[1];
5099
			        $defaulttx=preg_replace('/\s*\(.*\)/', '', $defaulttx);
5100
		        }
5101
				if (empty($defaulttx)) $defaultnpr=0;
5102
			}
5103
5104
			// Si taux par defaut n'a pu etre determine, on prend dernier de la liste.
5105
			// Comme ils sont tries par ordre croissant, dernier = plus eleve = taux courant
5106
			if ($defaulttx < 0 || dol_strlen($defaulttx) == 0)
5107
			{
5108
				if (empty($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS)) $defaulttx = $this->cache_vatrates[$num-1]['txtva'];
5109
				else $defaulttx=($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS == 'none' ? '' : $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS);
5110
			}
5111
5112
			// Disabled if seller is not subject to VAT
5113
			$disabled=false; $title='';
5114
			if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0")
5115
			{
5116
				// Override/enable VAT for expense report regardless of global setting - needed if expense report used for business expenses
5117
				if (empty($conf->global->OVERRIDE_VAT_FOR_EXPENSE_REPORT))
5118
				{
5119
					$title=' title="'.$langs->trans('VATIsNotUsed').'"';
5120
					$disabled=true;
5121
				}
5122
			}
5123
5124
			if (! $options_only) $return.= '<select class="flat minwidth75imp" id="'.$htmlname.'" name="'.$htmlname.'"'.($disabled?' disabled':'').$title.'>';
5125
5126
			$selectedfound=false;
5127
			foreach ($this->cache_vatrates as $rate)
5128
			{
5129
				// Keep only 0 if seller is not subject to VAT
5130
				if ($disabled && $rate['txtva'] != 0) continue;
5131
5132
				// Define key to use into select list
5133
				$key = $rate['txtva'];
5134
				$key.= $rate['nprtva'] ? '*': '';
5135
				if ($mode > 0 && $rate['code']) $key.=' ('.$rate['code'].')';
5136
				if ($mode < 0) $key = $rate['rowid'];
5137
5138
				$return.= '<option value="'.$key.'"';
5139
				if (! $selectedfound)
5140
				{
5141
					if ($defaultcode) // If defaultcode is defined, we used it in priority to select combo option instead of using rate+npr flag
5142
					{
5143
						if ($defaultcode == $rate['code'])
5144
						{
5145
							$return.= ' selected';
5146
							$selectedfound=true;
5147
						}
5148
					}
5149
					elseif ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr)
5150
			   		{
5151
			   			$return.= ' selected';
5152
			   			$selectedfound=true;
5153
					}
5154
				}
5155
				$return.= '>';
5156
				//if (! empty($conf->global->MAIN_VAT_SHOW_POSITIVE_RATES))
5157
				if ($mysoc->country_code == 'IN' || ! empty($conf->global->MAIN_VAT_LABEL_IS_POSITIVE_RATES))
5158
				{
5159
					$return.= $rate['labelpositiverates'];
5160
				}
5161
				else
5162
				{
5163
					$return.= vatrate($rate['label']);
5164
				}
5165
				//$return.=($rate['code']?' '.$rate['code']:'');
5166
				$return.= (empty($rate['code']) && $rate['nprtva']) ? ' *': '';         // We show the *  (old behaviour only if new vat code is not used)
5167
5168
				$return.= '</option>';
5169
			}
5170
5171
			if (! $options_only) $return.= '</select>';
5172
		}
5173
		else
5174
		{
5175
			$return.= $this->error;
5176
		}
5177
5178
		$this->num = $num;
5179
		return $return;
5180
	}
5181
5182
5183
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5184
    /**
5185
     *  Show a HTML widget to input a date or combo list for day, month, years and optionaly hours and minutes.
5186
	 *  Fields are preselected with :
5187
	 *            	- set_time date (must be a local PHP server timestamp or string date with format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM')
5188
	 *            	- local date in user area, if set_time is '' (so if set_time is '', output may differs when done from two different location)
5189
	 *            	- Empty (fields empty), if set_time is -1 (in this case, parameter empty must also have value 1)
5190
	 *
5191
	 *	@param	integer	    $set_time 		Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2).
5192
	 *	@param	string		$prefix			Prefix for fields name
5193
	 *	@param	int			$h				1 or 2=Show also hours (2=hours on a new line), -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show hour always empty
5194
	 *	@param	int			$m				1=Show also minutes, -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show minutes always empty
5195
	 *	@param	int			$empty			0=Fields required, 1=Empty inputs are allowed, 2=Empty inputs are allowed for hours only
5196
	 *	@param	string		$form_name 		Not used
5197
	 *	@param	int			$d				1=Show days, month, years
5198
	 * 	@param	int			$addnowlink		Add a link "Now"
5199
	 * 	@param	int			$nooutput		Do not output html string but return it
5200
	 * 	@param 	int			$disabled		Disable input fields
5201
	 *  @param  int			$fullday        When a checkbox with this html name is on, hour and day are set with 00:00 or 23:59
5202
	 *  @param	string		$addplusone		Add a link "+1 hour". Value must be name of another select_date field.
5203
	 *  @param  datetime    $adddateof      Add a link "Date of invoice" using the following date.
5204
	 *  @return	string|void					Nothing or string if nooutput is 1
5205
     *  @deprecated
5206
	 *  @see    form_date(), select_month(), select_year(), select_dayofweek()
5207
	 */
5208
    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 = '', $addplusone = '', $adddateof = '')
5209
    {
5210
        // phpcs:enable
5211
        $retstring = $this->selectDate($set_time, $prefix, $h, $m, $empty, $form_name, $d, $addnowlink, $disabled, $fullday, $addplusone, $adddateof);
5212
        if (! empty($nooutput)) {
5213
            return $retstring;
5214
        }
5215
        print $retstring;
5216
        return;
5217
    }
5218
5219
    /**
5220
     *  Show a HTML widget to input a date or combo list for day, month, years and optionaly hours and minutes.
5221
	 *  Fields are preselected with :
5222
	 *              - set_time date (must be a local PHP server timestamp or string date with format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM')
5223
	 *              - local date in user area, if set_time is '' (so if set_time is '', output may differs when done from two different location)
5224
	 *              - Empty (fields empty), if set_time is -1 (in this case, parameter empty must also have value 1)
5225
	 *
5226
	 *  @param  integer     $set_time       Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2).
5227
	 *  @param	string		$prefix			Prefix for fields name
5228
	 *  @param	int			$h				1 or 2=Show also hours (2=hours on a new line), -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show hour always empty
5229
	 *	@param	int			$m				1=Show also minutes, -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show minutes always empty
5230
	 *	@param	int			$empty			0=Fields required, 1=Empty inputs are allowed, 2=Empty inputs are allowed for hours only
5231
	 *	@param	string		$form_name 		Not used
5232
	 *	@param	int			$d				1=Show days, month, years
5233
	 * 	@param	int			$addnowlink		Add a link "Now"
5234
	 * 	@param 	int			$disabled		Disable input fields
5235
	 *  @param  int			$fullday        When a checkbox with this html name is on, hour and day are set with 00:00 or 23:59
5236
	 *  @param	string		$addplusone		Add a link "+1 hour". Value must be name of another selectDate field.
5237
	 *  @param  datetime    $adddateof      Add a link "Date of invoice" using the following date.
5238
     *  @param  string      $openinghours   Specify hour strat and hour end for the select ex 8,20
5239
     *  @param  int         $stepminutes    Specify step for minutes between 1 and 30
5240
	 * 	@return string                      Html for selectDate
5241
	 *  @see    form_date(), select_month(), select_year(), select_dayofweek()
5242
	 */
5243
    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)
5244
	{
5245
		global $conf,$langs;
5246
5247
		$retstring='';
5248
5249
		if ($prefix=='') $prefix='re';
5250
		if ($h == '') $h=0;
5251
		if ($m == '') $m=0;
5252
		$emptydate=0;
5253
		$emptyhours=0;
5254
        if ($stepminutes<=0 || $stepminutes>30) $stepminutes = 1;
5255
		if ($empty == 1) { $emptydate=1; $emptyhours=1; }
5256
		if ($empty == 2) { $emptydate=0; $emptyhours=1; }
5257
		$orig_set_time=$set_time;
5258
5259
		if ($set_time === '' && $emptydate == 0)
5260
		{
5261
			include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
5262
			$set_time = dol_now('tzuser')-(getServerTimeZoneInt('now')*3600); // set_time must be relative to PHP server timezone
5263
		}
5264
5265
		// Analysis of the pre-selection date
5266
		if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', $set_time, $reg))	// deprecated usage
5267
		{
5268
			// Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'
5269
			$syear	= (! empty($reg[1])?$reg[1]:'');
5270
			$smonth	= (! empty($reg[2])?$reg[2]:'');
5271
			$sday	= (! empty($reg[3])?$reg[3]:'');
5272
			$shour	= (! empty($reg[4])?$reg[4]:'');
5273
			$smin	= (! empty($reg[5])?$reg[5]:'');
5274
		}
5275
		elseif (strval($set_time) != '' && $set_time != -1)
5276
		{
5277
			// set_time est un timestamps (0 possible)
5278
			$syear = dol_print_date($set_time, "%Y");
5279
			$smonth = dol_print_date($set_time, "%m");
5280
			$sday = dol_print_date($set_time, "%d");
5281
			if ($orig_set_time != '')
5282
			{
5283
				$shour = dol_print_date($set_time, "%H");
5284
				$smin = dol_print_date($set_time, "%M");
5285
				$ssec = dol_print_date($set_time, "%S");
5286
			}
5287
			else
5288
			{
5289
				$shour = '';
5290
				$smin = '';
5291
				$ssec = '';
5292
			}
5293
		}
5294
		else
5295
		{
5296
			// Date est '' ou vaut -1
5297
			$syear = '';
5298
			$smonth = '';
5299
			$sday = '';
5300
			$shour = !isset($conf->global->MAIN_DEFAULT_DATE_HOUR) ? ($h == -1 ? '23' : '') : $conf->global->MAIN_DEFAULT_DATE_HOUR;
5301
			$smin = !isset($conf->global->MAIN_DEFAULT_DATE_MIN) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_MIN;
5302
			$ssec = !isset($conf->global->MAIN_DEFAULT_DATE_SEC) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_SEC;
5303
		}
5304
		if ($h == 3) $shour = '';
5305
		if ($m == 3) $smin = '';
5306
5307
		// You can set MAIN_POPUP_CALENDAR to 'eldy' or 'jquery'
5308
		$usecalendar='combo';
5309
		if (! empty($conf->use_javascript_ajax) && (empty($conf->global->MAIN_POPUP_CALENDAR) || $conf->global->MAIN_POPUP_CALENDAR != "none")) {
5310
			$usecalendar = ((empty($conf->global->MAIN_POPUP_CALENDAR) || $conf->global->MAIN_POPUP_CALENDAR == 'eldy')?'jquery':$conf->global->MAIN_POPUP_CALENDAR);
5311
		}
5312
5313
		if ($d)
5314
		{
5315
			// Show date with popup
5316
			if ($usecalendar != 'combo')
5317
			{
5318
				$formated_date='';
5319
				//print "e".$set_time." t ".$conf->format_date_short;
5320
				if (strval($set_time) != '' && $set_time != -1)
5321
				{
5322
					//$formated_date=dol_print_date($set_time,$conf->format_date_short);
5323
					$formated_date=dol_print_date($set_time, $langs->trans("FormatDateShortInput"));  // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
5324
				}
5325
5326
				// Calendrier popup version eldy
5327
				if ($usecalendar == "eldy")
5328
				{
5329
					// Zone de saisie manuelle de la date
5330
					$retstring.='<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidth75" maxlength="11" value="'.$formated_date.'"';
5331
					$retstring.=($disabled?' disabled':'');
5332
					$retstring.=' onChange="dpChangeDay(\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\'); "';  // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
5333
					$retstring.='>';
5334
5335
					// Icone calendrier
5336
					if (! $disabled)
5337
					{
5338
						$retstring.='<button id="'.$prefix.'Button" type="button" class="dpInvisibleButtons"';
5339
						$base=DOL_URL_ROOT.'/core/';
5340
						$retstring.=' onClick="showDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');"';
5341
						$retstring.='>'.img_object($langs->trans("SelectDate"), 'calendarday', 'class="datecallink"').'</button>';
5342
					}
5343
					else $retstring.='<button id="'.$prefix.'Button" type="button" class="dpInvisibleButtons">'.img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"').'</button>';
5344
5345
					$retstring.='<input type="hidden" id="'.$prefix.'day"   name="'.$prefix.'day"   value="'.$sday.'">'."\n";
5346
					$retstring.='<input type="hidden" id="'.$prefix.'month" name="'.$prefix.'month" value="'.$smonth.'">'."\n";
5347
					$retstring.='<input type="hidden" id="'.$prefix.'year"  name="'.$prefix.'year"  value="'.$syear.'">'."\n";
5348
				}
5349
				elseif ($usecalendar == 'jquery')
5350
				{
5351
					if (! $disabled)
5352
					{
5353
						// Output javascript for datepicker
5354
						$retstring.="<script type='text/javascript'>";
5355
						$retstring.="$(function(){ $('#".$prefix."').datepicker({
5356
							dateFormat: '".$langs->trans("FormatDateShortJQueryInput")."',
5357
							autoclose: true,
5358
							todayHighlight: true,";
5359
							if (! empty($conf->dol_use_jmobile))
5360
							{
5361
								$retstring.="
5362
								beforeShow: function (input, datePicker) {
5363
									input.disabled = true;
5364
								},
5365
								onClose: function (dateText, datePicker) {
5366
									this.disabled = false;
5367
								},
5368
								";
5369
							}
5370
							// Note: We don't need monthNames, monthNamesShort, dayNames, dayNamesShort, dayNamesMin, they are set globally on datepicker component in lib_head.js.php
5371
							if (empty($conf->global->MAIN_POPUP_CALENDAR_ON_FOCUS))
5372
							{
5373
							$retstring.="
5374
								showOn: 'button',
5375
								buttonImage: '".DOL_URL_ROOT."/theme/".$conf->theme."/img/object_calendarday.png',
5376
								buttonImageOnly: true";
5377
							}
5378
							$retstring.="
5379
							}) });";
5380
						$retstring.="</script>";
5381
					}
5382
5383
					// Zone de saisie manuelle de la date
5384
					$retstring.='<div class="nowrap inline-block">';
5385
					$retstring.='<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidth75" maxlength="11" value="'.$formated_date.'"';
5386
					$retstring.=($disabled?' disabled':'');
5387
					$retstring.=' onChange="dpChangeDay(\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\'); "';  // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
5388
					$retstring.='>';
5389
5390
					// Icone calendrier
5391
					if (! $disabled)
5392
					{
5393
						/* Not required. Managed by option buttonImage of jquery
5394
                		$retstring.=img_object($langs->trans("SelectDate"),'calendarday','id="'.$prefix.'id" class="datecallink"');
5395
                		$retstring.="<script type='text/javascript'>";
5396
                		$retstring.="jQuery(document).ready(function() {";
5397
                		$retstring.='	jQuery("#'.$prefix.'id").click(function() {';
5398
                		$retstring.="    	jQuery('#".$prefix."').focus();";
5399
                		$retstring.='    });';
5400
                		$retstring.='});';
5401
                		$retstring.="</script>";*/
5402
					}
5403
					else
5404
					{
5405
						$retstring.='<button id="'.$prefix.'Button" type="button" class="dpInvisibleButtons">'.img_object($langs->trans("Disabled"), 'calendarday', 'class="datecallink"').'</button>';
5406
					}
5407
5408
					$retstring.='</div>';
5409
					$retstring.='<input type="hidden" id="'.$prefix.'day"   name="'.$prefix.'day"   value="'.$sday.'">'."\n";
5410
					$retstring.='<input type="hidden" id="'.$prefix.'month" name="'.$prefix.'month" value="'.$smonth.'">'."\n";
5411
					$retstring.='<input type="hidden" id="'.$prefix.'year"  name="'.$prefix.'year"  value="'.$syear.'">'."\n";
5412
				}
5413
				else
5414
				{
5415
					$retstring.="Bad value of MAIN_POPUP_CALENDAR";
5416
				}
5417
			}
5418
			// Show date with combo selects
5419
			else
5420
			{
5421
				//$retstring.='<div class="inline-block">';
5422
				// Day
5423
				$retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth50imp" id="'.$prefix.'day" name="'.$prefix.'day">';
5424
5425
				if ($emptydate || $set_time == -1)
5426
				{
5427
					$retstring.='<option value="0" selected>&nbsp;</option>';
5428
				}
5429
5430
				for ($day = 1 ; $day <= 31; $day++)
5431
				{
5432
					$retstring.='<option value="'.$day.'"'.($day == $sday ? ' selected':'').'>'.$day.'</option>';
5433
				}
5434
5435
				$retstring.="</select>";
5436
5437
				$retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth75imp" id="'.$prefix.'month" name="'.$prefix.'month">';
5438
				if ($emptydate || $set_time == -1)
5439
				{
5440
					$retstring.='<option value="0" selected>&nbsp;</option>';
5441
				}
5442
5443
				// Month
5444
				for ($month = 1 ; $month <= 12 ; $month++)
5445
				{
5446
					$retstring.='<option value="'.$month.'"'.($month == $smonth?' selected':'').'>';
5447
					$retstring.=dol_print_date(mktime(12, 0, 0, $month, 1, 2000), "%b");
5448
					$retstring.="</option>";
5449
				}
5450
				$retstring.="</select>";
5451
5452
				// Year
5453
				if ($emptydate || $set_time == -1)
5454
				{
5455
					$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.'">';
5456
				}
5457
				else
5458
				{
5459
					$retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth75imp" id="'.$prefix.'year" name="'.$prefix.'year">';
5460
5461
					for ($year = $syear - 10; $year < $syear + 10 ; $year++)
5462
					{
5463
						$retstring.='<option value="'.$year.'"'.($year == $syear ? ' selected':'').'>'.$year.'</option>';
5464
					}
5465
					$retstring.="</select>\n";
5466
				}
5467
				//$retstring.='</div>';
5468
			}
5469
		}
5470
5471
		if ($d && $h) $retstring.=($h==2?'<br>':' ');
5472
5473
		if ($h)
5474
		{
5475
			$hourstart = 0;
5476
			$hourend = 24;
5477
			if ($openinghours != '') {
5478
				$openinghours = explode(',', $openinghours);
5479
				$hourstart = $openinghours[0];
5480
				$hourend = $openinghours[1];
5481
				if ($hourend<$hourstart) $hourend = $hourstart;
5482
			}
5483
			// Show hour
5484
			$retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth50 '.($fullday?$fullday.'hour':'').'" id="'.$prefix.'hour" name="'.$prefix.'hour">';
5485
			if ($emptyhours) $retstring.='<option value="-1">&nbsp;</option>';
5486
			for ($hour = $hourstart; $hour < $hourend; $hour++)
5487
			{
5488
				if (strlen($hour) < 2) $hour = "0" . $hour;
5489
				$retstring.='<option value="'.$hour.'"'.(($hour == $shour)?' selected':'').'>'.$hour.(empty($conf->dol_optimize_smallscreen)?'':'H').'</option>';
5490
			}
5491
			$retstring.='</select>';
5492
			if ($m && empty($conf->dol_optimize_smallscreen)) $retstring.=":";
5493
		}
5494
5495
		if ($m)
5496
		{
5497
			// Show minutes
5498
			$retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth50 '.($fullday?$fullday.'min':'').'" id="'.$prefix.'min" name="'.$prefix.'min">';
5499
			if ($emptyhours) $retstring.='<option value="-1">&nbsp;</option>';
5500
			for ($min = 0; $min < 60 ; $min+=$stepminutes)
5501
			{
5502
				if (strlen($min) < 2) $min = "0" . $min;
5503
				$retstring.='<option value="'.$min.'"'.(($min == $smin)?' selected':'').'>'.$min.(empty($conf->dol_optimize_smallscreen)?'':'').'</option>';
5504
			}
5505
			$retstring.='</select>';
5506
5507
			$retstring.='<input type="hidden" name="'.$prefix.'sec" value="'.$ssec.'">';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $ssec does not seem to be defined for all execution paths leading up to this point.
Loading history...
5508
		}
5509
5510
		// Add a "Now" link
5511
		if ($conf->use_javascript_ajax && $addnowlink)
5512
		{
5513
			// Script which will be inserted in the onClick of the "Now" link
5514
			$reset_scripts = "";
5515
5516
			// Generate the date part, depending on the use or not of the javascript calendar
5517
			$reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date(dol_now(), 'day').'\');';
5518
			$reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.dol_print_date(dol_now(), '%d').'\');';
5519
			$reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.dol_print_date(dol_now(), '%m').'\');';
5520
			$reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.dol_print_date(dol_now(), '%Y').'\');';
5521
			/*if ($usecalendar == "eldy")
5522
            {
5523
                $base=DOL_URL_ROOT.'/core/';
5524
                $reset_scripts .= 'resetDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');';
5525
            }
5526
            else
5527
            {
5528
                $reset_scripts .= 'this.form.elements[\''.$prefix.'day\'].value=formatDate(new Date(), \'d\'); ';
5529
                $reset_scripts .= 'this.form.elements[\''.$prefix.'month\'].value=formatDate(new Date(), \'M\'); ';
5530
                $reset_scripts .= 'this.form.elements[\''.$prefix.'year\'].value=formatDate(new Date(), \'yyyy\'); ';
5531
            }*/
5532
			// Update the hour part
5533
			if ($h)
5534
			{
5535
				if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
5536
				//$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); ';
5537
				$reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(), '%H').'\');';
5538
				if ($fullday) $reset_scripts .= ' } ';
5539
			}
5540
			// Update the minute part
5541
			if ($m)
5542
			{
5543
				if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
5544
				//$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); ';
5545
				$reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(), '%M').'\');';
5546
				if ($fullday) $reset_scripts .= ' } ';
5547
			}
5548
			// If reset_scripts is not empty, print the link with the reset_scripts in the onClick
5549
			if ($reset_scripts && empty($conf->dol_optimize_smallscreen))
5550
			{
5551
				$retstring.=' <button class="dpInvisibleButtons datenowlink" id="'.$prefix.'ButtonNow" type="button" name="_useless" value="now" onClick="'.$reset_scripts.'">';
5552
				$retstring.=$langs->trans("Now");
5553
				$retstring.='</button> ';
5554
			}
5555
		}
5556
5557
		// Add a "Plus one hour" link
5558
		if ($conf->use_javascript_ajax && $addplusone)
5559
		{
5560
			// Script which will be inserted in the onClick of the "Add plusone" link
5561
			$reset_scripts = "";
5562
5563
			// Generate the date part, depending on the use or not of the javascript calendar
5564
			$reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date(dol_now(), 'day').'\');';
5565
			$reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.dol_print_date(dol_now(), '%d').'\');';
5566
			$reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.dol_print_date(dol_now(), '%m').'\');';
5567
			$reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.dol_print_date(dol_now(), '%Y').'\');';
5568
			// Update the hour part
5569
			if ($h)
5570
			{
5571
				if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
5572
				$reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(), '%H').'\');';
5573
				if ($fullday) $reset_scripts .= ' } ';
5574
			}
5575
			// Update the minute part
5576
			if ($m)
5577
			{
5578
				if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
5579
				$reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(), '%M').'\');';
5580
				if ($fullday) $reset_scripts .= ' } ';
5581
			}
5582
			// If reset_scripts is not empty, print the link with the reset_scripts in the onClick
5583
			if ($reset_scripts && empty($conf->dol_optimize_smallscreen))
5584
			{
5585
				$retstring.=' <button class="dpInvisibleButtons datenowlink" id="'.$prefix.'ButtonPlusOne" type="button" name="_useless2" value="plusone" onClick="'.$reset_scripts.'">';
5586
				$retstring.=$langs->trans("DateStartPlusOne");
5587
				$retstring.='</button> ';
5588
			}
5589
		}
5590
5591
		// Add a "Plus one hour" link
5592
		if ($conf->use_javascript_ajax && $adddateof)
5593
		{
5594
			$tmparray=dol_getdate($adddateof);
5595
			$retstring.=' - <button class="dpInvisibleButtons datenowlink" id="dateofinvoice" type="button" name="_dateofinvoice" value="now" onclick="jQuery(\'#re\').val(\''.dol_print_date($adddateof, 'day').'\');jQuery(\'#reday\').val(\''.$tmparray['mday'].'\');jQuery(\'#remonth\').val(\''.$tmparray['mon'].'\');jQuery(\'#reyear\').val(\''.$tmparray['year'].'\');">'.$langs->trans("DateInvoice").'</a>';
5596
		}
5597
5598
		return $retstring;
5599
	}
5600
5601
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
5602
    /**
5603
     *  Function to show a form to select a duration on a page
5604
	 *
5605
	 *	@param	string	$prefix   		Prefix for input fields
5606
	 *	@param  int	$iSecond  		    Default preselected duration (number of seconds or '')
5607
	 * 	@param	int	$disabled           Disable the combo box
5608
	 * 	@param	string	$typehour		If 'select' then input hour and input min is a combo,
5609
	 *						            if 'text' input hour is in text and input min is a text,
5610
	 *						            if 'textselect' input hour is in text and input min is a combo
5611
	 *  @param	integer	$minunderhours	If 1, show minutes selection under the hours
5612
	 * 	@param	int	$nooutput		    Do not output html string but return it
5613
	 *  @return	string|void
5614
	 */
5615
    public function select_duration($prefix, $iSecond = '', $disabled = 0, $typehour = 'select', $minunderhours = 0, $nooutput = 0)
5616
	{
5617
        // phpcs:enable
5618
		global $langs;
5619
5620
		$retstring='';
5621
5622
		$hourSelected=0; $minSelected=0;
5623
5624
		// Hours
5625
		if ($iSecond != '')
5626
		{
5627
			require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
5628
5629
			$hourSelected = convertSecondToTime($iSecond, 'allhour');
5630
			$minSelected = convertSecondToTime($iSecond, 'min');
5631
		}
5632
5633
		if ($typehour=='select' )
5634
		{
5635
			$retstring.='<select class="flat" id="select_'.$prefix.'hour" name="'.$prefix.'hour"'.($disabled?' disabled':'').'>';
5636
			for ($hour = 0; $hour < 25; $hour++)	// For a duration, we allow 24 hours
5637
			{
5638
				$retstring.='<option value="'.$hour.'"';
5639
				if ($hourSelected == $hour)
5640
				{
5641
					$retstring.=" selected";
5642
				}
5643
				$retstring.=">".$hour."</option>";
5644
			}
5645
			$retstring.="</select>";
5646
		}
5647
		elseif ($typehour=='text' || $typehour=='textselect')
5648
		{
5649
			$retstring.='<input placeholder="'.$langs->trans('HourShort').'" type="number" min="0" size="1" name="'.$prefix.'hour"'.($disabled?' disabled':'').' class="flat maxwidth50 inputhour" value="'.(($hourSelected != '')?((int) $hourSelected):'').'">';
5650
		}
5651
		else return 'BadValueForParameterTypeHour';
5652
5653
		if ($typehour!='text') $retstring.=' '.$langs->trans('HourShort');
5654
		else $retstring.='<span class="hideonsmartphone">:</span>';
5655
5656
		// Minutes
5657
		if ($minunderhours) $retstring.='<br>';
5658
		else $retstring.='<span class="hideonsmartphone">&nbsp;</span>';
5659
5660
		if ($typehour=='select' || $typehour=='textselect')
5661
		{
5662
			$retstring.='<select class="flat" id="select_'.$prefix.'min" name="'.$prefix.'min"'.($disabled?' disabled':'').'>';
5663
			for ($min = 0; $min <= 55; $min=$min+5)
5664
			{
5665
				$retstring.='<option value="'.$min.'"';
5666
				if ($minSelected == $min) $retstring.=' selected';
5667
				$retstring.='>'.$min.'</option>';
5668
			}
5669
			$retstring.="</select>";
5670
		}
5671
		elseif ($typehour=='text' )
5672
		{
5673
			$retstring.='<input placeholder="'.$langs->trans('MinuteShort').'" type="number" min="0" size="1" name="'.$prefix.'min"'.($disabled?' disabled':'').' class="flat maxwidth50 inputminute" value="'.(($minSelected != '')?((int) $minSelected):'').'">';
5674
		}
5675
5676
		if ($typehour!='text') $retstring.=' '.$langs->trans('MinuteShort');
5677
5678
		//$retstring.="&nbsp;";
5679
5680
		if (! empty($nooutput)) return $retstring;
5681
5682
		print $retstring;
5683
		return;
5684
	}
5685
5686
5687
	/**
5688
	 * Generic method to select a component from a combo list.
5689
	 * This is the generic method that will replace all specific existing methods.
5690
	 *
5691
	 * @param 	string			$objectdesc			Objectclassname:Objectclasspath
5692
	 * @param	string			$htmlname			Name of HTML select component
5693
	 * @param	int				$preselectedvalue	Preselected value (ID of element)
5694
	 * @param	string			$showempty			''=empty values not allowed, 'string'=value show if we allow empty values (for example 'All', ...)
5695
	 * @param	string			$searchkey			Search criteria
5696
	 * @param	string			$placeholder		Place holder
5697
	 * @param	string			$morecss			More CSS
5698
	 * @param	string			$moreparams			More params provided to ajax call
5699
	 * @param	int				$forcecombo			Force to load all values and output a standard combobox (with no beautification)
5700
	 * @return	string								Return HTML string
5701
	 * @see selectForFormsList() select_thirdparty
5702
	 */
5703
    public function selectForForms($objectdesc, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0)
5704
	{
5705
		global $conf, $user;
5706
5707
		$objecttmp = null;
5708
5709
		$InfoFieldList = explode(":", $objectdesc);
5710
		$classname=$InfoFieldList[0];
5711
		$classpath=$InfoFieldList[1];
5712
		if (! empty($classpath))
5713
		{
5714
			dol_include_once($classpath);
5715
			if ($classname && class_exists($classname))
5716
			{
5717
				$objecttmp = new $classname($this->db);
5718
			}
5719
		}
5720
		if (! is_object($objecttmp))
5721
		{
5722
			dol_syslog('Error bad setup of type for field '.$InfoFieldList, LOG_WARNING);
1 ignored issue
show
Bug introduced by
Are you sure $InfoFieldList of type string[] can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

5722
			dol_syslog('Error bad setup of type for field './** @scrutinizer ignore-type */ $InfoFieldList, LOG_WARNING);
Loading history...
5723
			return 'Error bad setup of type for field '.join(',', $InfoFieldList);
5724
		}
5725
5726
		$prefixforautocompletemode=$objecttmp->element;
5727
		if ($prefixforautocompletemode == 'societe') $prefixforautocompletemode='company';
5728
		$confkeyforautocompletemode=strtoupper($prefixforautocompletemode).'_USE_SEARCH_TO_SELECT';	// For example COMPANY_USE_SEARCH_TO_SELECT
5729
5730
		dol_syslog(get_class($this)."::selectForForms", LOG_DEBUG);
5731
5732
		$out='';
5733
		if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->$confkeyforautocompletemode) && ! $forcecombo)
5734
		{
5735
			$objectdesc=$classname.':'.$classpath;
5736
			$urlforajaxcall = DOL_URL_ROOT.'/core/ajax/selectobject.php';
5737
5738
			// No immediate load of all database
5739
			$urloption='htmlname='.$htmlname.'&outjson=1&objectdesc='.$objectdesc.($moreparams?$moreparams:'');
5740
			// Activate the auto complete using ajax call.
5741
			$out.=  ajax_autocompleter($preselectedvalue, $htmlname, $urlforajaxcall, $urloption, $conf->global->$confkeyforautocompletemode, 0, array());
5742
			$out.= '<style type="text/css">.ui-autocomplete { z-index: 250; }</style>';
5743
			if ($placeholder) $placeholder=' placeholder="'.$placeholder.'"';
5744
			$out.= '<input type="text" class="'.$morecss.'" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$preselectedvalue.'"'.$placeholder.' />';
5745
		}
5746
		else
5747
		{
5748
			// Immediate load of all database
5749
			$out.=$this->selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo);
5750
		}
5751
5752
		return $out;
5753
	}
5754
5755
	/**
5756
	 * Output html form to select an object.
5757
	 * Note, this function is called by selectForForms or by ajax selectobject.php
5758
	 *
5759
	 * @param 	Object			$objecttmp			Object
5760
	 * @param	string			$htmlname			Name of HTML select component
5761
	 * @param	int				$preselectedvalue	Preselected value (ID of element)
5762
	 * @param	string			$showempty			''=empty values not allowed, 'string'=value show if we allow empty values (for example 'All', ...)
5763
	 * @param	string			$searchkey			Search value
5764
	 * @param	string			$placeholder		Place holder
5765
	 * @param	string			$morecss			More CSS
5766
	 * @param	string			$moreparams			More params provided to ajax call
5767
	 * @param	int				$forcecombo			Force to load all values and output a standard combobox (with no beautification)
5768
	 * @param	int				$outputmode			0=HTML select string, 1=Array
5769
	 * @return	string								Return HTML string
5770
	 * @see selectForForms()
5771
	 */
5772
    public function selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $outputmode = 0)
5773
	{
5774
		global $conf, $langs, $user;
5775
5776
		$prefixforautocompletemode=$objecttmp->element;
5777
		if ($prefixforautocompletemode == 'societe') $prefixforautocompletemode='company';
5778
		$confkeyforautocompletemode=strtoupper($prefixforautocompletemode).'_USE_SEARCH_TO_SELECT';	// For example COMPANY_USE_SEARCH_TO_SELECT
5779
5780
		$fieldstoshow='t.ref';
5781
		if (! empty($objecttmp->fields))	// For object that declare it, it is better to use declared fields ( like societe, contact, ...)
5782
		{
5783
			$tmpfieldstoshow='';
5784
			foreach($objecttmp->fields as $key => $val)
5785
			{
5786
				if ($val['showoncombobox']) $tmpfieldstoshow.=($tmpfieldstoshow?',':'').'t.'.$key;
5787
			}
5788
			if ($tmpfieldstoshow) $fieldstoshow = $tmpfieldstoshow;
5789
		}
5790
5791
		$out='';
5792
		$outarray=array();
5793
5794
		$num=0;
5795
5796
		// Search data
5797
		$sql = "SELECT t.rowid, ".$fieldstoshow." FROM ".MAIN_DB_PREFIX .$objecttmp->table_element." as t";
5798
		if ($objecttmp->ismultientitymanaged == 2)
5799
			if (!$user->rights->societe->client->voir && !$user->societe_id) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
5800
		$sql.= " WHERE 1=1";
5801
		if(! empty($objecttmp->ismultientitymanaged)) $sql.= " AND t.entity IN (".getEntity($objecttmp->table_element).")";
5802
		if ($objecttmp->ismultientitymanaged == 1 && ! empty($user->societe_id))
5803
		{
5804
			if ($objecttmp->element == 'societe') $sql.= " AND t.rowid = ".$user->societe_id;
5805
				else $sql.= " AND t.fk_soc = ".$user->societe_id;
5806
		}
5807
		if ($searchkey != '') $sql.=natural_search(explode(',', $fieldstoshow), $searchkey);
5808
		if ($objecttmp->ismultientitymanaged == 2)
5809
			if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND t.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
5810
		$sql.=$this->db->order($fieldstoshow, "ASC");
5811
		//$sql.=$this->db->plimit($limit, 0);
5812
5813
		// Build output string
5814
		$resql=$this->db->query($sql);
5815
		if ($resql)
5816
		{
5817
			if (! $forcecombo)
5818
			{
5819
				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
5820
				$out .= ajax_combobox($htmlname, null, $conf->global->$confkeyforautocompletemode);
5821
			}
5822
5823
			// Construct $out and $outarray
5824
			$out.= '<select id="'.$htmlname.'" class="flat'.($morecss?' '.$morecss:'').'"'.($moreparams?' '.$moreparams:'').' name="'.$htmlname.'">'."\n";
5825
5826
			// 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
5827
			$textifempty='&nbsp;';
5828
5829
			//if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
5830
			if (! empty($conf->global->$confkeyforautocompletemode))
5831
			{
5832
				if ($showempty && ! is_numeric($showempty)) $textifempty=$langs->trans($showempty);
5833
				else $textifempty.=$langs->trans("All");
5834
			}
5835
			if ($showempty) $out.= '<option value="-1">'.$textifempty.'</option>'."\n";
5836
5837
			$num = $this->db->num_rows($resql);
5838
			$i = 0;
5839
			if ($num)
5840
			{
5841
				while ($i < $num)
5842
				{
5843
					$obj = $this->db->fetch_object($resql);
5844
					$label='';
5845
					$tmparray=explode(',', $fieldstoshow);
5846
					foreach($tmparray as $key => $val)
5847
					{
5848
						$val = preg_replace('/t\./', '', $val);
5849
						$label .= (($label && $obj->$val)?' - ':'').$obj->$val;
5850
					}
5851
					if (empty($outputmode))
5852
					{
5853
						if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid)
5854
						{
5855
							$out.= '<option value="'.$obj->rowid.'" selected>'.$label.'</option>';
5856
						}
5857
						else
5858
						{
5859
							$out.= '<option value="'.$obj->rowid.'">'.$label.'</option>';
5860
						}
5861
					}
5862
					else
5863
					{
5864
						array_push($outarray, array('key'=>$obj->rowid, 'value'=>$label, 'label'=>$label));
5865
					}
5866
5867
					$i++;
5868
					if (($i % 10) == 0) $out.="\n";
5869
				}
5870
			}
5871
5872
			$out.= '</select>'."\n";
5873
		}
5874
		else
5875
		{
5876
			dol_print_error($this->db);
5877
		}
5878
5879
		$this->result=array('nbofelement'=>$num);
5880
5881
		if ($outputmode) return $outarray;
5882
		return $out;
5883
	}
5884
5885
5886
	/**
5887
	 *	Return a HTML select string, built from an array of key+value.
5888
	 *  Note: Do not apply langs->trans function on returned content, content may be entity encoded twice.
5889
	 *
5890
	 *	@param	string			$htmlname			Name of html select area. Must start with "multi" if this is a multiselect
5891
	 *	@param	array			$array				Array like array(key => value) or array(key=>array('label'=>..., 'data-...'=>...))
5892
	 *	@param	string|string[]	$id					Preselected key or preselected keys for multiselect
5893
	 *	@param	int|string		$show_empty			0 no empty value allowed, 1 or string to add an empty value into list (key is -1 and value is '' or '&nbsp;' if 1, key is -1 and value is text if string), <0 to add an empty value with key that is this value.
5894
	 *	@param	int				$key_in_label		1 to show key into label with format "[key] value"
5895
	 *	@param	int				$value_as_key		1 to use value as key
5896
	 *	@param  string			$moreparam			Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
5897
	 *	@param  int				$translate			1=Translate and encode value
5898
	 * 	@param	int				$maxlen				Length maximum for labels
5899
	 * 	@param	int				$disabled			Html select box is disabled
5900
	 *  @param	string			$sort				'ASC' or 'DESC' = Sort on label, '' or 'NONE' or 'POS' = Do not sort, we keep original order
5901
	 *  @param	string			$morecss			Add more class to css styles
5902
	 *  @param	int				$addjscombo			Add js combo
5903
	 *  @param  string          $moreparamonempty	Add more param on the empty option line. Not used if show_empty not set
5904
	 *  @param  int             $disablebademail	1=Check if a not valid email, 2=Check string '---', and if found into value, disable and colorize entry
5905
	 *  @param  int             $nohtmlescape		No html escaping.
5906
	 * 	@return	string								HTML select string.
5907
	 *  @see multiselectarray(), selectArrayAjax(), selectArrayFilter()
5908
	 */
5909
	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 = '', $addjscombo = 0, $moreparamonempty = '', $disablebademail = 0, $nohtmlescape = 0)
5910
	{
5911
		global $conf, $langs;
5912
5913
		// Do we want a multiselect ?
5914
		//$jsbeautify = 0;
5915
		//if (preg_match('/^multi/',$htmlname)) $jsbeautify = 1;
5916
		$jsbeautify = 1;
5917
5918
		if ($value_as_key) $array=array_combine($array, $array);
5919
5920
		$out='';
5921
5922
		// Add code for jquery to use multiselect
5923
		if ($addjscombo && $jsbeautify)
5924
		{
5925
			$minLengthToAutocomplete=0;
5926
			$tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?(constant('REQUIRE_JQUERY_MULTISELECT')?constant('REQUIRE_JQUERY_MULTISELECT'):'select2'):$conf->global->MAIN_USE_JQUERY_MULTISELECT;
5927
5928
			// Enhance with select2
5929
			include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
5930
			$out .= ajax_combobox($htmlname);
5931
		}
5932
5933
		$out.='<select id="'.preg_replace('/^\./', '', $htmlname).'" '.($disabled?'disabled ':'').'class="flat '.(preg_replace('/^\./', '', $htmlname)).($morecss?' '.$morecss:'').'"';
5934
		$out.=' name="'.preg_replace('/^\./', '', $htmlname).'" '.($moreparam?$moreparam:'');
5935
		$out.='>';
5936
5937
		if ($show_empty)
5938
		{
5939
			$textforempty=' ';
5940
			if (! empty($conf->use_javascript_ajax)) $textforempty='&nbsp;';	// If we use ajaxcombo, we need &nbsp; here to avoid to have an empty element that is too small.
5941
			if (! is_numeric($show_empty)) $textforempty=$show_empty;
5942
			$out.='<option class="optiongrey" '.($moreparamonempty?$moreparamonempty.' ':'').'value="'.($show_empty < 0 ? $show_empty : -1).'"'.($id == $show_empty ?' selected':'').'>'.$textforempty.'</option>'."\n";
5943
		}
5944
5945
		if (is_array($array))
5946
		{
5947
			// Translate
5948
			if ($translate)
5949
			{
5950
				foreach($array as $key => $value)
5951
				{
5952
				    if (! is_array($value)) $array[$key]=$langs->trans($value);
5953
				    else $array[$key]['label']=$langs->trans($value['label']);
5954
				}
5955
			}
5956
5957
			// Sort
5958
			if ($sort == 'ASC') asort($array);
5959
			elseif ($sort == 'DESC') arsort($array);
5960
5961
			foreach($array as $key => $tmpvalue)
5962
			{
5963
			    if (is_array($tmpvalue)) $value=$tmpvalue['label'];
5964
			    else $value = $tmpvalue;
5965
5966
				$disabled=''; $style='';
5967
				if (! empty($disablebademail))
5968
				{
5969
				    if (($disablebademail == 1 && ! preg_match('/&lt;.+@.+&gt;/', $value))
5970
				        || ($disablebademail == 2 && preg_match('/---/', $value)))
5971
					{
5972
						$disabled=' disabled';
5973
						$style=' class="warning"';
5974
					}
5975
				}
5976
5977
				if ($key_in_label)
5978
				{
5979
					if (empty($nohtmlescape)) $selectOptionValue = dol_escape_htmltag($key.' - '.($maxlen?dol_trunc($value, $maxlen):$value));
5980
					else $selectOptionValue = $key.' - '.($maxlen?dol_trunc($value, $maxlen):$value);
5981
				}
5982
				else
5983
				{
5984
					if (empty($nohtmlescape)) $selectOptionValue = dol_escape_htmltag($maxlen?dol_trunc($value, $maxlen):$value);
5985
					else $selectOptionValue = $maxlen?dol_trunc($value, $maxlen):$value;
5986
					if ($value == '' || $value == '-') $selectOptionValue='&nbsp;';
5987
				}
5988
5989
				$out.='<option value="'.$key.'"';
5990
				$out.=$style.$disabled;
5991
				if ($id != '' && $id == $key && ! $disabled) $out.=' selected';		// To preselect a value
5992
				if ($nohtmlescape) $out.=' data-html="'.dol_escape_htmltag($selectOptionValue).'"';
5993
				if (is_array($tmpvalue))
5994
				{
5995
				    foreach($tmpvalue as $keyforvalue => $valueforvalue)
5996
				    {
5997
				        if (preg_match('/^data-/', $keyforvalue)) $out.=' '.$keyforvalue.'="'.$valueforvalue.'"';
5998
				    }
5999
				}
6000
				$out.='>';
6001
				//var_dump($selectOptionValue);
6002
				$out.=$selectOptionValue;
6003
				$out.="</option>\n";
6004
			}
6005
		}
6006
6007
		$out.="</select>";
6008
		return $out;
6009
	}
6010
6011
6012
	/**
6013
	 *	Return a HTML select string, built from an array of key+value, but content returned into select come from an Ajax call of an URL.
6014
	 *  Note: Do not apply langs->trans function on returned content of Ajax service, content may be entity encoded twice.
6015
	 *
6016
	 *	@param	string	$htmlname       		Name of html select area
6017
	 *	@param	string	$url					Url. Must return a json_encode of array(key=>array('text'=>'A text', 'url'=>'An url'), ...)
6018
	 *	@param	string	$id             		Preselected key
6019
	 *	@param  string	$moreparam      		Add more parameters onto the select tag
6020
	 *	@param  string	$moreparamtourl 		Add more parameters onto the Ajax called URL
6021
	 * 	@param	int		$disabled				Html select box is disabled
6022
	 *  @param	int		$minimumInputLength		Minimum Input Length
6023
	 *  @param	string	$morecss				Add more class to css styles
6024
	 *  @param  int     $callurlonselect        If set to 1, some code is added so an url return by the ajax is called when value is selected.
6025
	 *  @param  string  $placeholder            String to use as placeholder
6026
	 *  @param  integer $acceptdelayedhtml      1 = caller is requesting to have html js content not returned but saved into global $delayedhtmlcontent (so caller can show it at end of page to avoid flash FOUC effect)
6027
	 * 	@return	string   						HTML select string
6028
	 *  @see selectArrayFilter(), ajax_combobox() in ajax.lib.php
6029
	 */
6030
	public static function selectArrayAjax($htmlname, $url, $id = '', $moreparam = '', $moreparamtourl = '', $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0)
6031
	{
6032
		global $conf, $langs;
6033
		global $delayedhtmlcontent;
6034
6035
		// TODO Use an internal dolibarr component instead of select2
6036
		if (empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && ! defined('REQUIRE_JQUERY_MULTISELECT')) return '';
6037
6038
		$out='<select type="text" class="'.$htmlname.($morecss?' '.$morecss:'').'" '.($moreparam?$moreparam.' ':'').'name="'.$htmlname.'"></select>';
6039
6040
		$tmpplugin='select2';
6041
		$outdelayed="\n".'<!-- JS CODE TO ENABLE '.$tmpplugin.' for id '.$htmlname.' -->
6042
	    	<script>
6043
	    	$(document).ready(function () {
6044
6045
    	        '.($callurlonselect ? 'var saveRemoteData = [];':'').'
6046
6047
                $(".'.$htmlname.'").select2({
6048
			    	ajax: {
6049
				    	dir: "ltr",
6050
				    	url: "'.$url.'",
6051
				    	dataType: \'json\',
6052
				    	delay: 250,
6053
				    	data: function (params) {
6054
				    		return {
6055
						    	q: params.term, 	// search term
6056
				    			page: params.page
6057
				    		};
6058
			    		},
6059
			    		processResults: function (data) {
6060
			    			// parse the results into the format expected by Select2.
6061
			    			// since we are using custom formatting functions we do not need to alter the remote JSON data
6062
			    			//console.log(data);
6063
							saveRemoteData = data;
6064
				    	    /* format json result for select2 */
6065
				    	    result = []
6066
				    	    $.each( data, function( key, value ) {
6067
				    	       result.push({id: key, text: value.text});
6068
                            });
6069
			    			//return {results:[{id:\'none\', text:\'aa\'}, {id:\'rrr\', text:\'Red\'},{id:\'bbb\', text:\'Search a into projects\'}], more:false}
6070
			    			//console.log(result);
6071
			    			return {results: result, more: false}
6072
			    		},
6073
			    		cache: true
6074
			    	},
6075
	 				language: select2arrayoflanguage,
6076
					containerCssClass: \':all:\',					/* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
6077
				    placeholder: "'.dol_escape_js($placeholder).'",
6078
			    	escapeMarkup: function (markup) { return markup; }, 	// let our custom formatter work
6079
			    	minimumInputLength: '.$minimumInputLength.',
6080
			        formatResult: function(result, container, query, escapeMarkup) {
6081
                        return escapeMarkup(result.text);
6082
                    },
6083
			    });
6084
6085
                '.($callurlonselect ? '
6086
                /* Code to execute a GET when we select a value */
6087
                $(".'.$htmlname.'").change(function() {
6088
			    	var selected = $(".'.$htmlname.'").val();
6089
                	console.log("We select in selectArrayAjax the entry "+selected)
6090
			        $(".'.$htmlname.'").val("");  /* reset visible combo value */
6091
    			    $.each( saveRemoteData, function( key, value ) {
6092
    				        if (key == selected)
6093
    			            {
6094
    			                 console.log("selectArrayAjax - Do a redirect to "+value.url)
6095
    			                 location.assign(value.url);
6096
    			            }
6097
                    });
6098
    			});' : '' ) . '
6099
6100
    	   });
6101
	       </script>';
6102
6103
		if ($acceptdelayedhtml)
6104
		{
6105
			$delayedhtmlcontent.=$outdelayed;
6106
		}
6107
		else
6108
		{
6109
			$out.=$outdelayed;
6110
		}
6111
		return $out;
6112
	}
6113
6114
    /**
6115
     *  Return a HTML select string, built from an array of key+value, but content returned into select is defined into $array parameter.
6116
     *  Note: Do not apply langs->trans function on returned content of Ajax service, content may be entity encoded twice.
6117
     *
6118
     *  @param  string	$htmlname               Name of html select area
6119
	 *	@param	string	$array					Array (key=>array('text'=>'A text', 'url'=>'An url'), ...)
6120
	 *	@param	string	$id             		Preselected key
6121
	 *	@param  string	$moreparam      		Add more parameters onto the select tag
6122
	 *	@param	int		$disableFiltering		If set to 1, results are not filtered with searched string
6123
	 * 	@param	int		$disabled				Html select box is disabled
6124
	 *  @param	int		$minimumInputLength		Minimum Input Length
6125
	 *  @param	string	$morecss				Add more class to css styles
6126
	 *  @param  int     $callurlonselect        If set to 1, some code is added so an url return by the ajax is called when value is selected.
6127
	 *  @param  string  $placeholder            String to use as placeholder
6128
	 *  @param  integer $acceptdelayedhtml      1 = caller is requesting to have html js content not returned but saved into global $delayedhtmlcontent (so caller can show it at end of page to avoid flash FOUC effect)
6129
	 *  @return	string   						HTML select string
6130
	 *  @see selectArrayAjax(), ajax_combobox() in ajax.lib.php
6131
	 */
6132
	public static function selectArrayFilter($htmlname, $array, $id = '', $moreparam = '', $disableFiltering = 0, $disabled = 0, $minimumInputLength = 1, $morecss = '', $callurlonselect = 0, $placeholder = '', $acceptdelayedhtml = 0)
6133
	{
6134
		global $conf, $langs;
6135
		global $delayedhtmlcontent;
6136
6137
		// TODO Use an internal dolibarr component instead of select2
6138
		if (empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && ! defined('REQUIRE_JQUERY_MULTISELECT')) return '';
6139
6140
		$out='<select type="text" class="'.$htmlname.($morecss?' '.$morecss:'').'" '.($moreparam?$moreparam.' ':'').'name="'.$htmlname.'"><option></option></select>';
6141
6142
		$formattedarrayresult = array();
6143
6144
		foreach($array as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $array of type string is not traversable.
Loading history...
6145
			$o = new stdClass();
6146
			$o->id = $key;
6147
			$o->text = $value['text'];
6148
			$o->url = $value['url'];
6149
			$formattedarrayresult[] = $o;
6150
		}
6151
6152
		$tmpplugin='select2';
6153
		$outdelayed="\n".'<!-- JS CODE TO ENABLE '.$tmpplugin.' for id '.$htmlname.' -->
6154
			<script>
6155
			$(document).ready(function () {
6156
				var data = '.json_encode($formattedarrayresult).';
6157
6158
				'.($callurlonselect ? 'var saveRemoteData = '.json_encode($array).';':'').'
6159
6160
				$(".'.$htmlname.'").select2({
6161
					data: data,
6162
					language: select2arrayoflanguage,
6163
					containerCssClass: \':all:\',					/* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
6164
					placeholder: "'.dol_escape_js($placeholder).'",
6165
					escapeMarkup: function (markup) { return markup; }, 	// let our custom formatter work
6166
					minimumInputLength: '.$minimumInputLength.',
6167
					formatResult: function(result, container, query, escapeMarkup) {
6168
						return escapeMarkup(result.text);
6169
					},
6170
					matcher: function (params, data) {
6171
6172
						if(! data.id) return null;';
6173
6174
		if($callurlonselect) {
6175
			$outdelayed.='
6176
6177
						var urlBase = data.url;
6178
						var separ = urlBase.indexOf("?") >= 0 ? "&" : "?";
6179
						/* console.log("params.term="+params.term); */
6180
						/* console.log("params.term encoded="+encodeURIComponent(params.term)); */
6181
						saveRemoteData[data.id].url = urlBase + separ + "sall=" + encodeURIComponent(params.term);';
6182
		}
6183
6184
		if(! $disableFiltering) {
6185
			$outdelayed.='
6186
6187
						if(data.text.match(new RegExp(params.term))) {
6188
							return data;
6189
						}
6190
6191
						return null;';
6192
		} else {
6193
			$outdelayed.='
6194
6195
						return data;';
6196
		}
6197
6198
		$outdelayed.='
6199
					}
6200
				});
6201
6202
				'.($callurlonselect ? '
6203
				/* Code to execute a GET when we select a value */
6204
				$(".'.$htmlname.'").change(function() {
6205
					var selected = $(".'.$htmlname.'").val();
6206
					console.log("We select "+selected)
6207
6208
					$(".'.$htmlname.'").val("");  /* reset visible combo value */
6209
					$.each( saveRemoteData, function( key, value ) {
6210
						if (key == selected)
6211
						{
6212
							console.log("selectArrayAjax - Do a redirect to "+value.url)
6213
							location.assign(value.url);
6214
						}
6215
					});
6216
				});' : '' ) . '
6217
6218
			});
6219
			</script>';
6220
6221
		if ($acceptdelayedhtml)
6222
		{
6223
			$delayedhtmlcontent.=$outdelayed;
6224
		}
6225
		else
6226
		{
6227
			$out.=$outdelayed;
6228
		}
6229
		return $out;
6230
	}
6231
6232
	/**
6233
	 *	Show a multiselect form from an array.
6234
	 *
6235
	 *	@param	string	$htmlname		Name of select
6236
	 *	@param	array	$array			Array with key+value
6237
	 *	@param	array	$selected		Array with key+value preselected
6238
	 *	@param	int		$key_in_label   1 pour afficher la key dans la valeur "[key] value"
6239
	 *	@param	int		$value_as_key   1 to use value as key
6240
	 *	@param  string	$morecss        Add more css style
6241
	 *	@param  int		$translate		Translate and encode value
6242
	 *  @param	int		$width			Force width of select box. May be used only when using jquery couch. Example: 250, 95%
6243
	 *  @param	string	$moreattrib		Add more options on select component. Example: 'disabled'
6244
	 *  @param	string	$elemtype		Type of element we show ('category', ...)
6245
	 *  @param	string	$placeholder	String to use as placeholder
6246
	 *  @param	int		$addjscombo		Add js combo
6247
	 *	@return	string					HTML multiselect string
6248
	 *  @see selectarray(), selectArrayAjax(), selectArrayFilter()
6249
	 */
6250
	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)
6251
	{
6252
		global $conf, $langs;
6253
6254
		$out = '';
6255
6256
		if ($addjscombo < 0) {
6257
		    if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $addjscombo = 1;
6258
		    else $addjscombo = 0;
6259
		}
6260
6261
		// Add code for jquery to use multiselect
6262
		if (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT'))
6263
		{
6264
			$out.="\n".'<!-- JS CODE TO ENABLE '.$tmpplugin.' for id '.$htmlname.' -->
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tmpplugin seems to be never defined.
Loading history...
6265
						<script>'."\n";
6266
			if ($addjscombo == 1)
6267
			{
6268
				$tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT;
6269
				$out.=	'function formatResult(record) {'."\n";
6270
				if ($elemtype == 'category')
6271
				{
6272
					$out.='	//return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> <a href="'.DOL_URL_ROOT.'/categories/viewcat.php?type=0&id=\'+record.id+\'">\'+record.text+\'</a></span>\';
6273
									  	return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> \'+record.text+\'</span>\';';
6274
				}
6275
				else
6276
				{
6277
					$out.='return record.text;';
6278
				}
6279
				$out.=	'};'."\n";
6280
				$out.=	'function formatSelection(record) {'."\n";
6281
				if ($elemtype == 'category')
6282
				{
6283
					$out.='	//return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> <a href="'.DOL_URL_ROOT.'/categories/viewcat.php?type=0&id=\'+record.id+\'">\'+record.text+\'</a></span>\';
6284
									  	return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> \'+record.text+\'</span>\';';
6285
				}
6286
				else
6287
				{
6288
					$out.='return record.text;';
6289
				}
6290
				$out.=	'};'."\n";
6291
				$out.=	'$(document).ready(function () {
6292
							$(\'#'.$htmlname.'\').'.$tmpplugin.'({
6293
								dir: \'ltr\',
6294
								// Specify format function for dropdown item
6295
								formatResult: formatResult,
6296
							 	templateResult: formatResult,		/* For 4.0 */
6297
								// Specify format function for selected item
6298
								formatSelection: formatSelection,
6299
							 	templateResult: formatSelection		/* For 4.0 */
6300
							});
6301
						});'."\n";
6302
			}
6303
			elseif ($addjscombo == 2)
6304
			{
6305
				// Add other js lib
6306
				// ...
6307
				$out.= '$(document).ready(function () {
6308
							$(\'#'.$htmlname.'\').multiSelect({
6309
								containerHTML: \'<div class="multi-select-container">\',
6310
								menuHTML: \'<div class="multi-select-menu">\',
6311
								buttonHTML: \'<span class="multi-select-button '.$morecss.'">\',
6312
								menuItemHTML: \'<label class="multi-select-menuitem">\',
6313
								activeClass: \'multi-select-container--open\',
6314
								noneText: \''.$placeholder.'\'
6315
							});
6316
						})';
6317
			}
6318
			$out.=	'</script>';
6319
		}
6320
6321
		// Try also magic suggest
6322
		$out .= '<select id="'.$htmlname.'" class="multiselect'.($morecss?' '.$morecss:'').'" multiple name="'.$htmlname.'[]"'.($moreattrib?' '.$moreattrib:'').($width?' style="width: '.(preg_match('/%/', $width)?$width:$width.'px').'"':'').'>'."\n";
6323
		if (is_array($array) && ! empty($array))
6324
		{
6325
			if ($value_as_key) $array=array_combine($array, $array);
6326
6327
			if (! empty($array))
6328
			{
6329
				foreach ($array as $key => $value)
6330
				{
6331
					$out.= '<option value="'.$key.'"';
6332
                    if (is_array($selected) && ! empty($selected) && in_array((string) $key, $selected) && ((string) $key != ''))
6333
					{
6334
						$out.= ' selected';
6335
					}
6336
					$out.= '>';
6337
6338
					$newval = ($translate ? $langs->trans($value) : $value);
6339
					$newval = ($key_in_label ? $key.' - '.$newval : $newval);
6340
					$out.= dol_htmlentitiesbr($newval);
6341
					$out.= '</option>'."\n";
6342
				}
6343
			}
6344
		}
6345
		$out.= '</select>'."\n";
6346
6347
		return $out;
6348
	}
6349
6350
6351
	/**
6352
	 *	Show a multiselect dropbox from an array.
6353
	 *
6354
	 *	@param	string	$htmlname		Name of HTML field
6355
	 *	@param	array	$array			Array with array of fields we could show. This array may be modified according to setup of user.
6356
	 *  @param  string  $varpage        Id of context for page. Can be set by caller with $varpage=(empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage);
6357
	 *	@return	string					HTML multiselect string
6358
	 *  @see selectarray()
6359
	 */
6360
	public static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage)
6361
	{
6362
		global $conf,$langs,$user;
6363
6364
		if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) return '';
6365
6366
		$tmpvar="MAIN_SELECTEDFIELDS_".$varpage;
6367
		if (! empty($user->conf->$tmpvar))
6368
		{
6369
			$tmparray=explode(',', $user->conf->$tmpvar);
6370
			foreach($array as $key => $val)
6371
			{
6372
				//var_dump($key);
6373
				//var_dump($tmparray);
6374
				if (in_array($key, $tmparray)) $array[$key]['checked']=1;
6375
				else $array[$key]['checked']=0;
6376
			}
6377
		}
6378
6379
		$lis='';
6380
		$listcheckedstring='';
6381
6382
		foreach($array as $key => $val)
6383
		{
6384
		   /* var_dump($val);
6385
            var_dump(array_key_exists('enabled', $val));
6386
            var_dump(!$val['enabled']);*/
6387
		   if (array_key_exists('enabled', $val) && isset($val['enabled']) && ! $val['enabled'])
6388
		   {
6389
			   unset($array[$key]);     // We don't want this field
6390
			   continue;
6391
		   }
6392
		   if ($val['label'])
6393
		   {
6394
		   	$lis.='<li><input type="checkbox" id="checkbox'.$key.'" value="'.$key.'"'.(empty($val['checked'])?'':' checked="checked"').'/><label for="checkbox'.$key.'">'.dol_escape_htmltag($langs->trans($val['label'])).'</label></li>';
6395
			   $listcheckedstring.=(empty($val['checked'])?'':$key.',');
6396
		   }
6397
		}
6398
6399
		$out ='<!-- Component multiSelectArrayWithCheckbox '.$htmlname.' -->
6400
6401
        <dl class="dropdown">
6402
            <dt>
6403
            <a href="#'.$htmlname.'">
6404
              '.img_picto('', 'list').'
6405
            </a>
6406
            <input type="hidden" class="'.$htmlname.'" name="'.$htmlname.'" value="'.$listcheckedstring.'">
6407
            </dt>
6408
            <dd class="dropdowndd">
6409
                <div class="multiselectcheckbox'.$htmlname.'">
6410
                    <ul class="ul'.$htmlname.'">
6411
                    '.$lis.'
6412
                    </ul>
6413
                </div>
6414
            </dd>
6415
        </dl>
6416
6417
        <script type="text/javascript">
6418
          jQuery(document).ready(function () {
6419
              $(\'.multiselectcheckbox'.$htmlname.' input[type="checkbox"]\').on(\'click\', function () {
6420
                  console.log("A new field was added/removed")
6421
                  $("input:hidden[name=formfilteraction]").val(\'listafterchangingselectedfields\')
6422
                  var title = $(this).val() + ",";
6423
                  if ($(this).is(\':checked\')) {
6424
                      $(\'.'.$htmlname.'\').val(title + $(\'.'.$htmlname.'\').val());
6425
                  }
6426
                  else {
6427
                      $(\'.'.$htmlname.'\').val( $(\'.'.$htmlname.'\').val().replace(title, \'\') )
6428
                  }
6429
                  // Now, we submit page
6430
                  $(this).parents(\'form:first\').submit();
6431
              });
6432
           });
6433
        </script>
6434
6435
        ';
6436
		return $out;
6437
	}
6438
6439
	/**
6440
	 * 	Render list of categories linked to object with id $id and type $type
6441
	 *
6442
	 * 	@param		int		$id				Id of object
6443
	 * 	@param		string	$type			Type of category ('member', 'customer', 'supplier', 'product', 'contact'). Old mode (0, 1, 2, ...) is deprecated.
6444
	 *  @param		int		$rendermode		0=Default, use multiselect. 1=Emulate multiselect (recommended)
6445
	 * 	@return		string					String with categories
6446
	 */
6447
    public function showCategories($id, $type, $rendermode = 0)
6448
	{
6449
		global $db;
6450
6451
		include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
6452
6453
		$cat = new Categorie($db);
6454
		$categories = $cat->containing($id, $type);
6455
6456
		if ($rendermode == 1)
6457
		{
6458
			$toprint = array();
6459
			foreach($categories as $c)
0 ignored issues
show
Bug introduced by
The expression $categories of type integer is not traversable.
Loading history...
6460
			{
6461
				$ways = $c->print_all_ways();       // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formated text
6462
				foreach($ways as $way)
6463
				{
6464
					$toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"'.($c->color?' style="background: #'.$c->color.';"':' style="background: #aaa"').'>'.img_object('', 'category').' '.$way.'</li>';
6465
				}
6466
			}
6467
			return '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
6468
		}
6469
6470
		if ($rendermode == 0)
6471
		{
6472
			$cate_arbo = $this->select_all_categories($type, '', 'parent', 64, 0, 1);
6473
			foreach($categories as $c) {
0 ignored issues
show
Bug introduced by
The expression $categories of type integer is not traversable.
Loading history...
6474
				$arrayselected[] = $c->id;
6475
			}
6476
6477
			return $this->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, '', 0, '100%', 'disabled', 'category');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $arrayselected seems to be defined by a foreach iteration on line 6473. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
6478
		}
6479
6480
		return 'ErrorBadValueForParameterRenderMode';	// Should not happened
6481
	}
6482
6483
6484
	/**
6485
	 *  Show linked object block.
6486
	 *
6487
	 *  @param	CommonObject	$object		      Object we want to show links to
6488
	 *  @param  string          $morehtmlright    More html to show on right of title
6489
	 *  @param  array           $compatibleImportElementsList  Array of compatibles elements object for "import from" action
6490
	 *  @return	int							      <0 if KO, >=0 if OK
6491
	 */
6492
    public function showLinkedObjectBlock($object, $morehtmlright = '', $compatibleImportElementsList = false)
6493
	{
6494
		global $conf,$langs,$hookmanager;
6495
		global $bc, $action;
6496
6497
		$object->fetchObjectLinked();
6498
6499
		// Bypass the default method
6500
		$hookmanager->initHooks(array('commonobject'));
6501
		$parameters=array(
6502
			'morehtmlright' => $morehtmlright,
6503
		    'compatibleImportElementsList' => &$compatibleImportElementsList,
6504
		);
6505
		$reshook=$hookmanager->executeHooks('showLinkedObjectBlock', $parameters, $object, $action);    // Note that $action and $object may have been modified by hook
6506
6507
		if (empty($reshook))
6508
		{
6509
			$nbofdifferenttypes = count($object->linkedObjects);
6510
6511
			print '<!-- showLinkedObjectBlock -->';
6512
			print load_fiche_titre($langs->trans('RelatedObjects'), $morehtmlright, '', 0, 0, 'showlinkedobjectblock');
6513
6514
6515
			print '<div class="div-table-responsive-no-min">';
6516
			print '<table class="noborder allwidth" data-block="showLinkedObject" data-element="'.$object->element.'"  data-elementid="'.$object->id.'"   >';
6517
6518
			print '<tr class="liste_titre">';
6519
			print '<td>'.$langs->trans("Type").'</td>';
6520
			print '<td>'.$langs->trans("Ref").'</td>';
6521
			print '<td class="center"></td>';
6522
			print '<td class="center">'.$langs->trans("Date").'</td>';
6523
			print '<td class="right">'.$langs->trans("AmountHTShort").'</td>';
6524
			print '<td class="right">'.$langs->trans("Status").'</td>';
6525
			print '<td></td>';
6526
			print '</tr>';
6527
6528
			$nboftypesoutput=0;
6529
6530
			foreach($object->linkedObjects as $objecttype => $objects)
6531
			{
6532
				$tplpath = $element = $subelement = $objecttype;
6533
6534
				// to display inport button on tpl
6535
				$showImportButton=false;
6536
				if(!empty($compatibleImportElementsList) && in_array($element, $compatibleImportElementsList)){
6537
				    $showImportButton=true;
6538
				}
6539
6540
				$regs = array();
6541
				if ($objecttype != 'supplier_proposal' && preg_match('/^([^_]+)_([^_]+)/i', $objecttype, $regs))
6542
				{
6543
					$element = $regs[1];
6544
					$subelement = $regs[2];
6545
					$tplpath = $element.'/'.$subelement;
6546
				}
6547
				$tplname='linkedobjectblock';
6548
6549
				// To work with non standard path
6550
				if ($objecttype == 'facture')          {
6551
					$tplpath = 'compta/'.$element;
6552
					if (empty($conf->facture->enabled)) continue;	// Do not show if module disabled
6553
				}
6554
				elseif ($objecttype == 'facturerec')          {
6555
					$tplpath = 'compta/facture';
6556
					$tplname = 'linkedobjectblockForRec';
6557
					if (empty($conf->facture->enabled)) continue;	// Do not show if module disabled
6558
				}
6559
				elseif ($objecttype == 'propal')           {
6560
					$tplpath = 'comm/'.$element;
6561
					if (empty($conf->propal->enabled)) continue;	// Do not show if module disabled
6562
				}
6563
				elseif ($objecttype == 'supplier_proposal')           {
6564
					if (empty($conf->supplier_proposal->enabled)) continue;	// Do not show if module disabled
6565
				}
6566
				elseif ($objecttype == 'shipping' || $objecttype == 'shipment') {
6567
					$tplpath = 'expedition';
6568
					if (empty($conf->expedition->enabled)) continue;	// Do not show if module disabled
6569
				}
6570
        		elseif ($objecttype == 'reception') {
6571
        			$tplpath = 'reception';
6572
        			if (empty($conf->reception->enabled)) continue;	// Do not show if module disabled
6573
        		}
6574
				elseif ($objecttype == 'delivery')         {
6575
					$tplpath = 'livraison';
6576
					if (empty($conf->expedition->enabled)) continue;	// Do not show if module disabled
6577
				}
6578
				elseif ($objecttype == 'invoice_supplier') {
6579
					$tplpath = 'fourn/facture';
6580
				}
6581
				elseif ($objecttype == 'order_supplier')   {
6582
					$tplpath = 'fourn/commande';
6583
				}
6584
				elseif ($objecttype == 'expensereport')   {
6585
					$tplpath = 'expensereport';
6586
				}
6587
				elseif ($objecttype == 'subscription')   {
6588
					$tplpath = 'adherents';
6589
				}
6590
6591
				global $linkedObjectBlock;
6592
				$linkedObjectBlock = $objects;
6593
6594
6595
				// Output template part (modules that overwrite templates must declare this into descriptor)
6596
				$dirtpls=array_merge($conf->modules_parts['tpl'], array('/'.$tplpath.'/tpl'));
6597
				foreach($dirtpls as $reldir)
6598
				{
6599
					if ($nboftypesoutput == ($nbofdifferenttypes - 1))    // No more type to show after
6600
					{
6601
						global $noMoreLinkedObjectBlockAfter;
6602
						$noMoreLinkedObjectBlockAfter=1;
6603
					}
6604
6605
					$res=@include dol_buildpath($reldir.'/'.$tplname.'.tpl.php');
6606
					if ($res)
6607
					{
6608
						$nboftypesoutput++;
6609
						break;
6610
					}
6611
				}
6612
			}
6613
6614
			if (! $nboftypesoutput)
6615
			{
6616
				print '<tr><td class="impair opacitymedium" colspan="7">'.$langs->trans("None").'</td></tr>';
6617
			}
6618
6619
			print '</table>';
6620
6621
			if (!empty($compatibleImportElementsList))
6622
			{
6623
			    $res=@include dol_buildpath('core/tpl/ajax/objectlinked_lineimport.tpl.php');
6624
			}
6625
6626
6627
			print '</div>';
6628
6629
			return $nbofdifferenttypes;
6630
		}
6631
	}
6632
6633
	/**
6634
	 *  Show block with links to link to other objects.
6635
	 *
6636
	 *  @param	CommonObject	$object				Object we want to show links to
6637
	 *  @param	array			$restrictlinksto	Restrict links to some elements, for exemple array('order') or array('supplier_order'). null or array() if no restriction.
6638
	 *  @param	array			$excludelinksto		Do not show links of this type, for exemple array('order') or array('supplier_order'). null or array() if no exclusion.
6639
	 *  @return	string								<0 if KO, >0 if OK
6640
	 */
6641
    public function showLinkToObjectBlock($object, $restrictlinksto = array(), $excludelinksto = array())
6642
	{
6643
		global $conf, $langs, $hookmanager;
6644
		global $bc, $action;
6645
6646
		$linktoelem='';
6647
		$linktoelemlist='';
6648
		$listofidcompanytoscan='';
6649
6650
		if (! is_object($object->thirdparty)) $object->fetch_thirdparty();
6651
6652
		$possiblelinks=array();
6653
		if (is_object($object->thirdparty) && ! empty($object->thirdparty->id) && $object->thirdparty->id > 0)
6654
		{
6655
			$listofidcompanytoscan=$object->thirdparty->id;
6656
			if (($object->thirdparty->parent > 0) && ! empty($conf->global->THIRDPARTY_INCLUDE_PARENT_IN_LINKTO)) $listofidcompanytoscan.=','.$object->thirdparty->parent;
6657
			if (($object->fk_project > 0) && ! empty($conf->global->THIRDPARTY_INCLUDE_PROJECT_THIRDPARY_IN_LINKTO))
6658
			{
6659
				include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
6660
				$tmpproject=new Project($this->db);
6661
				$tmpproject->fetch($object->fk_project);
6662
				if ($tmpproject->socid > 0 && ($tmpproject->socid != $object->thirdparty->id)) $listofidcompanytoscan.=','.$tmpproject->socid;
6663
				unset($tmpproject);
6664
			}
6665
6666
			$possiblelinks=array(
6667
				'propal'=>array('enabled'=>$conf->propal->enabled, 'perms'=>1, 'label'=>'LinkToProposal', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."propal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('propal').')'),
6668
				'order'=>array('enabled'=>$conf->commande->enabled, 'perms'=>1, 'label'=>'LinkToOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."commande as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('commande').')'),
6669
				'invoice'=>array('enabled'=>$conf->facture->enabled, 'perms'=>1, 'label'=>'LinkToInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."facture as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('invoice').')'),
6670
				'invoice_template'=>array('enabled'=>$conf->facture->enabled, 'perms'=>1, 'label'=>'LinkToTemplateInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.titre as ref, t.total as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."facture_rec as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('invoice').')'),
6671
				'contrat'=>array('enabled'=>$conf->contrat->enabled , 'perms'=>1, 'label'=>'LinkToContract', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, '' as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."contrat as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('contract').')'),
6672
				'fichinter'=>array('enabled'=>$conf->ficheinter->enabled, 'perms'=>1, 'label'=>'LinkToIntervention', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."fichinter as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('intervention').')'),
6673
				'supplier_proposal'=>array('enabled'=>$conf->supplier_proposal->enabled , 'perms'=>1, 'label'=>'LinkToSupplierProposal', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, '' as ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."supplier_proposal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('supplier_proposal').')'),
6674
				'order_supplier'=>array('enabled'=>$conf->supplier_order->enabled , 'perms'=>1, 'label'=>'LinkToSupplierOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('commande_fournisseur').')'),
6675
				'invoice_supplier'=>array('enabled'=>$conf->supplier_invoice->enabled , 'perms'=>1, 'label'=>'LinkToSupplierInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."facture_fourn as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('facture_fourn').')'),
6676
				'ticket'=>array('enabled'=>$conf->ticket->enabled , 'perms'=>1, 'label'=>'LinkToTicket', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.track_id, '0' as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."ticket as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('ticket').')')
6677
			);
6678
		}
6679
6680
		// Can complete the possiblelink array
6681
		$hookmanager->initHooks(array('commonobject'));
6682
		$parameters=array('listofidcompanytoscan' => $listofidcompanytoscan);
6683
6684
		if (! empty($listofidcompanytoscan))  // If empty, we don't have criteria to scan the object we can link to
6685
		{
6686
            $reshook=$hookmanager->executeHooks('showLinkToObjectBlock', $parameters, $object, $action);    // Note that $action and $object may have been modified by hook
6687
		}
6688
6689
		if (empty($reshook))
6690
		{
6691
			if (is_array($hookmanager->resArray) && count($hookmanager->resArray))
6692
			{
6693
				$possiblelinks=array_merge($possiblelinks, $hookmanager->resArray);
6694
			}
6695
		}
6696
		elseif ($reshook > 0)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $reshook does not seem to be defined for all execution paths leading up to this point.
Loading history...
6697
		{
6698
			if (is_array($hookmanager->resArray) && count($hookmanager->resArray))
6699
			{
6700
				$possiblelinks=$hookmanager->resArray;
6701
			}
6702
		}
6703
6704
		foreach($possiblelinks as $key => $possiblelink)
6705
		{
6706
			$num = 0;
6707
6708
			if (empty($possiblelink['enabled'])) continue;
6709
6710
			if (! empty($possiblelink['perms']) && (empty($restrictlinksto) || in_array($key, $restrictlinksto)) && (empty($excludelinksto) || ! in_array($key, $excludelinksto)))
6711
			{
6712
				print '<div id="'.$key.'list"'.(empty($conf->use_javascript_ajax)?'':' style="display:none"').'>';
6713
				$sql = $possiblelink['sql'];
6714
6715
				$resqllist = $this->db->query($sql);
6716
				if ($resqllist)
6717
				{
6718
					$num = $this->db->num_rows($resqllist);
6719
					$i = 0;
6720
6721
					print '<br>';
6722
					print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formlinked'.$key.'">';
6723
					print '<input type="hidden" name="action" value="addlink">';
6724
					print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
6725
					print '<input type="hidden" name="id" value="'.$object->id.'">';
6726
					print '<input type="hidden" name="addlink" value="'.$key.'">';
6727
					print '<table class="noborder">';
6728
					print '<tr class="liste_titre">';
6729
					print '<td class="nowrap"></td>';
6730
					print '<td class="center">' . $langs->trans("Ref") . '</td>';
6731
					print '<td class="left">' . $langs->trans("RefCustomer") . '</td>';
6732
					print '<td class="right">' . $langs->trans("AmountHTShort") . '</td>';
6733
					print '<td class="left">' . $langs->trans("Company") . '</td>';
6734
					print '</tr>';
6735
					while ($i < $num)
6736
					{
6737
						$objp = $this->db->fetch_object($resqllist);
6738
6739
						print '<tr class="oddeven">';
6740
						print '<td class="left">';
6741
						print '<input type="radio" name="idtolinkto" value=' . $objp->rowid . '>';
6742
						print '</td>';
6743
						print '<td class="center">' . $objp->ref . '</td>';
6744
						print '<td>' . $objp->ref_client . '</td>';
6745
						print '<td class="right">' . price($objp->total_ht) . '</td>';
6746
						print '<td>' . $objp->name . '</td>';
6747
						print '</tr>';
6748
						$i++;
6749
					}
6750
					print '</table>';
6751
					print '<div class="center"><input type="submit" class="button valignmiddle" value="' . $langs->trans('ToLink') . '">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="submit" class="button" name="cancel" value="' . $langs->trans('Cancel') . '"></div>';
6752
6753
					print '</form>';
6754
					$this->db->free($resqllist);
6755
				} else {
6756
					dol_print_error($this->db);
6757
				}
6758
				print '</div>';
6759
				if ($num > 0)
6760
				{
6761
				}
6762
6763
				//$linktoelem.=($linktoelem?' &nbsp; ':'');
6764
				if ($num > 0) $linktoelemlist.='<li><a href="#linkto'.$key.'" class="linkto dropdowncloseonclick" rel="'.$key.'">' . $langs->trans($possiblelink['label']) .' ('.$num.')</a></li>';
6765
				//else $linktoelem.=$langs->trans($possiblelink['label']);
6766
				else $linktoelemlist.='<li><span class="linktodisabled">' . $langs->trans($possiblelink['label']) . ' (0)</span></li>';
6767
			}
6768
		}
6769
6770
		if ($linktoelemlist)
6771
		{
6772
			$linktoelem='
6773
    		<dl class="dropdown" id="linktoobjectname">
6774
    		';
6775
			if (! empty($conf->use_javascript_ajax)) $linktoelem.='<dt><a href="#linktoobjectname">'.$langs->trans("LinkTo").'...</a></dt>';
6776
			$linktoelem.='<dd>
6777
    		<div class="multiselectlinkto">
6778
    		<ul class="ulselectedfields">'.$linktoelemlist.'
6779
    		</ul>
6780
    		</div>
6781
    		</dd>
6782
    		</dl>';
6783
		}
6784
		else
6785
		{
6786
			$linktoelem='';
6787
		}
6788
6789
		if (! empty($conf->use_javascript_ajax))
6790
		{
6791
		  print '<!-- Add js to show linkto box -->
6792
				<script>
6793
				jQuery(document).ready(function() {
6794
					jQuery(".linkto").click(function() {
6795
						console.log("We choose to show/hide link for rel="+jQuery(this).attr(\'rel\'));
6796
					    jQuery("#"+jQuery(this).attr(\'rel\')+"list").toggle();
6797
						jQuery(this).toggle();
6798
					});
6799
				});
6800
				</script>
6801
		  ';
6802
		}
6803
6804
		return $linktoelem;
6805
	}
6806
6807
	/**
6808
	 *	Return an html string with a select combo box to choose yes or no
6809
	 *
6810
	 *	@param	string		$htmlname		Name of html select field
6811
	 *	@param	string		$value			Pre-selected value
6812
	 *	@param	int			$option			0 return yes/no, 1 return 1/0
6813
	 *	@param	bool		$disabled		true or false
6814
	 *  @param	int      	$useempty		1=Add empty line
6815
	 *	@return	string						See option
6816
	 */
6817
    public function selectyesno($htmlname, $value = '', $option = 0, $disabled = false, $useempty = 0)
6818
	{
6819
		global $langs;
6820
6821
		$yes="yes"; $no="no";
6822
		if ($option)
6823
		{
6824
			$yes="1";
6825
			$no="0";
6826
		}
6827
6828
		$disabled = ($disabled ? ' disabled' : '');
6829
6830
		$resultyesno = '<select class="flat width75" id="'.$htmlname.'" name="'.$htmlname.'"'.$disabled.'>'."\n";
6831
		if ($useempty) $resultyesno .= '<option value="-1"'.(($value < 0)?' selected':'').'>&nbsp;</option>'."\n";
6832
		if (("$value" == 'yes') || ($value == 1))
6833
		{
6834
			$resultyesno .= '<option value="'.$yes.'" selected>'.$langs->trans("Yes").'</option>'."\n";
6835
			$resultyesno .= '<option value="'.$no.'">'.$langs->trans("No").'</option>'."\n";
6836
		}
6837
		else
6838
	   {
6839
	   		$selected=(($useempty && $value != '0' && $value != 'no')?'':' selected');
6840
			$resultyesno .= '<option value="'.$yes.'">'.$langs->trans("Yes").'</option>'."\n";
6841
			$resultyesno .= '<option value="'.$no.'"'.$selected.'>'.$langs->trans("No").'</option>'."\n";
6842
		}
6843
		$resultyesno .= '</select>'."\n";
6844
		return $resultyesno;
6845
	}
6846
6847
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
6848
	/**
6849
	 *  Return list of export templates
6850
	 *
6851
	 *  @param	string	$selected          Id modele pre-selectionne
6852
	 *  @param  string	$htmlname          Name of HTML select
6853
	 *  @param  string	$type              Type of searched templates
6854
	 *  @param  int		$useempty          Affiche valeur vide dans liste
6855
	 *  @return	void
6856
	 */
6857
    public function select_export_model($selected = '', $htmlname = 'exportmodelid', $type = '', $useempty = 0)
6858
	{
6859
        // phpcs:enable
6860
		$sql = "SELECT rowid, label";
6861
		$sql.= " FROM ".MAIN_DB_PREFIX."export_model";
6862
		$sql.= " WHERE type = '".$type."'";
6863
		$sql.= " ORDER BY rowid";
6864
		$result = $this->db->query($sql);
6865
		if ($result)
6866
		{
6867
			print '<select class="flat" id="select_'.$htmlname.'" name="'.$htmlname.'">';
6868
			if ($useempty)
6869
			{
6870
				print '<option value="-1">&nbsp;</option>';
6871
			}
6872
6873
			$num = $this->db->num_rows($result);
6874
			$i = 0;
6875
			while ($i < $num)
6876
			{
6877
				$obj = $this->db->fetch_object($result);
6878
				if ($selected == $obj->rowid)
6879
				{
6880
					print '<option value="'.$obj->rowid.'" selected>';
6881
				}
6882
				else
6883
				{
6884
					print '<option value="'.$obj->rowid.'">';
6885
				}
6886
				print $obj->label;
6887
				print '</option>';
6888
				$i++;
6889
			}
6890
			print "</select>";
6891
		}
6892
		else {
6893
			dol_print_error($this->db);
6894
		}
6895
	}
6896
6897
	/**
6898
	 *    Return a HTML area with the reference of object and a navigation bar for a business object
6899
	 *    Note: To complete search with a particular filter on select, you can set $object->next_prev_filter set to define SQL criterias.
6900
	 *
6901
	 *    @param	object	$object			Object to show.
6902
	 *    @param	string	$paramid   		Name of parameter to use to name the id into the URL next/previous link.
6903
	 *    @param	string	$morehtml  		More html content to output just before the nav bar.
6904
	 *    @param	int		$shownav	  	Show Condition (navigation is shown if value is 1).
6905
	 *    @param	string	$fieldid   		Name of field id into database to use for select next and previous (we make the select max and min on this field compared to $object->ref). Use 'none' to disable next/prev.
6906
	 *    @param	string	$fieldref   	Name of field ref of object (object->ref) to show or 'none' to not show ref.
6907
	 *    @param	string	$morehtmlref  	More html to show after ref.
6908
	 *    @param	string	$moreparam  	More param to add in nav link url. Must start with '&...'.
6909
	 *	  @param	int		$nodbprefix		Do not include DB prefix to forge table name.
6910
	 *	  @param	string	$morehtmlleft	More html code to show before ref.
6911
	 *	  @param	string	$morehtmlstatus	More html code to show under navigation arrows (status place).
6912
	 *	  @param	string	$morehtmlright	More html code to show after ref.
6913
	 * 	  @return	string    				Portion HTML with ref + navigation buttons
6914
	 */
6915
    public function showrefnav($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $morehtmlright = '')
6916
	{
6917
		global $langs,$conf,$hookmanager;
6918
6919
		$ret='';
6920
		if (empty($fieldid))  $fieldid='rowid';
6921
		if (empty($fieldref)) $fieldref='ref';
6922
6923
		// Add where from hooks
6924
		if (is_object($hookmanager))
6925
		{
6926
			$parameters=array();
6927
			$reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters, $object);    // Note that $action and $object may have been modified by hook
6928
			$object->next_prev_filter.=$hookmanager->resPrint;
6929
		}
6930
		$previous_ref = $next_ref = '';
6931
		if ($shownav)
6932
		{
6933
			//print "paramid=$paramid,morehtml=$morehtml,shownav=$shownav,$fieldid,$fieldref,$morehtmlref,$moreparam";
6934
			$object->load_previous_next_ref((isset($object->next_prev_filter)?$object->next_prev_filter:''), $fieldid, $nodbprefix);
6935
6936
			$navurl = $_SERVER["PHP_SELF"];
6937
			// Special case for project/task page
6938
			if ($paramid == 'project_ref')
6939
			{
6940
			    if (preg_match('/\/tasks\/(task|contact|note|document)\.php/', $navurl))     // TODO Remove this when nav with project_ref on task pages are ok
6941
			    {
6942
				    $navurl = preg_replace('/\/tasks\/(task|contact|time|note|document)\.php/', '/tasks.php', $navurl);
6943
    				$paramid='ref';
6944
			    }
6945
			}
6946
6947
			// accesskey is for Windows or Linux:  ALT + key for chrome, ALT + SHIFT + KEY for firefox
6948
			// accesskey is for Mac:               CTRL + key for all browsers
6949
			$stringforfirstkey = $langs->trans("KeyboardShortcut");
6950
			if ($conf->browser->name == 'chrome')
6951
			{
6952
				$stringforfirstkey .= ' ALT +';
6953
			}
6954
			elseif ($conf->browser->name == 'firefox')
6955
			{
6956
				$stringforfirstkey .= ' ALT + SHIFT +';
6957
			}
6958
			else
6959
			{
6960
				$stringforfirstkey .= ' CTL +';
6961
			}
6962
6963
			$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>';
6964
			$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>';
6965
		}
6966
6967
		//print "xx".$previous_ref."x".$next_ref;
6968
		$ret.='<!-- Start banner content --><div style="vertical-align: middle">';
6969
6970
		// Right part of banner
6971
		if ($morehtmlright) $ret.='<div class="inline-block floatleft">'.$morehtmlright.'</div>';
6972
6973
		if ($previous_ref || $next_ref || $morehtml)
6974
		{
6975
			$ret.='<div class="pagination paginationref"><ul class="right">';
6976
		}
6977
		if ($morehtml)
6978
		{
6979
			$ret.='<li class="noborder litext">'.$morehtml.'</li>';
6980
		}
6981
		if ($shownav && ($previous_ref || $next_ref))
6982
		{
6983
			$ret.='<li class="pagination">'.$previous_ref.'</li>';
6984
			$ret.='<li class="pagination">'.$next_ref.'</li>';
6985
		}
6986
		if ($previous_ref || $next_ref || $morehtml)
6987
		{
6988
			$ret.='</ul></div>';
6989
		}
6990
6991
		$parameters=array();
6992
		$reshook=$hookmanager->executeHooks('moreHtmlStatus', $parameters, $object);    // Note that $action and $object may have been modified by hook
6993
		if (empty($reshook)) $morehtmlstatus.=$hookmanager->resPrint;
6994
		else $morehtmlstatus=$hookmanager->resPrint;
6995
		if ($morehtmlstatus) $ret.='<div class="statusref">'.$morehtmlstatus.'</div>';
6996
6997
		$parameters = array();
6998
		$reshook = $hookmanager->executeHooks('moreHtmlRef', $parameters, $object); // Note that $action and $object may have been modified by hook
6999
		if (empty($reshook)) $morehtmlref.=$hookmanager->resPrint;
7000
		elseif ($reshook > 0) $morehtmlref=$hookmanager->resPrint;
7001
7002
		// Left part of banner
7003
		if ($morehtmlleft)
7004
		{
7005
			if ($conf->browser->layout == 'phone') $ret.='<div class="floatleft">'.$morehtmlleft.'</div>';    // class="center" to have photo in middle
7006
			else $ret.='<div class="inline-block floatleft">'.$morehtmlleft.'</div>';
7007
		}
7008
7009
		//if ($conf->browser->layout == 'phone') $ret.='<div class="clearboth"></div>';
7010
		$ret.='<div class="inline-block floatleft valignmiddle refid'.(($shownav && ($previous_ref || $next_ref))?' refidpadding':'').'">';
7011
7012
		// For thirdparty, contact, user, member, the ref is the id, so we show something else
7013
		if ($object->element == 'societe')
7014
		{
7015
			$ret.=dol_htmlentities($object->name);
7016
		}
7017
		elseif ($object->element == 'member')
7018
		{
7019
			$ret.=$object->ref.'<br>';
7020
			$fullname=$object->getFullName($langs);
7021
			if ($object->morphy == 'mor' && $object->societe) {
7022
				$ret.= dol_htmlentities($object->societe) . ((! empty($fullname) && $object->societe != $fullname)?' ('.dol_htmlentities($fullname).')':'');
7023
			} else {
7024
				$ret.= dol_htmlentities($fullname) . ((! empty($object->societe) && $object->societe != $fullname)?' ('.dol_htmlentities($object->societe).')':'');
7025
			}
7026
		}
7027
		elseif (in_array($object->element, array('contact', 'user', 'usergroup')))
7028
		{
7029
			$ret.=dol_htmlentities($object->getFullName($langs));
7030
		}
7031
		elseif (in_array($object->element, array('action', 'agenda')))
7032
		{
7033
			$ret.=$object->ref.'<br>'.$object->label;
7034
		}
7035
		elseif (in_array($object->element, array('adherent_type')))
7036
		{
7037
			$ret.=$object->label;
7038
		}
7039
		elseif ($object->element == 'ecm_directories')
7040
		{
7041
			$ret.='';
7042
		}
7043
		elseif ($fieldref != 'none') $ret.=dol_htmlentities($object->$fieldref);
7044
7045
7046
		if ($morehtmlref)
7047
		{
7048
			$ret.=' '.$morehtmlref;
7049
		}
7050
		$ret.='</div>';
7051
7052
		$ret.='</div><!-- End banner content -->';
7053
7054
		return $ret;
7055
	}
7056
7057
7058
	/**
7059
	 *    	Return HTML code to output a barcode
7060
	 *
7061
	 *     	@param	Object	$object		Object containing data to retrieve file name
7062
	 * 		@param	int		$width			Width of photo
7063
	 * 	  	@return string    				HTML code to output barcode
7064
	 */
7065
    public function showbarcode(&$object, $width = 100)
7066
	{
7067
		global $conf;
7068
7069
		//Check if barcode is filled in the card
7070
		if (empty($object->barcode)) return '';
7071
7072
		// Complete object if not complete
7073
		if (empty($object->barcode_type_code) || empty($object->barcode_type_coder))
7074
		{
7075
			$result = $object->fetch_barcode();
7076
			//Check if fetch_barcode() failed
7077
			if ($result < 1) return '<!-- ErrorFetchBarcode -->';
7078
		}
7079
7080
		// Barcode image
7081
		$url=DOL_URL_ROOT.'/viewimage.php?modulepart=barcode&generator='.urlencode($object->barcode_type_coder).'&code='.urlencode($object->barcode).'&encoding='.urlencode($object->barcode_type_code);
7082
		$out ='<!-- url barcode = '.$url.' -->';
7083
		$out.='<img src="'.$url.'">';
7084
		return $out;
7085
	}
7086
7087
	/**
7088
	 *    	Return HTML code to output a photo
7089
	 *
7090
	 *    	@param	string		$modulepart			Key to define module concerned ('societe', 'userphoto', 'memberphoto')
7091
	 *     	@param  object		$object				Object containing data to retrieve file name
7092
	 * 		@param	int			$width				Width of photo
7093
	 * 		@param	int			$height				Height of photo (auto if 0)
7094
	 * 		@param	int			$caneditfield		Add edit fields
7095
	 * 		@param	string		$cssclass			CSS name to use on img for photo
7096
	 * 		@param	string		$imagesize		    'mini', 'small' or '' (original)
7097
	 *      @param  int         $addlinktofullsize  Add link to fullsize image
7098
	 *      @param  int         $cache              1=Accept to use image in cache
7099
	 *      @param	string		$forcecapture		Force parameter capture on HTML input file element to ask a smartphone to allow to open camera to take photo. Auto if empty.
7100
	 * 	  	@return string    						HTML code to output photo
7101
	 */
7102
	public static function showphoto($modulepart, $object, $width = 100, $height = 0, $caneditfield = 0, $cssclass = 'photowithmargin', $imagesize = '', $addlinktofullsize = 1, $cache = 0, $forcecapture = '')
7103
	{
7104
		global $conf,$langs;
7105
7106
		$entity = (! empty($object->entity) ? $object->entity : $conf->entity);
7107
		$id = (! empty($object->id) ? $object->id : $object->rowid);
7108
7109
		$ret='';$dir='';$file='';$originalfile='';$altfile='';$email='';$capture='';
7110
		if ($modulepart=='societe')
7111
		{
7112
			$dir=$conf->societe->multidir_output[$entity];
7113
			if (! empty($object->logo))
7114
			{
7115
				if ((string) $imagesize == 'mini') $file=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.getImageFileNameForSize($object->logo, '_mini');             // getImageFileNameForSize include the thumbs
7116
				elseif ((string) $imagesize == 'small') $file=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.getImageFileNameForSize($object->logo, '_small');
7117
				else $file=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.$object->logo;
7118
				$originalfile=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.$object->logo;
7119
			}
7120
			$email=$object->email;
7121
		}
7122
		elseif ($modulepart=='contact')
7123
		{
7124
			$dir=$conf->societe->multidir_output[$entity].'/contact';
7125
			if (! empty($object->photo))
7126
			{
7127
				if ((string) $imagesize == 'mini') $file=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.getImageFileNameForSize($object->photo, '_mini');
7128
				elseif ((string) $imagesize == 'small') $file=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.getImageFileNameForSize($object->photo, '_small');
7129
				else $file=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.$object->photo;
7130
				$originalfile=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.$object->photo;
7131
			}
7132
			$email=$object->email;
7133
			$capture='user';
7134
		}
7135
		elseif ($modulepart=='userphoto')
7136
		{
7137
			$dir=$conf->user->dir_output;
7138
			if (! empty($object->photo))
7139
			{
7140
				if ((string) $imagesize == 'mini') $file=get_exdir(0, 0, 0, 0, $object, 'user').$object->id.'/'.getImageFileNameForSize($object->photo, '_mini');
7141
				elseif ((string) $imagesize == 'small') $file=get_exdir(0, 0, 0, 0, $object, 'user').$object->id.'/'.getImageFileNameForSize($object->photo, '_small');
7142
				else $file=get_exdir(0, 0, 0, 0, $object, 'user').'/'.$object->id.'/'.$object->photo;
7143
				$originalfile=get_exdir(0, 0, 0, 0, $object, 'user').'/'.$object->id.'/'.$object->photo;
7144
			}
7145
			if (! empty($conf->global->MAIN_OLD_IMAGE_LINKS)) $altfile=$object->id.".jpg";	// For backward compatibility
7146
			$email=$object->email;
7147
			$capture='user';
7148
		}
7149
		elseif ($modulepart=='memberphoto')
7150
		{
7151
			$dir=$conf->adherent->dir_output;
7152
			if (! empty($object->photo))
7153
			{
7154
				if ((string) $imagesize == 'mini') $file=get_exdir(0, 0, 0, 0, $object, 'member').'photos/'.getImageFileNameForSize($object->photo, '_mini');
7155
				elseif ((string) $imagesize == 'small') $file=get_exdir(0, 0, 0, 0, $object, 'member').'photos/'.getImageFileNameForSize($object->photo, '_small');
7156
				else $file=get_exdir(0, 0, 0, 0, $object, 'member').'photos/'.$object->photo;
7157
				$originalfile=get_exdir(0, 0, 0, 0, $object, 'member').'photos/'.$object->photo;
7158
			}
7159
			if (! empty($conf->global->MAIN_OLD_IMAGE_LINKS)) $altfile=$object->id.".jpg";	// For backward compatibility
7160
			$email=$object->email;
7161
			$capture='user';
7162
		}
7163
		else
7164
		{
7165
			// Generic case to show photos
7166
			$dir=$conf->$modulepart->dir_output;
7167
			if (! empty($object->photo))
7168
			{
7169
				if ((string) $imagesize == 'mini') $file=get_exdir($id, 2, 0, 0, $object, $modulepart).'photos/'.getImageFileNameForSize($object->photo, '_mini');
7170
				elseif ((string) $imagesize == 'small') $file=get_exdir($id, 2, 0, 0, $object, $modulepart).'photos/'.getImageFileNameForSize($object->photo, '_small');
7171
				else $file=get_exdir($id, 2, 0, 0, $object, $modulepart).'photos/'.$object->photo;
7172
				$originalfile=get_exdir($id, 2, 0, 0, $object, $modulepart).'photos/'.$object->photo;
7173
			}
7174
			if (! empty($conf->global->MAIN_OLD_IMAGE_LINKS)) $altfile=$object->id.".jpg";	// For backward compatibility
7175
			$email=$object->email;
7176
		}
7177
7178
		if ($forcecapture) $capture = $forcecapture;
7179
7180
		if ($dir)
7181
		{
7182
			if ($file && file_exists($dir."/".$file))
7183
			{
7184
				if ($addlinktofullsize)
7185
				{
7186
					$urladvanced=getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity='.$entity);
7187
					if ($urladvanced) $ret.='<a href="'.$urladvanced.'">';
7188
					else $ret.='<a href="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$entity.'&file='.urlencode($originalfile).'&cache='.$cache.'">';
7189
				}
7190
				$ret.='<img class="photo'.$modulepart.($cssclass?' '.$cssclass:'').'" alt="Photo" id="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.'">';
7191
				if ($addlinktofullsize) $ret.='</a>';
7192
			}
7193
			elseif ($altfile && file_exists($dir."/".$altfile))
7194
			{
7195
				if ($addlinktofullsize)
7196
				{
7197
					$urladvanced=getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity='.$entity);
7198
					if ($urladvanced) $ret.='<a href="'.$urladvanced.'">';
7199
					else $ret.='<a href="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$entity.'&file='.urlencode($originalfile).'&cache='.$cache.'">';
7200
				}
7201
				$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.'">';
7202
				if ($addlinktofullsize) $ret.='</a>';
7203
			}
7204
			else
7205
			{
7206
				$nophoto='/public/theme/common/nophoto.png';
7207
				if (in_array($modulepart, array('userphoto','contact')))	// For module that are "physical" users
7208
				{
7209
					$nophoto='/public/theme/common/user_anonymous.png';
7210
					if ($object->gender == 'man') $nophoto='/public/theme/common/user_man.png';
7211
					if ($object->gender == 'woman') $nophoto='/public/theme/common/user_woman.png';
7212
				}
7213
7214
				if (! empty($conf->gravatar->enabled) && $email)
7215
				{
7216
					/**
7217
					 * @see https://gravatar.com/site/implement/images/php/
7218
					 */
7219
					global $dolibarr_main_url_root;
7220
					$ret.='<!-- Put link to gravatar -->';
7221
					//$defaultimg=urlencode(dol_buildpath($nophoto,3));
7222
					$defaultimg='mm';
7223
					$ret.='<img class="photo'.$modulepart.($cssclass?' '.$cssclass:'').'" alt="Gravatar avatar" title="'.$email.' Gravatar avatar" '.($width?' width="'.$width.'"':'').($height?' height="'.$height.'"':'').' src="https://www.gravatar.com/avatar/'.dol_hash(strtolower(trim($email)), 3).'?s='.$width.'&d='.$defaultimg.'">';	// gravatar need md5 hash
7224
				}
7225
				else
7226
				{
7227
					$ret.='<img class="photo'.$modulepart.($cssclass?' '.$cssclass:'').'" alt="No photo" '.($width?' width="'.$width.'"':'').($height?' height="'.$height.'"':'').' src="'.DOL_URL_ROOT.$nophoto.'">';
7228
				}
7229
			}
7230
7231
			if ($caneditfield)
7232
			{
7233
				if ($object->photo) $ret.="<br>\n";
7234
				$ret.='<table class="nobordernopadding centpercent">';
7235
				if ($object->photo) $ret.='<tr><td><input type="checkbox" class="flat photodelete" name="deletephoto" id="photodelete"> '.$langs->trans("Delete").'<br><br></td></tr>';
7236
				$ret.='<tr><td class="tdoverflow"><input type="file" class="flat maxwidth200onsmartphone" name="photo" id="photoinput" accept="image/*"'.($capture?' capture="'.$capture.'"':'').'></td></tr>';
7237
				$ret.='</table>';
7238
			}
7239
		}
7240
		else dol_print_error('', 'Call of showphoto with wrong parameters modulepart='.$modulepart);
7241
7242
		return $ret;
7243
	}
7244
7245
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
7246
	/**
7247
	 *	Return select list of groups
7248
	 *
7249
	 *  @param	string	$selected       Id group preselected
7250
	 *  @param  string	$htmlname       Field name in form
7251
	 *  @param  int		$show_empty     0=liste sans valeur nulle, 1=ajoute valeur inconnue
7252
	 *  @param  string	$exclude        Array list of groups id to exclude
7253
	 * 	@param	int		$disabled		If select list must be disabled
7254
	 *  @param  string	$include        Array list of groups id to include
7255
	 * 	@param	int		$enableonly		Array list of groups id to be enabled. All other must be disabled
7256
	 * 	@param	string	$force_entity	'0' or Ids of environment to force
7257
	 * 	@param	bool	$multiple		add [] in the name of element and add 'multiple' attribut (not working with ajax_autocompleter)
7258
	 *  @return	string
7259
	 *  @see select_dolusers()
7260
	 */
7261
    public function select_dolgroups($selected = '', $htmlname = 'groupid', $show_empty = 0, $exclude = '', $disabled = 0, $include = '', $enableonly = '', $force_entity = '0', $multiple = false)
7262
	{
7263
        // phpcs:enable
7264
		global $conf,$user,$langs;
7265
7266
		// Permettre l'exclusion de groupes
7267
		if (is_array($exclude))	$excludeGroups = implode("','", $exclude);
0 ignored issues
show
introduced by
The condition is_array($exclude) is always false.
Loading history...
7268
		// Permettre l'inclusion de groupes
7269
		if (is_array($include))	$includeGroups = implode("','", $include);
0 ignored issues
show
introduced by
The condition is_array($include) is always false.
Loading history...
7270
7271
		if (!is_array($selected)) $selected = array($selected);
0 ignored issues
show
introduced by
The condition is_array($selected) is always false.
Loading history...
7272
7273
		$out='';
7274
7275
		// On recherche les groupes
7276
		$sql = "SELECT ug.rowid, ug.nom as name";
7277
		if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
7278
		{
7279
			$sql.= ", e.label";
7280
		}
7281
		$sql.= " FROM ".MAIN_DB_PREFIX."usergroup as ug ";
7282
		if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
7283
		{
7284
			$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entity as e ON e.rowid=ug.entity";
7285
			if ($force_entity) $sql.= " WHERE ug.entity IN (0,".$force_entity.")";
7286
			else $sql.= " WHERE ug.entity IS NOT NULL";
7287
		}
7288
		else
7289
		{
7290
			$sql.= " WHERE ug.entity IN (0,".$conf->entity.")";
7291
		}
7292
		if (is_array($exclude) && $excludeGroups) $sql.= " AND ug.rowid NOT IN ('".$excludeGroups."')";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $excludeGroups does not seem to be defined for all execution paths leading up to this point.
Loading history...
introduced by
The condition is_array($exclude) is always false.
Loading history...
7293
		if (is_array($include) && $includeGroups) $sql.= " AND ug.rowid IN ('".$includeGroups."')";
0 ignored issues
show
introduced by
The condition is_array($include) is always false.
Loading history...
Comprehensibility Best Practice introduced by
The variable $includeGroups does not seem to be defined for all execution paths leading up to this point.
Loading history...
7294
		$sql.= " ORDER BY ug.nom ASC";
7295
7296
		dol_syslog(get_class($this)."::select_dolgroups", LOG_DEBUG);
7297
		$resql=$this->db->query($sql);
7298
		if ($resql)
7299
		{
7300
			// Enhance with select2
7301
			include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
7302
		   	$out .= ajax_combobox($htmlname);
7303
7304
			$out.= '<select class="flat minwidth200" id="'.$htmlname.'" name="'.$htmlname.($multiple ? '[]' : '').'" '.($multiple ? 'multiple' : '').' '.($disabled?' disabled':'').'>';
7305
7306
			$num = $this->db->num_rows($resql);
7307
			$i = 0;
7308
			if ($num)
7309
			{
7310
				if ($show_empty && !$multiple) $out.= '<option value="-1"'.(in_array(-1, $selected)?' selected':'').'>&nbsp;</option>'."\n";
7311
7312
				while ($i < $num)
7313
				{
7314
					$obj = $this->db->fetch_object($resql);
7315
					$disableline=0;
7316
					if (is_array($enableonly) && count($enableonly) && ! in_array($obj->rowid, $enableonly)) $disableline=1;
7317
7318
					$out.= '<option value="'.$obj->rowid.'"';
7319
					if ($disableline) $out.= ' disabled';
7320
					if ((is_object($selected[0]) && $selected[0]->id == $obj->rowid) || (! is_object($selected[0]) && in_array($obj->rowid, $selected) ))
7321
					{
7322
						$out.= ' selected';
7323
					}
7324
					$out.= '>';
7325
7326
					$out.= $obj->name;
7327
					if (! empty($conf->multicompany->enabled) && empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $conf->entity == 1)
7328
					{
7329
						$out.= " (".$obj->label.")";
7330
					}
7331
7332
					$out.= '</option>';
7333
					$i++;
7334
				}
7335
			}
7336
			else
7337
			{
7338
				if ($show_empty) $out.= '<option value="-1"'.(in_array(-1, $selected)?' selected':'').'></option>'."\n";
7339
				$out.= '<option value="" disabled>'.$langs->trans("NoUserGroupDefined").'</option>';
7340
			}
7341
			$out.= '</select>';
7342
		}
7343
		else
7344
		{
7345
			dol_print_error($this->db);
7346
		}
7347
7348
		return $out;
7349
	}
7350
7351
7352
	/**
7353
	 *	Return HTML to show the search and clear seach button
7354
	 *
7355
	 *  @return	string
7356
	 */
7357
    public function showFilterButtons()
7358
	{
7359
		global $conf, $langs;
7360
7361
		$out='<div class="nowrap">';
7362
		//$out.='<input type="image" class="liste_titre" name="button_search" src="'.img_picto($langs->trans("Search"), 'search.png', '', '', 1).'" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
7363
		//$out.='<input type="image" class="liste_titre" name="button_removefilter" src="'.img_picto($langs->trans("Search"), 'searchclear.png', '', '', 1).'" value="'.dol_escape_htmltag($langs->trans("RemoveFilter")).'" title="'.dol_escape_htmltag($langs->trans("RemoveFilter")).'">';
7364
		$out.='<button type="submit" class="liste_titre button_search" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
7365
		$out.='<button type="submit" class="liste_titre button_removefilter" name="button_removefilter_x" value="x"><span class="fa fa-remove"></span></button>';
7366
		$out.='</div>';
7367
7368
		return $out;
7369
	}
7370
7371
	/**
7372
	 *	Return HTML to show the search and clear seach button
7373
	 *
7374
	 *  @param  string  $cssclass                  CSS class
7375
	 *  @param  int     $calljsfunction            0=default. 1=call function initCheckForSelect() after changing status of checkboxes
7376
	 *  @return	string
7377
	 */
7378
    public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0)
7379
	{
7380
		global $conf, $langs;
7381
7382
		$out='';
7383
		if (! empty($conf->use_javascript_ajax)) $out.='<div class="inline-block checkallactions"><input type="checkbox" id="checkallactions" name="checkallactions" class="checkallactions"></div>';
7384
		$out.='<script>
7385
            $(document).ready(function() {
7386
            	$("#checkallactions").click(function() {
7387
                    if($(this).is(\':checked\')){
7388
                        console.log("We check all");
7389
                		$(".'.$cssclass.'").prop(\'checked\', true).trigger(\'change\');
7390
                    }
7391
                    else
7392
                    {
7393
                        console.log("We uncheck all");
7394
                		$(".'.$cssclass.'").prop(\'checked\', false).trigger(\'change\');
7395
                    }'."\n";
7396
		if ($calljsfunction) $out.='if (typeof initCheckForSelect == \'function\') { initCheckForSelect(0); } else { console.log("No function initCheckForSelect found. Call won\'t be done."); }';
7397
		$out.='         });
7398
7399
        	$(".checkforselect").change(function() {
7400
				$(this).closest("tr").toggleClass("highlight", this.checked);
7401
			});
7402
7403
 	});
7404
    </script>';
7405
7406
		return $out;
7407
	}
7408
7409
	/**
7410
	 *	Return HTML to show the search and clear seach button
7411
	 *
7412
	 *  @param	int  	$addcheckuncheckall        Add the check all/uncheck all checkbox (use javascript) and code to manage this
7413
	 *  @param  string  $cssclass                  CSS class
7414
	 *  @param  int     $calljsfunction            0=default. 1=call function initCheckForSelect() after changing status of checkboxes
7415
	 *  @return	string
7416
	 */
7417
    public function showFilterAndCheckAddButtons($addcheckuncheckall = 0, $cssclass = 'checkforaction', $calljsfunction = 0)
7418
	{
7419
		$out.=$this->showFilterButtons();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $out seems to be never defined.
Loading history...
7420
		if ($addcheckuncheckall)
7421
		{
7422
			$out.=$this->showCheckAddButtons($cssclass, $calljsfunction);
7423
		}
7424
		return $out;
7425
	}
7426
7427
	/**
7428
	 * Return HTML to show the select of expense categories
7429
	 *
7430
	 * @param	string	$selected              preselected category
7431
	 * @param	string	$htmlname              name of HTML select list
7432
	 * @param	integer	$useempty              1=Add empty line
7433
	 * @param	array	$excludeid             id to exclude
7434
	 * @param	string	$target                htmlname of target select to bind event
7435
	 * @param	int		$default_selected      default category to select if fk_c_type_fees change = EX_KME
7436
	 * @param	array	$params                param to give
7437
	 * @return	string
7438
	 */
7439
    public function selectExpenseCategories($selected = '', $htmlname = 'fk_c_exp_tax_cat', $useempty = 0, $excludeid = array(), $target = '', $default_selected = 0, $params = array())
7440
	{
7441
		global $db, $conf, $langs, $user;
7442
7443
		$sql = 'SELECT rowid, label FROM '.MAIN_DB_PREFIX.'c_exp_tax_cat WHERE active = 1';
7444
		$sql.= ' AND entity IN (0,'.getEntity('exp_tax_cat').')';
7445
		if (!empty($excludeid)) $sql.= ' AND rowid NOT IN ('.implode(',', $excludeid).')';
7446
		$sql.= ' ORDER BY label';
7447
7448
		$resql = $db->query($sql);
7449
		if ($resql)
7450
		{
7451
			$out = '<select id="select_'.$htmlname.'" name="'.$htmlname.'" class="'.$htmlname.' flat minwidth75imp">';
7452
			if ($useempty) $out.= '<option value="0">&nbsp;</option>';
7453
7454
			while ($obj = $db->fetch_object($resql))
7455
			{
7456
				$out.= '<option '.($selected == $obj->rowid ? 'selected="selected"' : '').' value="'.$obj->rowid.'">'.$langs->trans($obj->label).'</option>';
7457
			}
7458
			$out.= '</select>';
7459
			if (! empty($htmlname) && $user->admin) $out .= ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
7460
7461
			if (!empty($target))
7462
			{
7463
				$sql = "SELECT c.id FROM ".MAIN_DB_PREFIX."c_type_fees as c WHERE c.code = 'EX_KME' AND c.active = 1";
7464
				$resql = $db->query($sql);
7465
				if ($resql)
7466
				{
7467
					if ($db->num_rows($resql) > 0)
7468
					{
7469
						$obj = $db->fetch_object($resql);
7470
						$out.= '<script>
7471
							$(function() {
7472
								$("select[name='.$target.']").on("change", function() {
7473
									var current_val = $(this).val();
7474
									if (current_val == '.$obj->id.') {';
7475
						if (!empty($default_selected) || !empty($selected)) $out.= '$("select[name='.$htmlname.']").val("'.($default_selected > 0 ? $default_selected : $selected).'");';
7476
7477
						$out.= '
7478
										$("select[name='.$htmlname.']").change();
7479
									}
7480
								});
7481
7482
								$("select[name='.$htmlname.']").change(function() {
7483
7484
									if ($("select[name='.$target.']").val() == '.$obj->id.') {
7485
										// get price of kilometer to fill the unit price
7486
										var data = '.json_encode($params).';
7487
										data.fk_c_exp_tax_cat = $(this).val();
7488
7489
										$.ajax({
7490
											method: "POST",
7491
											dataType: "json",
7492
											data: data,
7493
											url: "'.(DOL_URL_ROOT.'/expensereport/ajax/ajaxik.php').'",
7494
										}).done(function( data, textStatus, jqXHR ) {
7495
											console.log(data);
7496
											if (typeof data.up != "undefined") {
7497
												$("input[name=value_unit]").val(data.up);
7498
												$("select[name='.$htmlname.']").attr("title", data.title);
7499
											} else {
7500
												$("input[name=value_unit]").val("");
7501
												$("select[name='.$htmlname.']").attr("title", "");
7502
											}
7503
										});
7504
									}
7505
								});
7506
							});
7507
						</script>';
7508
					}
7509
				}
7510
			}
7511
		}
7512
		else
7513
		{
7514
			dol_print_error($db);
7515
		}
7516
7517
		return $out;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $out does not seem to be defined for all execution paths leading up to this point.
Loading history...
7518
	}
7519
7520
	/**
7521
	 * Return HTML to show the select ranges of expense range
7522
	 *
7523
	 * @param	string	$selected    preselected category
7524
	 * @param	string	$htmlname    name of HTML select list
7525
	 * @param	integer	$useempty    1=Add empty line
7526
	 * @return	string
7527
	 */
7528
    public function selectExpenseRanges($selected = '', $htmlname = 'fk_range', $useempty = 0)
7529
	{
7530
		global $db,$conf,$langs;
7531
7532
		$sql = 'SELECT rowid, range_ik FROM '.MAIN_DB_PREFIX.'c_exp_tax_range';
7533
		$sql.= ' WHERE entity = '.$conf->entity.' AND active = 1';
7534
7535
		$resql = $db->query($sql);
7536
		if ($resql)
7537
		{
7538
			$out = '<select id="select_'.$htmlname.'" name="'.$htmlname.'" class="'.$htmlname.' flat minwidth75imp">';
7539
			if ($useempty) $out.= '<option value="0"></option>';
7540
7541
			while ($obj = $db->fetch_object($resql))
7542
			{
7543
				$out.= '<option '.($selected == $obj->rowid ? 'selected="selected"' : '').' value="'.$obj->rowid.'">'.price($obj->range_ik, 0, $langs, 1, 0).'</option>';
7544
			}
7545
			$out.= '</select>';
7546
		}
7547
		else
7548
		{
7549
			dol_print_error($db);
7550
		}
7551
7552
		return $out;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $out does not seem to be defined for all execution paths leading up to this point.
Loading history...
7553
	}
7554
7555
	/**
7556
	 * Return HTML to show a select of expense
7557
	 *
7558
	 * @param	string	$selected    preselected category
7559
	 * @param	string	$htmlname    name of HTML select list
7560
	 * @param	integer	$useempty    1=Add empty choice
7561
	 * @param	integer	$allchoice   1=Add all choice
7562
	 * @param	integer	$useid       0=use 'code' as key, 1=use 'id' as key
7563
	 * @return	string
7564
	 */
7565
    public function selectExpense($selected = '', $htmlname = 'fk_c_type_fees', $useempty = 0, $allchoice = 1, $useid = 0)
7566
	{
7567
		global $db,$langs;
7568
7569
		$sql = 'SELECT id, code, label FROM '.MAIN_DB_PREFIX.'c_type_fees';
7570
		$sql.= ' WHERE active = 1';
7571
7572
		$resql = $db->query($sql);
7573
		if ($resql)
7574
		{
7575
			$out = '<select id="select_'.$htmlname.'" name="'.$htmlname.'" class="'.$htmlname.' flat minwidth75imp">';
7576
			if ($useempty) $out.= '<option value="0"></option>';
7577
			if ($allchoice) $out.= '<option value="-1">'.$langs->trans('AllExpenseReport').'</option>';
7578
7579
			$field = 'code';
7580
			if ($useid) $field = 'id';
7581
7582
			while ($obj = $db->fetch_object($resql))
7583
			{
7584
				$key = $langs->trans($obj->code);
7585
				$out.= '<option '.($selected == $obj->{$field} ? 'selected="selected"' : '').' value="'.$obj->{$field}.'">'.($key != $obj->code ? $key : $obj->label).'</option>';
7586
			}
7587
			$out.= '</select>';
7588
		}
7589
		else
7590
		{
7591
			dol_print_error($db);
7592
		}
7593
7594
        return $out;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $out does not seem to be defined for all execution paths leading up to this point.
Loading history...
7595
    }
7596
}
7597