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

Form::select_produits()   F

Complexity

Conditions 19
Paths 3076

Size

Total Lines 127
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 43
c 0
b 0
f 0
nc 3076
nop 17
dl 0
loc 127
rs 0.3499

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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