dolibarr  7.0.0-beta
html.form.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
5  * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
6  * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
7  * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@capnetworks.com>
8  * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
9  * Copyright (C) 2006 Marc Barilley/Ocebo <marc@ocebo.com>
10  * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerker@telenet.be>
11  * Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
12  * Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es>
13  * Copyright (C) 2010-2014 Philippe Grand <philippe.grand@atoo-net.com>
14  * Copyright (C) 2011 Herve Prot <herve.prot@symeos.com>
15  * Copyright (C) 2012-2016 Marcos García <marcosgdf@gmail.com>
16  * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
17  * Copyright (C) 2012-2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
18  * Copyright (C) 2014 Alexandre Spangaro <aspangaro.dolibarr@gmail.com>
19  *
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation; either version 3 of the License, or
23  * (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program. If not, see <http://www.gnu.org/licenses/>.
32  */
33 
47 class Form
48 {
49  var $db;
50  var $error;
51  var $num;
52 
53  // Cache arrays
54  var $cache_types_paiements=array();
55  var $cache_conditions_paiements=array();
56  var $cache_availability=array();
57  var $cache_demand_reason=array();
58  var $cache_types_fees=array();
59  var $cache_vatrates=array();
60 
61 
67  public function __construct($db)
68  {
69  $this->db = $db;
70  }
71 
86  function editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata='string', $moreparam='', $fieldrequired=0, $notabletag=0)
87  {
88  global $conf,$langs;
89 
90  $ret='';
91 
92  // TODO change for compatibility
93  if (! empty($conf->global->MAIN_USE_JQUERY_JEDITABLE) && ! preg_match('/^select;/',$typeofdata))
94  {
95  if (! empty($perm))
96  {
97  $tmp=explode(':',$typeofdata);
98  $ret.= '<div class="editkey_'.$tmp[0].(! empty($tmp[1]) ? ' '.$tmp[1] : '').'" id="'.$htmlname.'">';
99  if ($fieldrequired) $ret.='<span class="fieldrequired">';
100  $ret.= $langs->trans($text);
101  if ($fieldrequired) $ret.='</span>';
102  $ret.= '</div>'."\n";
103  }
104  else
105  {
106  if ($fieldrequired) $ret.='<span class="fieldrequired">';
107  $ret.= $langs->trans($text);
108  if ($fieldrequired) $ret.='</span>';
109  }
110  }
111  else
112  {
113  if (empty($notabletag) && GETPOST('action','aZ09') != 'edit'.$htmlname && $perm) $ret.='<table class="nobordernopadding" width="100%"><tr><td class="nowrap">';
114  if ($fieldrequired) $ret.='<span class="fieldrequired">';
115  $ret.=$langs->trans($text);
116  if ($fieldrequired) $ret.='</span>';
117  if (! empty($notabletag)) $ret.=' ';
118  if (empty($notabletag) && GETPOST('action','aZ09') != 'edit'.$htmlname && $perm) $ret.='</td>';
119  if (empty($notabletag) && GETPOST('action','aZ09') != 'edit'.$htmlname && $perm) $ret.='<td align="right">';
120  if ($htmlname && GETPOST('action','aZ09') != 'edit'.$htmlname && $perm) $ret.='<a href="'.$_SERVER["PHP_SELF"].'?action=edit'.$htmlname.'&amp;id='.$object->id.$moreparam.'">'.img_edit($langs->trans('Edit'), ($notabletag ? 0 : 1)).'</a>';
121  if (! empty($notabletag) && $notabletag == 1) $ret.=' : ';
122  if (! empty($notabletag) && $notabletag == 3) $ret.=' ';
123  if (empty($notabletag) && GETPOST('action','aZ09') != 'edit'.$htmlname && $perm) $ret.='</td>';
124  if (empty($notabletag) && GETPOST('action','aZ09') != 'edit'.$htmlname && $perm) $ret.='</tr></table>';
125  }
126 
127  return $ret;
128  }
129 
147  function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata='string', $editvalue='', $extObject=null, $custommsg=null, $moreparam='', $notabletag=0, $formatfunc='')
148  {
149  global $conf,$langs,$db;
150 
151  $ret='';
152 
153  // Check parameters
154  if (empty($typeofdata)) return 'ErrorBadParameter';
155 
156  // When option to edit inline is activated
157  if (! empty($conf->global->MAIN_USE_JQUERY_JEDITABLE) && ! preg_match('/^select;|datehourpicker/',$typeofdata)) // TODO add jquery timepicker
158  {
159  $ret.=$this->editInPlace($object, $value, $htmlname, $perm, $typeofdata, $editvalue, $extObject, $custommsg);
160  }
161  else
162  {
163  if (GETPOST('action','aZ09') == 'edit'.$htmlname)
164  {
165  $ret.="\n";
166  $ret.='<form method="post" action="'.$_SERVER["PHP_SELF"].($moreparam?'?'.$moreparam:'').'">';
167  $ret.='<input type="hidden" name="action" value="set'.$htmlname.'">';
168  $ret.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
169  $ret.='<input type="hidden" name="id" value="'.$object->id.'">';
170  if (empty($notabletag)) $ret.='<table class="nobordernopadding" cellpadding="0" cellspacing="0">';
171  if (empty($notabletag)) $ret.='<tr><td>';
172  if (preg_match('/^(string|email)/',$typeofdata))
173  {
174  $tmp=explode(':',$typeofdata);
175  $ret.='<input type="text" id="'.$htmlname.'" name="'.$htmlname.'" value="'.($editvalue?$editvalue:$value).'"'.($tmp[1]?' size="'.$tmp[1].'"':'').'>';
176  }
177  else if (preg_match('/^(numeric|amount)/',$typeofdata))
178  {
179  $tmp=explode(':',$typeofdata);
180  $valuetoshow=price2num($editvalue?$editvalue:$value);
181  $ret.='<input type="text" id="'.$htmlname.'" name="'.$htmlname.'" value="'.($valuetoshow!=''?price($valuetoshow):'').'"'.($tmp[1]?' size="'.$tmp[1].'"':'').'>';
182  }
183  else if (preg_match('/^text/',$typeofdata) || preg_match('/^note/',$typeofdata))
184  {
185  $tmp=explode(':',$typeofdata);
186  $cols=$tmp[2];
187  $morealt='';
188  if (preg_match('/%/',$cols))
189  {
190  $morealt=' style="width: '.$cols.'"';
191  $cols='';
192  }
193  $ret.='<textarea id="'.$htmlname.'" name="'.$htmlname.'" wrap="soft" rows="'.($tmp[1]?$tmp[1]:'20').'"'.($cols?' cols="'.$cols.'"':'class="quatrevingtpercent"').$morealt.'">'.($editvalue?$editvalue:$value).'</textarea>';
194  }
195  else if ($typeofdata == 'day' || $typeofdata == 'datepicker')
196  {
197  $ret.=$this->select_date($value,$htmlname,0,0,1,'form'.$htmlname,1,0,1);
198  }
199  else if ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker')
200  {
201  $ret.=$this->select_date($value,$htmlname,1,1,1,'form'.$htmlname,1,0,1);
202  }
203  else if (preg_match('/^select;/',$typeofdata))
204  {
205  $arraydata=explode(',',preg_replace('/^select;/','',$typeofdata));
206  foreach($arraydata as $val)
207  {
208  $tmp=explode(':',$val);
209  $arraylist[$tmp[0]]=$tmp[1];
210  }
211  $ret.=$this->selectarray($htmlname,$arraylist,$value);
212  }
213  else if (preg_match('/^ckeditor/',$typeofdata))
214  {
215  $tmp=explode(':',$typeofdata); // Example: ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols
216  require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
217  $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), true, true, ($tmp[6]?$tmp[6]:'20'), ($tmp[7]?$tmp[7]:'100'));
218  $ret.=$doleditor->Create(1);
219  }
220  if (empty($notabletag)) $ret.='</td>';
221 
222  if (empty($notabletag)) $ret.='<td align="left">';
223  //else $ret.='<div class="clearboth"></div>';
224  $ret.='<input type="submit" class="button'.(empty($notabletag)?'':' ').'" name="modify" value="'.$langs->trans("Modify").'">';
225  if (preg_match('/ckeditor|textarea/',$typeofdata) && empty($notabletag)) $ret.='<br>'."\n";
226  $ret.='<input type="submit" class="button'.(empty($notabletag)?'':' ').'" name="cancel" value="'.$langs->trans("Cancel").'">';
227  if (empty($notabletag)) $ret.='</td>';
228 
229  if (empty($notabletag)) $ret.='</tr></table>'."\n";
230  $ret.='</form>'."\n";
231  }
232  else
233  {
234  if (preg_match('/^(email)/',$typeofdata)) $ret.=dol_print_email($value,0,0,0,0,1);
235  elseif (preg_match('/^(amount|numeric)/',$typeofdata)) $ret.=($value != '' ? price($value,'',$langs,0,-1,-1,$conf->currency) : '');
236  elseif (preg_match('/^text/',$typeofdata) || preg_match('/^note/',$typeofdata)) $ret.=dol_htmlentitiesbr($value);
237  elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') $ret.=dol_print_date($value,'day');
238  elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') $ret.=dol_print_date($value,'dayhour');
239  else if (preg_match('/^select;/',$typeofdata))
240  {
241  $arraydata=explode(',',preg_replace('/^select;/','',$typeofdata));
242  foreach($arraydata as $val)
243  {
244  $tmp=explode(':',$val);
245  $arraylist[$tmp[0]]=$tmp[1];
246  }
247  $ret.=$arraylist[$value];
248  }
249  else if (preg_match('/^ckeditor/',$typeofdata))
250  {
251  $tmpcontent=dol_htmlentitiesbr($value);
252  if (! empty($conf->global->MAIN_DISABLE_NOTES_TAB))
253  {
254  $firstline=preg_replace('/<br>.*/','',$tmpcontent);
255  $firstline=preg_replace('/[\n\r].*/','',$firstline);
256  $tmpcontent=$firstline.((strlen($firstline) != strlen($tmpcontent))?'...':'');
257  }
258  $ret.=$tmpcontent;
259  }
260  else $ret.=$value;
261 
262  if ($formatfunc && method_exists($object, $formatfunc))
263  {
264  $ret=$object->$formatfunc($ret);
265  }
266  }
267  }
268  return $ret;
269  }
270 
284  private function editInPlace($object, $value, $htmlname, $condition, $inputType='textarea', $editvalue=null, $extObject=null, $custommsg=null)
285  {
286  global $conf;
287 
288  $out='';
289 
290  // Check parameters
291  if ($inputType == 'textarea') $value = dol_nl2br($value);
292  else if (preg_match('/^numeric/',$inputType)) $value = price($value);
293  else if ($inputType == 'day' || $inputType == 'datepicker') $value = dol_print_date($value, 'day');
294 
295  if ($condition)
296  {
297  $element = false;
298  $table_element = false;
299  $fk_element = false;
300  $loadmethod = false;
301  $savemethod = false;
302  $ext_element = false;
303  $button_only = false;
304  $inputOption = '';
305 
306  if (is_object($object))
307  {
308  $element = $object->element;
309  $table_element = $object->table_element;
310  $fk_element = $object->id;
311  }
312 
313  if (is_object($extObject))
314  {
315  $ext_element = $extObject->element;
316  }
317 
318  if (preg_match('/^(string|email|numeric)/',$inputType))
319  {
320  $tmp=explode(':',$inputType);
321  $inputType=$tmp[0];
322  if (! empty($tmp[1])) $inputOption=$tmp[1];
323  if (! empty($tmp[2])) $savemethod=$tmp[2];
324  $out.= '<input id="width_'.$htmlname.'" value="'.$inputOption.'" type="hidden"/>'."\n";
325  }
326  else if ((preg_match('/^day$/',$inputType)) || (preg_match('/^datepicker/',$inputType)) || (preg_match('/^datehourpicker/',$inputType)))
327  {
328  $tmp=explode(':',$inputType);
329  $inputType=$tmp[0];
330  if (! empty($tmp[1])) $inputOption=$tmp[1];
331  if (! empty($tmp[2])) $savemethod=$tmp[2];
332 
333  $out.= '<input id="timestamp" type="hidden"/>'."\n"; // Use for timestamp format
334  }
335  else if (preg_match('/^(select|autocomplete)/',$inputType))
336  {
337  $tmp=explode(':',$inputType);
338  $inputType=$tmp[0]; $loadmethod=$tmp[1];
339  if (! empty($tmp[2])) $savemethod=$tmp[2];
340  if (! empty($tmp[3])) $button_only=true;
341  }
342  else if (preg_match('/^textarea/',$inputType))
343  {
344  $tmp=explode(':',$inputType);
345  $inputType=$tmp[0];
346  $rows=(empty($tmp[1])?'8':$tmp[1]);
347  $cols=(empty($tmp[2])?'80':$tmp[2]);
348  }
349  else if (preg_match('/^ckeditor/',$inputType))
350  {
351  $tmp=explode(':',$inputType);
352  $inputType=$tmp[0]; $toolbar=$tmp[1];
353  if (! empty($tmp[2])) $width=$tmp[2];
354  if (! empty($tmp[3])) $heigth=$tmp[3];
355  if (! empty($tmp[4])) $savemethod=$tmp[4];
356 
357  if (! empty($conf->fckeditor->enabled))
358  {
359  $out.= '<input id="ckeditor_toolbar" value="'.$toolbar.'" type="hidden"/>'."\n";
360  }
361  else
362  {
363  $inputType = 'textarea';
364  }
365  }
366 
367  $out.= '<input id="element_'.$htmlname.'" value="'.$element.'" type="hidden"/>'."\n";
368  $out.= '<input id="table_element_'.$htmlname.'" value="'.$table_element.'" type="hidden"/>'."\n";
369  $out.= '<input id="fk_element_'.$htmlname.'" value="'.$fk_element.'" type="hidden"/>'."\n";
370  $out.= '<input id="loadmethod_'.$htmlname.'" value="'.$loadmethod.'" type="hidden"/>'."\n";
371  if (! empty($savemethod)) $out.= '<input id="savemethod_'.$htmlname.'" value="'.$savemethod.'" type="hidden"/>'."\n";
372  if (! empty($ext_element)) $out.= '<input id="ext_element_'.$htmlname.'" value="'.$ext_element.'" type="hidden"/>'."\n";
373  if (! empty($custommsg))
374  {
375  if (is_array($custommsg))
376  {
377  if (!empty($custommsg['success']))
378  $out.= '<input id="successmsg_'.$htmlname.'" value="'.$custommsg['success'].'" type="hidden"/>'."\n";
379  if (!empty($custommsg['error']))
380  $out.= '<input id="errormsg_'.$htmlname.'" value="'.$custommsg['error'].'" type="hidden"/>'."\n";
381  }
382  else
383  $out.= '<input id="successmsg_'.$htmlname.'" value="'.$custommsg.'" type="hidden"/>'."\n";
384  }
385  if ($inputType == 'textarea') {
386  $out.= '<input id="textarea_'.$htmlname.'_rows" value="'.$rows.'" type="hidden"/>'."\n";
387  $out.= '<input id="textarea_'.$htmlname.'_cols" value="'.$cols.'" type="hidden"/>'."\n";
388  }
389  $out.= '<span id="viewval_'.$htmlname.'" class="viewval_'.$inputType.($button_only ? ' inactive' : ' active').'">'.$value.'</span>'."\n";
390  $out.= '<span id="editval_'.$htmlname.'" class="editval_'.$inputType.($button_only ? ' inactive' : ' active').' hideobject">'.(! empty($editvalue) ? $editvalue : $value).'</span>'."\n";
391  }
392  else
393  {
394  $out = $value;
395  }
396 
397  return $out;
398  }
399 
419  function textwithtooltip($text, $htmltext, $tooltipon = 1, $direction = 0, $img = '', $extracss = '', $notabs = 2, $incbefore = '', $noencodehtmltext = 0, $tooltiptrigger='', $forcenowrap=0)
420  {
421  global $conf;
422 
423  if ($incbefore) $text = $incbefore.$text;
424  if (! $htmltext) return $text;
425 
426  $tag='td';
427  if ($notabs == 2) $tag='div';
428  if ($notabs == 3) $tag='span';
429  // Sanitize tooltip
430  $htmltext=str_replace("\\","\\\\",$htmltext);
431  $htmltext=str_replace("\r","",$htmltext);
432  $htmltext=str_replace("\n","",$htmltext);
433 
434  $extrastyle='';
435  if ($direction < 0) { $extracss=($extracss?$extracss.' ':'').'inline-block'; $extrastyle='padding: 0px; padding-left: 3px !important;'; }
436  if ($direction > 0) { $extracss=($extracss?$extracss.' ':'').'inline-block'; $extrastyle='padding: 0px; padding-right: 3px !important;'; }
437 
438  $classfortooltip='classfortooltip';
439 
440  $s='';$textfordialog='';
441 
442  if ($tooltiptrigger == '')
443  {
444  $htmltext=str_replace('"',"&quot;",$htmltext);
445  }
446  else
447  {
448  $classfortooltip='classfortooltiponclick';
449  $textfordialog.='<div style="display: none;" id="idfortooltiponclick_'.$tooltiptrigger.'" class="classfortooltiponclicktext">'.$htmltext.'</div>';
450  }
451  if ($tooltipon == 2 || $tooltipon == 3)
452  {
453  $paramfortooltipimg=' class="'.$classfortooltip.' inline-block'.($extracss?' '.$extracss:'').'" style="padding: 0px;'.($extrastyle?' '.$extrastyle:'').'"';
454  if ($tooltiptrigger == '') $paramfortooltipimg.=' title="'.($noencodehtmltext?$htmltext:dol_escape_htmltag($htmltext,1)).'"'; // Attribut to put on img tag to store tooltip
455  else $paramfortooltipimg.=' dolid="'.$tooltiptrigger.'"';
456  }
457  else $paramfortooltipimg =($extracss?' class="'.$extracss.'"':'').($extrastyle?' style="'.$extrastyle.'"':''); // Attribut to put on td text tag
458  if ($tooltipon == 1 || $tooltipon == 3)
459  {
460  $paramfortooltiptd=' class="'.($tooltipon == 3 ? 'cursorpointer ' : '').$classfortooltip.' inline-block'.($extracss?' '.$extracss:'').'" style="padding: 0px;'.($extrastyle?' '.$extrastyle:'').'" ';
461  if ($tooltiptrigger == '') $paramfortooltiptd.=' title="'.($noencodehtmltext?$htmltext:dol_escape_htmltag($htmltext,1)).'"'; // Attribut to put on td tag to store tooltip
462  else $paramfortooltiptd.=' dolid="'.$tooltiptrigger.'"';
463  }
464  else $paramfortooltiptd =($extracss?' class="'.$extracss.'"':'').($extrastyle?' style="'.$extrastyle.'"':''); // Attribut to put on td text tag
465  if (empty($notabs)) $s.='<table class="nobordernopadding" summary=""><tr style="height: auto;">';
466  elseif ($notabs == 2) $s.='<div class="inline-block'.($forcenowrap?' nowrap':'').'">';
467  // Define value if value is before
468  if ($direction < 0) {
469  $s.='<'.$tag.$paramfortooltipimg;
470  if ($tag == 'td') {
471  $s .= ' valign="top" width="14"';
472  }
473  $s.= '>'.$textfordialog.$img.'</'.$tag.'>';
474  }
475  // Use another method to help avoid having a space in value in order to use this value with jquery
476  // Define label
477  if ((string) $text != '') $s.='<'.$tag.$paramfortooltiptd.'>'.$text.'</'.$tag.'>';
478  // Define value if value is after
479  if ($direction > 0) {
480  $s.='<'.$tag.$paramfortooltipimg;
481  if ($tag == 'td') $s .= ' valign="middle" width="14"';
482  $s.= '>'.$textfordialog.$img.'</'.$tag.'>';
483  }
484  if (empty($notabs)) $s.='</tr></table>';
485  elseif ($notabs == 2) $s.='</div>';
486 
487  return $s;
488  }
489 
504  function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 2, $tooltiptrigger='', $forcenowrap=0)
505  {
506  global $conf, $langs;
507 
508  $alt = '';
509  if ($tooltiptrigger) $alt=$langs->transnoentitiesnoconv("ClickToShowHelp");
510 
511  //For backwards compatibility
512  if ($type == '0') $type = 'info';
513  elseif ($type == '1') $type = 'help';
514 
515  // If info or help with no javascript, show only text
516  if (empty($conf->use_javascript_ajax))
517  {
518  if ($type == 'info' || $type == 'help') return $text;
519  else
520  {
521  $alt = $htmltext;
522  $htmltext = '';
523  }
524  }
525 
526  // If info or help with smartphone, show only text (tooltip hover can't works)
527  if (! empty($conf->dol_no_mouse_hover) && empty($tooltiptrigger))
528  {
529  if ($type == 'info' || $type == 'help') return $text;
530  }
531  // If info or help with smartphone, show only text (tooltip on lick does not works with dialog on smaprtphone)
532  if (! empty($conf->dol_no_mouse_hover) && ! empty($tooltiptrigger))
533  {
534  if ($type == 'info' || $type == 'help') return $text;
535  }
536 
537  if ($type == 'info') $img = img_help(0, $alt);
538  elseif ($type == 'help') $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt);
539  elseif ($type == 'superadmin') $img = img_picto($alt, 'redstar');
540  elseif ($type == 'admin') $img = img_picto($alt, 'star');
541  elseif ($type == 'warning') $img = img_warning($alt);
542  else $img = img_picto($alt, $type);
543 
544  return $this->textwithtooltip($text, $htmltext, (($tooltiptrigger && ! $img)?3:2), $direction, $img, $extracss, $notabs, '', $noencodehtmltext, $tooltiptrigger, $forcenowrap);
545  }
546 
555  function selectMassAction($selected, $arrayofaction, $alwaysvisible=0)
556  {
557  global $conf,$langs,$hookmanager;
558 
559  if (count($arrayofaction) == 0) return;
560 
561  $disabled=0;
562  $ret='<div class="centpercent center">';
563  $ret.='<select class="flat'.(empty($conf->use_javascript_ajax)?'':' hideobject').' massaction massactionselect" name="massaction"'.($disabled?' disabled="disabled"':'').'>';
564 
565  // 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.
566  $parameters=array();
567  $reshook=$hookmanager->executeHooks('addMoreMassActions',$parameters); // Note that $action and $object may have been modified by hook
568  if (empty($reshook))
569  {
570  $ret.='<option value="0"'.($disabled?' disabled="disabled"':'').'>-- '.$langs->trans("SelectAction").' --</option>';
571  foreach($arrayofaction as $code => $label)
572  {
573  $ret.='<option value="'.$code.'"'.($disabled?' disabled="disabled"':'').'>'.$label.'</option>';
574  }
575  }
576  $ret.=$hookmanager->resPrint;
577 
578  $ret.='</select>';
579  // 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
580  $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.
581  $ret.='<input type="submit" disabled name="confirmmassaction" class="button'.(empty($conf->use_javascript_ajax)?'':' hideobject').' massaction massactionconfirmed" value="'.dol_escape_htmltag($langs->trans("Confirm")).'">';
582  $ret.='</div>';
583 
584  if (! empty($conf->use_javascript_ajax))
585  {
586  $ret.='<!-- JS CODE TO ENABLE mass action select -->
587  <script type="text/javascript">
588  function initCheckForSelect(mode) /* mode is 0 during init of page or click all, 1 when we click on 1 checkbox */
589  {
590  atleastoneselected=0;
591  jQuery(".checkforselect").each(function( index ) {
592  /* console.log( index + ": " + $( this ).text() ); */
593  if ($(this).is(\':checked\')) atleastoneselected++;
594  });
595  console.log("initCheckForSelect mode="+mode+" atleastoneselected="+atleastoneselected);
596  if (atleastoneselected || '.$alwaysvisible.')
597  {
598  jQuery(".massaction").show();
599  '.($selected ? 'if (atleastoneselected) { jQuery(".massactionselect").val("'.$selected.'"); jQuery(".massactionconfirmed").prop(\'disabled\', false); }' : '').'
600  '.($selected ? 'if (! atleastoneselected) { jQuery(".massactionselect").val("0"); jQuery(".massactionconfirmed").prop(\'disabled\', true); } ' : '').'
601  }
602  else
603  {
604  jQuery(".massaction").hide();
605  }
606  }
607 
608  jQuery(document).ready(function () {
609  initCheckForSelect(0);
610  jQuery(".checkforselect").click(function() {
611  initCheckForSelect(1);
612  });
613  jQuery(".massactionselect").change(function() {
614  var massaction = $( this ).val();
615  var urlform = $( this ).closest("form").attr("action").replace("#show_files","");
616  if (massaction == "builddoc")
617  {
618  urlform = urlform + "#show_files";
619  }
620  $( this ).closest("form").attr("action", urlform);
621  console.log("we select a mass action "+massaction+" - "+urlform);
622  /* Warning: if you set submit button to disabled, post using Enter will no more work if there is no other button */
623  if ($(this).val() != \'0\')
624  {
625  jQuery(".massactionconfirmed").prop(\'disabled\', false);
626  }
627  else
628  {
629  jQuery(".massactionconfirmed").prop(\'disabled\', true);
630  }
631  });
632  });
633  </script>
634  ';
635  }
636 
637  return $ret;
638  }
639 
651  function select_country($selected='',$htmlname='country_id',$htmloption='',$maxlength=0,$morecss='minwidth300',$usecodeaskey='')
652  {
653  global $conf,$langs;
654 
655  $langs->load("dict");
656 
657  $out='';
658  $countryArray=array();
659  $favorite=array();
660  $label=array();
661  $atleastonefavorite=0;
662 
663  $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite";
664  $sql.= " FROM ".MAIN_DB_PREFIX."c_country";
665  $sql.= " WHERE active > 0";
666  //$sql.= " ORDER BY code ASC";
667 
668  dol_syslog(get_class($this)."::select_country", LOG_DEBUG);
669  $resql=$this->db->query($sql);
670  if ($resql)
671  {
672  $out.= '<select id="select'.$htmlname.'" class="flat maxwidth200onsmartphone selectcountry'.($morecss?' '.$morecss:'').'" name="'.$htmlname.'" '.$htmloption.'>';
673  $num = $this->db->num_rows($resql);
674  $i = 0;
675  if ($num)
676  {
677  $foundselected=false;
678 
679  while ($i < $num)
680  {
681  $obj = $this->db->fetch_object($resql);
682  $countryArray[$i]['rowid'] = $obj->rowid;
683  $countryArray[$i]['code_iso'] = $obj->code_iso;
684  $countryArray[$i]['code_iso3'] = $obj->code_iso3;
685  $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:''));
686  $countryArray[$i]['favorite'] = $obj->favorite;
687  $favorite[$i] = $obj->favorite;
688  $label[$i] = dol_string_unaccent($countryArray[$i]['label']);
689  $i++;
690  }
691 
692  array_multisort($favorite, SORT_DESC, $label, SORT_ASC, $countryArray);
693 
694  foreach ($countryArray as $row)
695  {
696  if ($row['favorite'] && $row['code_iso']) $atleastonefavorite++;
697  if (empty($row['favorite']) && $atleastonefavorite)
698  {
699  $atleastonefavorite=0;
700  $out.= '<option a value="" disabled class="selectoptiondisabledwhite">----------------------</option>';
701  }
702  if ($selected && $selected != '-1' && ($selected == $row['rowid'] || $selected == $row['code_iso'] || $selected == $row['code_iso3'] || $selected == $row['label']) )
703  {
704  $foundselected=true;
705  $out.= '<option b value="'.($usecodeaskey?($usecodeaskey=='code2'?$row['code_iso']:$row['code_iso3']):$row['rowid']).'" selected>';
706  }
707  else
708  {
709  $out.= '<option c value="'.($usecodeaskey?($usecodeaskey=='code2'?$row['code_iso']:$row['code_iso3']):$row['rowid']).'">';
710  }
711  if ($row['label']) $out.= dol_trunc($row['label'],$maxlength,'middle');
712  else $out.= '&nbsp;';
713  if ($row['code_iso']) $out.= ' ('.$row['code_iso'] . ')';
714  $out.= '</option>';
715  }
716  }
717  $out.= '</select>';
718  }
719  else
720  {
721  dol_print_error($this->db);
722  }
723 
724  // Make select dynamic
725  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
726  $out .= ajax_combobox('select'.$htmlname);
727 
728  return $out;
729  }
730 
743  function select_incoterms($selected='', $location_incoterms='', $page='', $htmlname='incoterm_id', $htmloption='', $forcecombo=1, $events=array())
744  {
745  global $conf,$langs;
746 
747  $langs->load("dict");
748 
749  $out='';
750  $incotermArray=array();
751 
752  $sql = "SELECT rowid, code";
753  $sql.= " FROM ".MAIN_DB_PREFIX."c_incoterms";
754  $sql.= " WHERE active > 0";
755  $sql.= " ORDER BY code ASC";
756 
757  dol_syslog(get_class($this)."::select_incoterm", LOG_DEBUG);
758  $resql=$this->db->query($sql);
759  if ($resql)
760  {
761  if ($conf->use_javascript_ajax && ! $forcecombo)
762  {
763  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
764  $out .= ajax_combobox($htmlname, $events);
765  }
766 
767  if (!empty($page))
768  {
769  $out .= '<form method="post" action="'.$page.'">';
770  $out .= '<input type="hidden" name="action" value="set_incoterms">';
771  $out .= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
772  }
773 
774  $out.= '<select id="'.$htmlname.'" class="flat selectincoterm minwidth100imp noenlargeonsmartphone" name="'.$htmlname.'" '.$htmloption.'>';
775  $out.= '<option value="0">&nbsp;</option>';
776  $num = $this->db->num_rows($resql);
777  $i = 0;
778  if ($num)
779  {
780  $foundselected=false;
781 
782  while ($i < $num)
783  {
784  $obj = $this->db->fetch_object($resql);
785  $incotermArray[$i]['rowid'] = $obj->rowid;
786  $incotermArray[$i]['code'] = $obj->code;
787  $i++;
788  }
789 
790  foreach ($incotermArray as $row)
791  {
792  if ($selected && ($selected == $row['rowid'] || $selected == $row['code']))
793  {
794  $out.= '<option value="'.$row['rowid'].'" selected>';
795  }
796  else
797  {
798  $out.= '<option value="'.$row['rowid'].'">';
799  }
800 
801  if ($row['code']) $out.= $row['code'];
802 
803  $out.= '</option>';
804  }
805  }
806  $out.= '</select>';
807 
808  $out .= '<input id="location_incoterms" class="maxwidth100onsmartphone" name="location_incoterms" value="'.$location_incoterms.'">';
809 
810  if (!empty($page))
811  {
812  $out .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'"></form>';
813  }
814  }
815  else
816  {
817  dol_print_error($this->db);
818  }
819 
820  return $out;
821  }
822 
834  function select_type_of_lines($selected='',$htmlname='type',$showempty=0,$hidetext=0,$forceall=0)
835  {
836  global $db,$langs,$user,$conf;
837 
838  // If product & services are enabled or both disabled.
839  if ($forceall > 0 || (empty($forceall) && ! empty($conf->product->enabled) && ! empty($conf->service->enabled))
840  || (empty($forceall) && empty($conf->product->enabled) && empty($conf->service->enabled)) )
841  {
842  if (empty($hidetext)) print $langs->trans("Type").': ';
843  print '<select class="flat" id="select_'.$htmlname.'" name="'.$htmlname.'">';
844  if ($showempty)
845  {
846  print '<option value="-1"';
847  if ($selected == -1) print ' selected';
848  print '>&nbsp;</option>';
849  }
850 
851  print '<option value="0"';
852  if (0 == $selected) print ' selected';
853  print '>'.$langs->trans("Product");
854 
855  print '<option value="1"';
856  if (1 == $selected) print ' selected';
857  print '>'.$langs->trans("Service");
858 
859  print '</select>';
860  //if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
861  }
862  if (empty($forceall) && empty($conf->product->enabled) && ! empty($conf->service->enabled))
863  {
864  print $langs->trans("Service");
865  print '<input type="hidden" name="'.$htmlname.'" value="1">';
866  }
867  if (empty($forceall) && ! empty($conf->product->enabled) && empty($conf->service->enabled))
868  {
869  print $langs->trans("Product");
870  print '<input type="hidden" name="'.$htmlname.'" value="0">';
871  }
872  if ($forceall < 0) // This should happened only for contracts when both predefined product and service are disabled.
873  {
874  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
875  }
876  }
877 
884  {
885  global $langs;
886 
887  $num = count($this->cache_types_fees);
888  if ($num > 0) return 0; // Cache already loaded
889 
890  dol_syslog(__METHOD__, LOG_DEBUG);
891 
892  $langs->load("trips");
893 
894  $sql = "SELECT c.code, c.label";
895  $sql.= " FROM ".MAIN_DB_PREFIX."c_type_fees as c";
896  $sql.= " WHERE active > 0";
897 
898  $resql=$this->db->query($sql);
899  if ($resql)
900  {
901  $num = $this->db->num_rows($resql);
902  $i = 0;
903 
904  while ($i < $num)
905  {
906  $obj = $this->db->fetch_object($resql);
907 
908  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
909  $label=($obj->code != $langs->trans($obj->code) ? $langs->trans($obj->code) : $langs->trans($obj->label));
910  $this->cache_types_fees[$obj->code] = $label;
911  $i++;
912  }
913 
914  asort($this->cache_types_fees);
915 
916  return $num;
917  }
918  else
919  {
920  dol_print_error($this->db);
921  return -1;
922  }
923  }
924 
933  function select_type_fees($selected='',$htmlname='type',$showempty=0)
934  {
935  global $user, $langs;
936 
937  dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG);
938 
939  $this->load_cache_types_fees();
940 
941  print '<select class="flat" name="'.$htmlname.'">';
942  if ($showempty)
943  {
944  print '<option value="-1"';
945  if ($selected == -1) print ' selected';
946  print '>&nbsp;</option>';
947  }
948 
949  foreach($this->cache_types_fees as $key => $value)
950  {
951  print '<option value="'.$key.'"';
952  if ($key == $selected) print ' selected';
953  print '>';
954  print $value;
955  print '</option>';
956  }
957 
958  print '</select>';
959  if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
960  }
961 
962 
975  function select_thirdparty($selected='', $htmlname='socid', $filter='', $limit=20, $ajaxoptions=array(), $forcecombo=0)
976  {
977  return $this->select_thirdparty_list($selected,$htmlname,$filter,1,0,$forcecombo,array(),'',0, $limit);
978  }
979 
998  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())
999  {
1000  global $conf,$user,$langs;
1001 
1002  $out='';
1003 
1004  if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT) && ! $forcecombo)
1005  {
1006  // No immediate load of all database
1007  $placeholder='';
1008  if ($selected && empty($selected_input_value))
1009  {
1010  require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1011  $societetmp = new Societe($this->db);
1012  $societetmp->fetch($selected);
1013  $selected_input_value=$societetmp->name;
1014  unset($societetmp);
1015  }
1016  // mode 1
1017  $urloption='htmlname='.$htmlname.'&outjson=1&filter='.$filter.($showtype?'&showtype='.$showtype:'');
1018  $out.= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/societe/ajax/company.php', $urloption, $conf->global->COMPANY_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
1019  $out.='<style type="text/css">.ui-autocomplete { z-index: 250; }</style>';
1020  if (empty($hidelabel)) print $langs->trans("RefOrLabel").' : ';
1021  else if ($hidelabel > 1) {
1022  $placeholder=' placeholder="'.$langs->trans("RefOrLabel").'"';
1023  if ($hidelabel == 2) {
1024  $out.= img_picto($langs->trans("Search"), 'search');
1025  }
1026  }
1027  $out.= '<input type="text" class="'.$morecss.'" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' '.(!empty($conf->global->THIRDPARTY_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />';
1028  if ($hidelabel == 3) {
1029  $out.= img_picto($langs->trans("Search"), 'search');
1030  }
1031  }
1032  else
1033  {
1034  // Immediate load of all database
1035  $out.=$this->select_thirdparty_list($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, '', 0, $limit, $morecss, $moreparam);
1036  }
1037 
1038  return $out;
1039  }
1040 
1059  function select_thirdparty_list($selected='',$htmlname='socid',$filter='',$showempty='', $showtype=0, $forcecombo=0, $events=array(), $filterkey='', $outputmode=0, $limit=0, $morecss='minwidth100', $moreparam='')
1060  {
1061  global $conf,$user,$langs;
1062 
1063  $out='';
1064  $num=0;
1065  $outarray=array();
1066 
1067  // On recherche les societes
1068  $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.client, s.fournisseur, s.code_client, s.code_fournisseur";
1069  $sql.= " FROM ".MAIN_DB_PREFIX ."societe as s";
1070  if (!$user->rights->societe->client->voir && !$user->societe_id) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
1071  $sql.= " WHERE s.entity IN (".getEntity('societe').")";
1072  if (! empty($user->societe_id)) $sql.= " AND s.rowid = ".$user->societe_id;
1073  if ($filter) $sql.= " AND (".$filter.")";
1074  if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
1075  if (! empty($conf->global->COMPANY_HIDE_INACTIVE_IN_COMBOBOX)) $sql.= " AND s.status <> 0";
1076  // Add criteria
1077  if ($filterkey && $filterkey != '')
1078  {
1079  $sql.=" AND (";
1080  $prefix=empty($conf->global->COMPANY_DONOTSEARCH_ANYWHERE)?'%':''; // Can use index if COMPANY_DONOTSEARCH_ANYWHERE is on
1081  // For natural search
1082  $scrit = explode(' ', $filterkey);
1083  $i=0;
1084  if (count($scrit) > 1) $sql.="(";
1085  foreach ($scrit as $crit) {
1086  if ($i > 0) $sql.=" AND ";
1087  $sql.="(s.nom LIKE '".$this->db->escape($prefix.$crit)."%')";
1088  $i++;
1089  }
1090  if (count($scrit) > 1) $sql.=")";
1091  if (! empty($conf->barcode->enabled))
1092  {
1093  $sql .= " OR s.barcode LIKE '".$this->db->escape($filterkey)."%'";
1094  }
1095  $sql.=")";
1096  }
1097  $sql.=$this->db->order("nom","ASC");
1098  $sql.=$this->db->plimit($limit, 0);
1099 
1100  // Build output string
1101  dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
1102  $resql=$this->db->query($sql);
1103  if ($resql)
1104  {
1105  if (! $forcecombo)
1106  {
1107  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1108  $out .= ajax_combobox($htmlname, $events, $conf->global->COMPANY_USE_SEARCH_TO_SELECT);
1109  }
1110 
1111  // Construct $out and $outarray
1112  $out.= '<select id="'.$htmlname.'" class="flat'.($morecss?' '.$morecss:'').'"'.($moreparam?' '.$moreparam:'').' name="'.$htmlname.'">'."\n";
1113 
1114  $textifempty='';
1115  // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
1116  //if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
1117  if (! empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT))
1118  {
1119  if ($showempty && ! is_numeric($showempty)) $textifempty=$langs->trans($showempty);
1120  else $textifempty.=$langs->trans("All");
1121  }
1122  if ($showempty) $out.= '<option value="-1">'.$textifempty.'</option>'."\n";
1123 
1124  $num = $this->db->num_rows($resql);
1125  $i = 0;
1126  if ($num)
1127  {
1128  while ($i < $num)
1129  {
1130  $obj = $this->db->fetch_object($resql);
1131  $label='';
1132  if ($conf->global->SOCIETE_ADD_REF_IN_LIST) {
1133  if (($obj->client) && (!empty($obj->code_client))) {
1134  $label = $obj->code_client. ' - ';
1135  }
1136  if (($obj->fournisseur) && (!empty($obj->code_fournisseur))) {
1137  $label .= $obj->code_fournisseur. ' - ';
1138  }
1139  $label.=' '.$obj->name;
1140  }
1141  else
1142  {
1143  $label=$obj->name;
1144  }
1145 
1146  if(!empty($obj->name_alias)) {
1147  $label.=' ('.$obj->name_alias.')';
1148  }
1149 
1150  if ($showtype)
1151  {
1152  if ($obj->client || $obj->fournisseur) $label.=' (';
1153  if ($obj->client == 1 || $obj->client == 3) $label.=$langs->trans("Customer");
1154  if ($obj->client == 2 || $obj->client == 3) $label.=($obj->client==3?', ':'').$langs->trans("Prospect");
1155  if ($obj->fournisseur) $label.=($obj->client?', ':'').$langs->trans("Supplier");
1156  if ($obj->client || $obj->fournisseur) $label.=')';
1157  }
1158 
1159  if (empty($outputmode))
1160  {
1161  if ($selected > 0 && $selected == $obj->rowid)
1162  {
1163  $out.= '<option value="'.$obj->rowid.'" selected>'.$label.'</option>';
1164  }
1165  else
1166  {
1167  $out.= '<option value="'.$obj->rowid.'">'.$label.'</option>';
1168  }
1169  }
1170  else
1171  {
1172  array_push($outarray, array('key'=>$obj->rowid, 'value'=>$label, 'label'=>$label));
1173  }
1174 
1175  $i++;
1176  if (($i % 10) == 0) $out.="\n";
1177  }
1178  }
1179  $out.= '</select>'."\n";
1180  }
1181  else
1182  {
1183  dol_print_error($this->db);
1184  }
1185 
1186  $this->result=array('nbofthirdparties'=>$num);
1187 
1188  if ($outputmode) return $outarray;
1189  return $out;
1190  }
1191 
1192 
1203  function select_remises($selected, $htmlname, $filter, $socid, $maxvalue=0)
1204  {
1205  global $langs,$conf;
1206 
1207  // On recherche les remises
1208  $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
1209  $sql.= " re.description, re.fk_facture_source";
1210  $sql.= " FROM ".MAIN_DB_PREFIX ."societe_remise_except as re";
1211  $sql.= " WHERE re.fk_soc = ".(int) $socid;
1212  $sql.= " AND re.entity = " . $conf->entity;
1213  if ($filter) $sql.= " AND ".$filter;
1214  $sql.= " ORDER BY re.description ASC";
1215 
1216  dol_syslog(get_class($this)."::select_remises", LOG_DEBUG);
1217  $resql=$this->db->query($sql);
1218  if ($resql)
1219  {
1220  print '<select class="flat maxwidthonsmartphone" name="'.$htmlname.'">';
1221  $num = $this->db->num_rows($resql);
1222 
1223  $qualifiedlines=$num;
1224 
1225  $i = 0;
1226  if ($num)
1227  {
1228  print '<option value="0">&nbsp;</option>';
1229  while ($i < $num)
1230  {
1231  $obj = $this->db->fetch_object($resql);
1232  $desc=dol_trunc($obj->description,40);
1233  if (preg_match('/\(CREDIT_NOTE\)/', $desc)) $desc=preg_replace('/\(CREDIT_NOTE\)/', $langs->trans("CreditNote"), $desc);
1234  if (preg_match('/\(DEPOSIT\)/', $desc)) $desc=preg_replace('/\(DEPOSIT\)/', $langs->trans("Deposit"), $desc);
1235  if (preg_match('/\(EXCESS RECEIVED\)/', $desc)) $desc=preg_replace('/\(EXCESS RECEIVED\)/', $langs->trans("ExcessReceived"), $desc);
1236 
1237  $selectstring='';
1238  if ($selected > 0 && $selected == $obj->rowid) $selectstring=' selected';
1239 
1240  $disabled='';
1241  if ($maxvalue > 0 && $obj->amount_ttc > $maxvalue)
1242  {
1243  $qualifiedlines--;
1244  $disabled=' disabled';
1245  }
1246 
1247  if (!empty($conf->global->MAIN_SHOW_FACNUMBER_IN_DISCOUNT_LIST) && !empty($obj->fk_facture_source))
1248  {
1249  $tmpfac = new Facture($this->db);
1250  if ($tmpfac->fetch($obj->fk_facture_source) > 0) $desc=$desc.' - '.$tmpfac->ref;
1251  }
1252 
1253  print '<option value="'.$obj->rowid.'"'.$selectstring.$disabled.'>'.$desc.' ('.price($obj->amount_ht).' '.$langs->trans("HT").' - '.price($obj->amount_ttc).' '.$langs->trans("TTC").')</option>';
1254  $i++;
1255  }
1256  }
1257  print '</select>';
1258  return $qualifiedlines;
1259  }
1260  else
1261  {
1262  dol_print_error($this->db);
1263  return -1;
1264  }
1265  }
1266 
1287  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='')
1288  {
1289  print $this->selectcontacts($socid,$selected,$htmlname,$showempty,$exclude,$limitto,$showfunction, $moreclass, $options_only, $showsoc, $forcecombo, $events, $moreparam, $htmlid);
1290  return $this->num;
1291  }
1292 
1313  function selectcontacts($socid, $selected='', $htmlname='contactid', $showempty=0, $exclude='', $limitto='', $showfunction=0, $moreclass='', $options_only=false, $showsoc=0, $forcecombo=0, $events=array(), $moreparam='', $htmlid='')
1314  {
1315  global $conf,$langs;
1316 
1317  $langs->load('companies');
1318 
1319  if (empty($htmlid)) $htmlid = $htmlname;
1320  $out='';
1321 
1322  // On recherche les societes
1323  $sql = "SELECT sp.rowid, sp.lastname, sp.statut, sp.firstname, sp.poste";
1324  if ($showsoc > 0) $sql.= " , s.nom as company";
1325  $sql.= " FROM ".MAIN_DB_PREFIX ."socpeople as sp";
1326  if ($showsoc > 0) $sql.= " LEFT OUTER JOIN ".MAIN_DB_PREFIX ."societe as s ON s.rowid=sp.fk_soc";
1327  $sql.= " WHERE sp.entity IN (".getEntity('societe').")";
1328  if ($socid > 0) $sql.= " AND sp.fk_soc=".$socid;
1329  if (! empty($conf->global->CONTACT_HIDE_INACTIVE_IN_COMBOBOX)) $sql.= " AND sp.statut <> 0";
1330  $sql.= " ORDER BY sp.lastname ASC";
1331 
1332  dol_syslog(get_class($this)."::select_contacts", LOG_DEBUG);
1333  $resql=$this->db->query($sql);
1334  if ($resql)
1335  {
1336  $num=$this->db->num_rows($resql);
1337 
1338  if ($conf->use_javascript_ajax && ! $forcecombo && ! $options_only)
1339  {
1340  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1341  $out .= ajax_combobox($htmlid, $events, $conf->global->CONTACT_USE_SEARCH_TO_SELECT);
1342  }
1343 
1344  if ($htmlname != 'none' || $options_only) $out.= '<select class="flat'.($moreclass?' '.$moreclass:'').'" id="'.$htmlid.'" name="'.$htmlname.'" '.(!empty($moreparam) ? $moreparam : '').'>';
1345  if ($showempty == 1) $out.= '<option value="0"'.($selected=='0'?' selected':'').'>&nbsp;</option>';
1346  if ($showempty == 2) $out.= '<option value="0"'.($selected=='0'?' selected':'').'>'.$langs->trans("Internal").'</option>';
1347  $num = $this->db->num_rows($resql);
1348  $i = 0;
1349  if ($num)
1350  {
1351  include_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
1352  $contactstatic=new Contact($this->db);
1353 
1354  if (!is_array($selected)) $selected = array($selected);
1355  while ($i < $num)
1356  {
1357  $obj = $this->db->fetch_object($resql);
1358 
1359  $contactstatic->id=$obj->rowid;
1360  $contactstatic->lastname=$obj->lastname;
1361  $contactstatic->firstname=$obj->firstname;
1362  if ($obj->statut == 1){
1363  if ($htmlname != 'none')
1364  {
1365  $disabled=0;
1366  if (is_array($exclude) && count($exclude) && in_array($obj->rowid,$exclude)) $disabled=1;
1367  if (is_array($limitto) && count($limitto) && ! in_array($obj->rowid,$limitto)) $disabled=1;
1368  if (!empty($selected) && in_array($obj->rowid, $selected))
1369  {
1370  $out.= '<option value="'.$obj->rowid.'"';
1371  if ($disabled) $out.= ' disabled';
1372  $out.= ' selected>';
1373  $out.= $contactstatic->getFullName($langs);
1374  if ($showfunction && $obj->poste) $out.= ' ('.$obj->poste.')';
1375  if (($showsoc > 0) && $obj->company) $out.= ' - ('.$obj->company.')';
1376  $out.= '</option>';
1377  }
1378  else
1379  {
1380  $out.= '<option value="'.$obj->rowid.'"';
1381  if ($disabled) $out.= ' disabled';
1382  $out.= '>';
1383  $out.= $contactstatic->getFullName($langs);
1384  if ($showfunction && $obj->poste) $out.= ' ('.$obj->poste.')';
1385  if (($showsoc > 0) && $obj->company) $out.= ' - ('.$obj->company.')';
1386  $out.= '</option>';
1387  }
1388  }
1389  else
1390  {
1391  if (in_array($obj->rowid, $selected))
1392  {
1393  $out.= $contactstatic->getFullName($langs);
1394  if ($showfunction && $obj->poste) $out.= ' ('.$obj->poste.')';
1395  if (($showsoc > 0) && $obj->company) $out.= ' - ('.$obj->company.')';
1396  }
1397  }
1398  }
1399  $i++;
1400  }
1401  }
1402  else
1403  {
1404  $out.= '<option value="-1"'.($showempty==2?'':' selected').' disabled>'.$langs->trans($socid?"NoContactDefinedForThirdParty":"NoContactDefined").'</option>';
1405  }
1406  if ($htmlname != 'none' || $options_only)
1407  {
1408  $out.= '</select>';
1409  }
1410 
1411  $this->num = $num;
1412  return $out;
1413  }
1414  else
1415  {
1416  dol_print_error($this->db);
1417  return -1;
1418  }
1419  }
1420 
1436  function select_users($selected='',$htmlname='userid',$show_empty=0,$exclude=null,$disabled=0,$include='',$enableonly='',$force_entity=0)
1437  {
1438  print $this->select_dolusers($selected,$htmlname,$show_empty,$exclude,$disabled,$include,$enableonly,$force_entity);
1439  }
1440 
1462  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)
1463  {
1464  global $conf,$user,$langs;
1465 
1466  // If no preselected user defined, we take current user
1467  if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && empty($conf->global->SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE)) $selected=$user->id;
1468 
1469  $excludeUsers=null;
1470  $includeUsers=null;
1471 
1472  // Permettre l'exclusion d'utilisateurs
1473  if (is_array($exclude)) $excludeUsers = implode(",",$exclude);
1474  // Permettre l'inclusion d'utilisateurs
1475  if (is_array($include)) $includeUsers = implode(",",$include);
1476  else if ($include == 'hierarchy')
1477  {
1478  // Build list includeUsers to have only hierarchy
1479  $includeUsers = implode(",",$user->getAllChildIds(0));
1480  }
1481  else if ($include == 'hierarchyme')
1482  {
1483  // Build list includeUsers to have only hierarchy and current user
1484  $includeUsers = implode(",",$user->getAllChildIds(1));
1485  }
1486 
1487  $out='';
1488 
1489  // Forge request to select users
1490  $sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut, u.login, u.admin, u.entity";
1491  if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
1492  {
1493  $sql.= ", e.label";
1494  }
1495  $sql.= " FROM ".MAIN_DB_PREFIX ."user as u";
1496  if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
1497  {
1498  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX ."entity as e ON e.rowid=u.entity";
1499  if ($force_entity) $sql.= " WHERE u.entity IN (0,".$force_entity.")";
1500  else $sql.= " WHERE u.entity IS NOT NULL";
1501  }
1502  else
1503  {
1504  if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))
1505  {
1506  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."usergroup_user as ug";
1507  $sql.= " ON ug.fk_user = u.rowid";
1508  $sql.= " WHERE ug.entity = ".$conf->entity;
1509  }
1510  else
1511  {
1512  $sql.= " WHERE u.entity IN (0,".$conf->entity.")";
1513  }
1514  }
1515  if (! empty($user->societe_id)) $sql.= " AND u.fk_soc = ".$user->societe_id;
1516  if (is_array($exclude) && $excludeUsers) $sql.= " AND u.rowid NOT IN (".$excludeUsers.")";
1517  if ($includeUsers) $sql.= " AND u.rowid IN (".$includeUsers.")";
1518  if (! empty($conf->global->USER_HIDE_INACTIVE_IN_COMBOBOX) || $noactive) $sql.= " AND u.statut <> 0";
1519  if (! empty($morefilter)) $sql.=" ".$morefilter;
1520 
1521  if(empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION)){
1522  $sql.= " ORDER BY u.firstname ASC";
1523  }else{
1524  $sql.= " ORDER BY u.lastname ASC";
1525  }
1526 
1527 
1528  dol_syslog(get_class($this)."::select_dolusers", LOG_DEBUG);
1529  $resql=$this->db->query($sql);
1530  if ($resql)
1531  {
1532  $num = $this->db->num_rows($resql);
1533  $i = 0;
1534  if ($num)
1535  {
1536  // Enhance with select2
1537  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
1538  $out .= ajax_combobox($htmlname);
1539 
1540  // do not use maxwidthonsmartphone by default. Set it by caller so auto size to 100% will work when not defined
1541  $out.= '<select class="flat'.($morecss?' minwidth100 '.$morecss:' minwidth200').'" id="'.$htmlname.'" name="'.$htmlname.'"'.($disabled?' disabled':'').'>';
1542  if ($show_empty) $out.= '<option value="-1"'.((empty($selected) || $selected==-1)?' selected':'').'>&nbsp;</option>'."\n";
1543  if ($show_every) $out.= '<option value="-2"'.(($selected==-2)?' selected':'').'>-- '.$langs->trans("Everybody").' --</option>'."\n";
1544 
1545  $userstatic=new User($this->db);
1546 
1547  while ($i < $num)
1548  {
1549  $obj = $this->db->fetch_object($resql);
1550 
1551  $userstatic->id=$obj->rowid;
1552  $userstatic->lastname=$obj->lastname;
1553  $userstatic->firstname=$obj->firstname;
1554 
1555  $disableline='';
1556  if (is_array($enableonly) && count($enableonly) && ! in_array($obj->rowid,$enableonly)) $disableline=($enableonlytext?$enableonlytext:'1');
1557 
1558  if ((is_object($selected) && $selected->id == $obj->rowid) || (! is_object($selected) && $selected == $obj->rowid))
1559  {
1560  $out.= '<option value="'.$obj->rowid.'"';
1561  if ($disableline) $out.= ' disabled';
1562  $out.= ' selected>';
1563  }
1564  else
1565  {
1566  $out.= '<option value="'.$obj->rowid.'"';
1567  if ($disableline) $out.= ' disabled';
1568  $out.= '>';
1569  }
1570 
1571  $fullNameMode = 0; //Lastname + firstname
1572  if(empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION)){
1573  $fullNameMode = 1; //firstname + lastname
1574  }
1575  $out.= $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength);
1576 
1577  // Complete name with more info
1578  $moreinfo=0;
1579  if (! empty($conf->global->MAIN_SHOW_LOGIN))
1580  {
1581  $out.= ($moreinfo?' - ':' (').$obj->login;
1582  $moreinfo++;
1583  }
1584  if ($showstatus >= 0)
1585  {
1586  if ($obj->statut == 1 && $showstatus == 1)
1587  {
1588  $out.=($moreinfo?' - ':' (').$langs->trans('Enabled');
1589  $moreinfo++;
1590  }
1591  if ($obj->statut == 0)
1592  {
1593  $out.=($moreinfo?' - ':' (').$langs->trans('Disabled');
1594  $moreinfo++;
1595  }
1596  }
1597  if (! empty($conf->multicompany->enabled) && empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $conf->entity == 1 && $user->admin && ! $user->entity)
1598  {
1599  if ($obj->admin && ! $obj->entity)
1600  {
1601  $out.=($moreinfo?' - ':' (').$langs->trans("AllEntities");
1602  $moreinfo++;
1603  }
1604  else
1605  {
1606  $out.=($moreinfo?' - ':' (').($obj->label?$obj->label:$langs->trans("EntityNameNotDefined"));
1607  $moreinfo++;
1608  }
1609  }
1610  $out.=($moreinfo?')':'');
1611  if ($disableline && $disableline != '1')
1612  {
1613  $out.=' - '.$disableline; // This is text from $enableonlytext parameter
1614  }
1615  $out.= '</option>';
1616 
1617  $i++;
1618  }
1619  }
1620  else
1621  {
1622  $out.= '<select class="flat" id="'.$htmlname.'" name="'.$htmlname.'" disabled>';
1623  $out.= '<option value="">'.$langs->trans("None").'</option>';
1624  }
1625  $out.= '</select>';
1626  }
1627  else
1628  {
1629  dol_print_error($this->db);
1630  }
1631 
1632  return $out;
1633  }
1634 
1635 
1658  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())
1659  {
1660  global $conf, $user, $langs;
1661 
1662  $userstatic=new User($this->db);
1663  $out='';
1664 
1665  // Method with no ajax
1666  //$out.='<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
1667  if ($action == 'view')
1668  {
1669  $out.='';
1670  }
1671  else
1672  {
1673  $out.='<input type="hidden" class="removedassignedhidden" name="removedassigned" value="">';
1674  $out.='<script type="text/javascript" language="javascript">jQuery(document).ready(function () { jQuery(".removedassigned").click(function() { jQuery(".removedassignedhidden").val(jQuery(this).val()); });})</script>';
1675  $out.=$this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter);
1676  $out.=' <input type="submit" class="button valignmiddle" name="'.$action.'assignedtouser" value="'.dol_escape_htmltag($langs->trans("Add")).'">';
1677  $out.='<br>';
1678  }
1679  $assignedtouser=array();
1680  if (!empty($_SESSION['assignedtouser']))
1681  {
1682  $assignedtouser=json_decode($_SESSION['assignedtouser'], true);
1683  }
1684  $nbassignetouser=count($assignedtouser);
1685 
1686  if ($nbassignetouser && $action != 'view') $out.='<br>';
1687  if ($nbassignetouser) $out.='<ul class="attendees">';
1688  $i=0; $ownerid=0;
1689  foreach($assignedtouser as $key => $value)
1690  {
1691  if ($value['id'] == $ownerid) continue;
1692 
1693  $out.='<li>';
1694  $userstatic->fetch($value['id']);
1695  $out.= $userstatic->getNomUrl(-1);
1696  if ($i == 0) { $ownerid = $value['id']; $out.=' ('.$langs->trans("Owner").')'; }
1697  if ($nbassignetouser > 1 && $action != 'view') $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.'">';
1698  // Show my availability
1699  if ($showproperties)
1700  {
1701  if ($ownerid == $value['id'] && is_array($listofuserid) && count($listofuserid) && in_array($ownerid, array_keys($listofuserid)))
1702  {
1703  $out.='<div class="myavailability inline-block">';
1704  $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");
1705  $out.='</div>';
1706  }
1707  }
1708  //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional"));
1709  //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy"));
1710 
1711  $out.='</li>';
1712  $i++;
1713  }
1714  if ($nbassignetouser) $out.='</ul>';
1715 
1716  //$out.='</form>';
1717  return $out;
1718  }
1719 
1720 
1746  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())
1747  {
1748  global $langs,$conf;
1749 
1750  $price_level = (! empty($price_level) ? $price_level : 0);
1751 
1752  if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT))
1753  {
1754  $placeholder='';
1755 
1756  if ($selected && empty($selected_input_value))
1757  {
1758  require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1759  $producttmpselect = new Product($this->db);
1760  $producttmpselect->fetch($selected);
1761  $selected_input_value=$producttmpselect->ref;
1762  unset($producttmpselect);
1763  }
1764  // mode=1 means customers products
1765  $urloption='htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&finished='.$finished.'&hidepriceinlabel='.$hidepriceinlabel.'&warehousestatus='.$warehouseStatus;
1766  //Price by customer
1767  if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
1768  $urloption.='&socid='.$socid;
1769  }
1770  print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
1771 
1772  if (!empty($conf->variants->enabled)) {
1773  ?>
1774  <script>
1775 
1776  selected = <?php echo json_encode($selected_combinations) ?>;
1777  combvalues = {};
1778 
1779  jQuery(document).ready(function () {
1780 
1781  jQuery("input[name='prod_entry_mode']").change(function () {
1782  if (jQuery(this).val() == 'free') {
1783  jQuery('div#attributes_box').empty();
1784  }
1785  });
1786 
1787  jQuery("input#<?php echo $htmlname ?>").change(function () {
1788 
1789  if (!jQuery(this).val()) {
1790  jQuery('div#attributes_box').empty();
1791  return;
1792  }
1793 
1794  jQuery.getJSON("<?php echo dol_buildpath('/variants/ajax/getCombinations.php', 2) ?>", {
1795  id: jQuery(this).val()
1796  }, function (data) {
1797  jQuery('div#attributes_box').empty();
1798 
1799  jQuery.each(data, function (key, val) {
1800 
1801  combvalues[val.id] = val.values;
1802 
1803  var span = jQuery(document.createElement('div')).css({
1804  'display': 'table-row'
1805  });
1806 
1807  span.append(
1808  jQuery(document.createElement('div')).text(val.label).css({
1809  'font-weight': 'bold',
1810  'display': 'table-cell',
1811  'text-align': 'right'
1812  })
1813  );
1814 
1815  var html = jQuery(document.createElement('select')).attr('name', 'combinations[' + val.id + ']').css({
1816  'margin-left': '15px',
1817  'white-space': 'pre'
1818  }).append(
1819  jQuery(document.createElement('option')).val('')
1820  );
1821 
1822  jQuery.each(combvalues[val.id], function (key, val) {
1823  var tag = jQuery(document.createElement('option')).val(val.id).html(val.value);
1824 
1825  if (selected[val.fk_product_attribute] == val.id) {
1826  tag.attr('selected', 'selected');
1827  }
1828 
1829  html.append(tag);
1830  });
1831 
1832  span.append(html);
1833  jQuery('div#attributes_box').append(span);
1834  });
1835  })
1836  });
1837 
1838  <?php if ($selected): ?>
1839  jQuery("input#<?php echo $htmlname ?>").change();
1840  <?php endif ?>
1841  });
1842  </script>
1843  <?php
1844  }
1845  if (empty($hidelabel)) print $langs->trans("RefOrLabel").' : ';
1846  else if ($hidelabel > 1) {
1847  $placeholder=' placeholder="'.$langs->trans("RefOrLabel").'"';
1848  if ($hidelabel == 2) {
1849  print img_picto($langs->trans("Search"), 'search');
1850  }
1851  }
1852  print '<input type="text" class="minwidth100" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' '.(!empty($conf->global->PRODUCT_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />';
1853  if ($hidelabel == 3) {
1854  print img_picto($langs->trans("Search"), 'search');
1855  }
1856  }
1857  else
1858  {
1859  print $this->select_produits_list($selected,$htmlname,$filtertype,$limit,$price_level,'',$status,$finished,0,$socid,$showempty,$forcecombo,$morecss,$hidepriceinlabel, $warehouseStatus);
1860  }
1861  }
1862 
1886  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='')
1887  {
1888  global $langs,$conf,$user,$db;
1889 
1890  $out='';
1891  $outarray=array();
1892 
1893  $warehouseStatusArray = array();
1894  if (! empty($warehouseStatus))
1895  {
1896  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
1897  if (preg_match('/warehouseclosed/', $warehouseStatus))
1898  {
1899  $warehouseStatusArray[] = Entrepot::STATUS_CLOSED;
1900  }
1901  if (preg_match('/warehouseopen/', $warehouseStatus))
1902  {
1903  $warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL;
1904  }
1905  if (preg_match('/warehouseinternal/', $warehouseStatus))
1906  {
1907  $warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL;
1908  }
1909  }
1910 
1911  $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";
1912  (count($warehouseStatusArray)) ? $selectFieldsGrouped = ", sum(ps.reel) as stock" : $selectFieldsGrouped = ", p.stock";
1913 
1914  $sql = "SELECT ";
1915  $sql.= $selectFields . $selectFieldsGrouped;
1916  //Price by customer
1917  if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid))
1918  {
1919  $sql.=', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
1920  $sql.=' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx';
1921  $selectFields.= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx";
1922  }
1923 
1924  // Multilang : we add translation
1925  if (! empty($conf->global->MAIN_MULTILANGS))
1926  {
1927  $sql.= ", pl.label as label_translated";
1928  $selectFields.= ", label_translated";
1929  }
1930  // Price by quantity
1931  if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
1932  {
1933  $sql.= ", (SELECT pp.rowid FROM ".MAIN_DB_PREFIX."product_price as pp WHERE pp.fk_product = p.rowid";
1934  if ($price_level >= 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) $sql.= " AND price_level=".$price_level;
1935  $sql.= " ORDER BY date_price";
1936  $sql.= " DESC LIMIT 1) as price_rowid";
1937  $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
1938  if ($price_level >= 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) $sql.= " AND price_level=".$price_level;
1939  $sql.= " ORDER BY date_price";
1940  $sql.= " DESC LIMIT 1) as price_by_qty";
1941  $selectFields.= ", price_rowid, price_by_qty";
1942  }
1943  $sql.= " FROM ".MAIN_DB_PREFIX."product as p";
1944  if (count($warehouseStatusArray))
1945  {
1946  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps on ps.fk_product = p.rowid";
1947  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e on ps.fk_entrepot = e.rowid";
1948  }
1949 
1950  //Price by customer
1951  if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
1952  $sql.=" LEFT JOIN ".MAIN_DB_PREFIX."product_customer_price as pcp ON pcp.fk_soc=".$socid." AND pcp.fk_product=p.rowid";
1953  }
1954  // Multilang : we add translation
1955  if (! empty($conf->global->MAIN_MULTILANGS))
1956  {
1957  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND pl.lang='". $langs->getDefaultLang() ."'";
1958  }
1959 
1960  if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) {
1961  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination pac ON pac.fk_product_child = p.rowid";
1962  }
1963 
1964  $sql.= ' WHERE p.entity IN ('.getEntity('product').')';
1965  if (count($warehouseStatusArray))
1966  {
1967  $sql.= ' AND (p.fk_product_type = 1 OR e.statut IN ('.$this->db->escape(implode(',',$warehouseStatusArray)).'))';
1968  }
1969 
1970  if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) {
1971  $sql .= " AND pac.rowid IS NULL";
1972  }
1973 
1974  if ($finished == 0)
1975  {
1976  $sql.= " AND p.finished = ".$finished;
1977  }
1978  elseif ($finished == 1)
1979  {
1980  $sql.= " AND p.finished = ".$finished;
1981  if ($status >= 0) $sql.= " AND p.tosell = ".$status;
1982  }
1983  elseif ($status >= 0)
1984  {
1985  $sql.= " AND p.tosell = ".$status;
1986  }
1987  if (strval($filtertype) != '') $sql.=" AND p.fk_product_type=".$filtertype;
1988  // Add criteria on ref/label
1989  if ($filterkey != '')
1990  {
1991  $sql.=' AND (';
1992  $prefix=empty($conf->global->PRODUCT_DONOTSEARCH_ANYWHERE)?'%':''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
1993  // For natural search
1994  $scrit = explode(' ', $filterkey);
1995  $i=0;
1996  if (count($scrit) > 1) $sql.="(";
1997  foreach ($scrit as $crit)
1998  {
1999  if ($i > 0) $sql.=" AND ";
2000  $sql.="(p.ref LIKE '".$db->escape($prefix.$crit)."%' OR p.label LIKE '".$db->escape($prefix.$crit)."%'";
2001  if (! empty($conf->global->MAIN_MULTILANGS)) $sql.=" OR pl.label LIKE '".$db->escape($prefix.$crit)."%'";
2002  $sql.=")";
2003  $i++;
2004  }
2005  if (count($scrit) > 1) $sql.=")";
2006  if (! empty($conf->barcode->enabled)) $sql.= " OR p.barcode LIKE '".$db->escape($prefix.$filterkey)."%'";
2007  $sql.=')';
2008  }
2009  if (count($warehouseStatusArray))
2010  {
2011  $sql.= ' GROUP BY'.$selectFields;
2012  }
2013  $sql.= $db->order("p.ref");
2014  $sql.= $db->plimit($limit, 0);
2015 
2016  // Build output string
2017  dol_syslog(get_class($this)."::select_produits_list search product", LOG_DEBUG);
2018  $result=$this->db->query($sql);
2019  if ($result)
2020  {
2021  require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
2022  require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
2023  $num = $this->db->num_rows($result);
2024 
2025  $events=null;
2026 
2027  if (! $forcecombo)
2028  {
2029  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2030  $out .= ajax_combobox($htmlname, $events, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT);
2031  }
2032 
2033  $out.='<select class="flat'.($morecss?' '.$morecss:'').'" name="'.$htmlname.'" id="'.$htmlname.'">';
2034 
2035  $textifempty='';
2036  // Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
2037  //if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
2038  if (! empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT))
2039  {
2040  if ($showempty && ! is_numeric($showempty)) $textifempty=$langs->trans($showempty);
2041  else $textifempty.=$langs->trans("All");
2042  }
2043  if ($showempty) $out.='<option value="0" selected>'.$textifempty.'</option>';
2044 
2045  $i = 0;
2046  while ($num && $i < $num)
2047  {
2048  $opt = '';
2049  $optJson = array();
2050  $objp = $this->db->fetch_object($result);
2051 
2052  if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) && !empty($objp->price_by_qty) && $objp->price_by_qty == 1)
2053  { // Price by quantity will return many prices for the same product
2054  $sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise, price_base_type";
2055  $sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty";
2056  $sql.= " WHERE fk_product_price=".$objp->price_rowid;
2057  $sql.= " ORDER BY quantity ASC";
2058 
2059  dol_syslog(get_class($this)."::select_produits_list search price by qty", LOG_DEBUG);
2060  $result2 = $this->db->query($sql);
2061  if ($result2)
2062  {
2063  $nb_prices = $this->db->num_rows($result2);
2064  $j = 0;
2065  while ($nb_prices && $j < $nb_prices) {
2066  $objp2 = $this->db->fetch_object($result2);
2067 
2068  $objp->price_by_qty_rowid = $objp2->rowid;
2069  $objp->price_by_qty_price_base_type = $objp2->price_base_type;
2070  $objp->price_by_qty_quantity = $objp2->quantity;
2071  $objp->price_by_qty_unitprice = $objp2->unitprice;
2072  $objp->price_by_qty_remise_percent = $objp2->remise_percent;
2073  // For backward compatibility
2074  $objp->quantity = $objp2->quantity;
2075  $objp->price = $objp2->price;
2076  $objp->unitprice = $objp2->unitprice;
2077  $objp->remise_percent = $objp2->remise_percent;
2078  $objp->remise = $objp2->remise;
2079 
2080  $this->constructProductListOption($objp, $opt, $optJson, 0, $selected, $hidepriceinlabel);
2081 
2082  $j++;
2083 
2084  // Add new entry
2085  // "key" value of json key array is used by jQuery automatically as selected value
2086  // "label" value of json key array is used by jQuery automatically as text for combo box
2087  $out.=$opt;
2088  array_push($outarray, $optJson);
2089  }
2090  }
2091  }
2092  else
2093  {
2094  if (!empty($conf->dynamicprices->enabled) && !empty($objp->fk_price_expression)) {
2095  $price_product = new Product($this->db);
2096  $price_product->fetch($objp->rowid, '', '', 1);
2097  $priceparser = new PriceParser($this->db);
2098  $price_result = $priceparser->parseProduct($price_product);
2099  if ($price_result >= 0) {
2100  $objp->price = $price_result;
2101  $objp->unitprice = $price_result;
2102  //Calculate the VAT
2103  $objp->price_ttc = price2num($objp->price) * (1 + ($objp->tva_tx / 100));
2104  $objp->price_ttc = price2num($objp->price_ttc,'MU');
2105  }
2106  }
2107  $this->constructProductListOption($objp, $opt, $optJson, $price_level, $selected, $hidepriceinlabel);
2108  // Add new entry
2109  // "key" value of json key array is used by jQuery automatically as selected value
2110  // "label" value of json key array is used by jQuery automatically as text for combo box
2111  $out.=$opt;
2112  array_push($outarray, $optJson);
2113  }
2114 
2115  $i++;
2116  }
2117 
2118  $out.='</select>';
2119 
2120  $this->db->free($result);
2121 
2122  if (empty($outputmode)) return $out;
2123  return $outarray;
2124  }
2125  else
2126  {
2127  dol_print_error($db);
2128  }
2129  }
2130 
2142  private function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel=0)
2143  {
2144  global $langs,$conf,$user,$db;
2145 
2146  $outkey='';
2147  $outval='';
2148  $outref='';
2149  $outlabel='';
2150  $outdesc='';
2151  $outbarcode='';
2152  $outtype='';
2153  $outprice_ht='';
2154  $outprice_ttc='';
2155  $outpricebasetype='';
2156  $outtva_tx='';
2157  $outqty=1;
2158  $outdiscount=0;
2159 
2160  $maxlengtharticle=(empty($conf->global->PRODUCT_MAX_LENGTH_COMBO)?48:$conf->global->PRODUCT_MAX_LENGTH_COMBO);
2161 
2162  $label=$objp->label;
2163  if (! empty($objp->label_translated)) $label=$objp->label_translated;
2164  if (! empty($filterkey) && $filterkey != '') $label=preg_replace('/('.preg_quote($filterkey).')/i','<strong>$1</strong>',$label,1);
2165 
2166  $outkey=$objp->rowid;
2167  $outref=$objp->ref;
2168  $outlabel=$objp->label;
2169  $outdesc=$objp->description;
2170  $outbarcode=$objp->barcode;
2171 
2172  $outtype=$objp->fk_product_type;
2173  $outdurationvalue=$outtype == Product::TYPE_SERVICE?substr($objp->duration,0,dol_strlen($objp->duration)-1):'';
2174  $outdurationunit=$outtype == Product::TYPE_SERVICE?substr($objp->duration,-1):'';
2175 
2176  $opt = '<option value="'.$objp->rowid.'"';
2177  $opt.= ($objp->rowid == $selected)?' selected':'';
2178  if (!empty($objp->price_by_qty_rowid) && $objp->price_by_qty_rowid > 0)
2179  {
2180  $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.'"';
2181  }
2182  if (! empty($conf->stock->enabled) && $objp->fk_product_type == 0 && isset($objp->stock))
2183  {
2184  if ($objp->stock > 0) $opt.= ' class="product_line_stock_ok"';
2185  else if ($objp->stock <= 0) $opt.= ' class="product_line_stock_too_low"';
2186  }
2187  $opt.= '>';
2188  $opt.= $objp->ref;
2189  if ($outbarcode) $opt.=' ('.$outbarcode.')';
2190  $opt.=' - '.dol_trunc($label,$maxlengtharticle);
2191 
2192  $objRef = $objp->ref;
2193  if (! empty($filterkey) && $filterkey != '') $objRef=preg_replace('/('.preg_quote($filterkey).')/i','<strong>$1</strong>',$objRef,1);
2194  $outval.=$objRef;
2195  if ($outbarcode) $outval.=' ('.$outbarcode.')';
2196  $outval.=' - '.dol_trunc($label,$maxlengtharticle);
2197 
2198  $found=0;
2199 
2200  // Multiprice
2201  if (empty($hidepriceinlabel) && $price_level >= 1 && $conf->global->PRODUIT_MULTIPRICES) // If we need a particular price level (from 1 to 6)
2202  {
2203  $sql = "SELECT price, price_ttc, price_base_type, tva_tx";
2204  $sql.= " FROM ".MAIN_DB_PREFIX."product_price";
2205  $sql.= " WHERE fk_product='".$objp->rowid."'";
2206  $sql.= " AND entity IN (".getEntity('productprice').")";
2207  $sql.= " AND price_level=".$price_level;
2208  $sql.= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid.
2209  $sql.= " LIMIT 1";
2210 
2211  dol_syslog(get_class($this).'::constructProductListOption search price for level '.$price_level.'', LOG_DEBUG);
2212  $result2 = $this->db->query($sql);
2213  if ($result2)
2214  {
2215  $objp2 = $this->db->fetch_object($result2);
2216  if ($objp2)
2217  {
2218  $found=1;
2219  if ($objp2->price_base_type == 'HT')
2220  {
2221  $opt.= ' - '.price($objp2->price,1,$langs,0,0,-1,$conf->currency).' '.$langs->trans("HT");
2222  $outval.= ' - '.price($objp2->price,0,$langs,0,0,-1,$conf->currency).' '.$langs->transnoentities("HT");
2223  }
2224  else
2225  {
2226  $opt.= ' - '.price($objp2->price_ttc,1,$langs,0,0,-1,$conf->currency).' '.$langs->trans("TTC");
2227  $outval.= ' - '.price($objp2->price_ttc,0,$langs,0,0,-1,$conf->currency).' '.$langs->transnoentities("TTC");
2228  }
2229  $outprice_ht=price($objp2->price);
2230  $outprice_ttc=price($objp2->price_ttc);
2231  $outpricebasetype=$objp2->price_base_type;
2232  $outtva_tx=$objp2->tva_tx;
2233  }
2234  }
2235  else
2236  {
2237  dol_print_error($this->db);
2238  }
2239  }
2240 
2241  // Price by quantity
2242  if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1 && ! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
2243  {
2244  $found = 1;
2245  $outqty=$objp->quantity;
2246  $outdiscount=$objp->remise_percent;
2247  if ($objp->quantity == 1)
2248  {
2249  $opt.= ' - '.price($objp->unitprice,1,$langs,0,0,-1,$conf->currency)."/";
2250  $outval.= ' - '.price($objp->unitprice,0,$langs,0,0,-1,$conf->currency)."/";
2251  $opt.= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
2252  $outval.=$langs->transnoentities("Unit");
2253  }
2254  else
2255  {
2256  $opt.= ' - '.price($objp->price,1,$langs,0,0,-1,$conf->currency)."/".$objp->quantity;
2257  $outval.= ' - '.price($objp->price,0,$langs,0,0,-1,$conf->currency)."/".$objp->quantity;
2258  $opt.= $langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
2259  $outval.=$langs->transnoentities("Units");
2260  }
2261 
2262  $outprice_ht=price($objp->unitprice);
2263  $outprice_ttc=price($objp->unitprice * (1 + ($objp->tva_tx / 100)));
2264  $outpricebasetype=$objp->price_base_type;
2265  $outtva_tx=$objp->tva_tx;
2266  }
2267  if (empty($hidepriceinlabel) && !empty($objp->quantity) && $objp->quantity >= 1)
2268  {
2269  $opt.=" (".price($objp->unitprice,1,$langs,0,0,-1,$conf->currency)."/".$langs->trans("Unit").")"; // Do not use strtolower because it breaks utf8 encoding
2270  $outval.=" (".price($objp->unitprice,0,$langs,0,0,-1,$conf->currency)."/".$langs->transnoentities("Unit").")"; // Do not use strtolower because it breaks utf8 encoding
2271  }
2272  if (empty($hidepriceinlabel) && !empty($objp->remise_percent) && $objp->remise_percent >= 1)
2273  {
2274  $opt.=" - ".$langs->trans("Discount")." : ".vatrate($objp->remise_percent).' %';
2275  $outval.=" - ".$langs->transnoentities("Discount")." : ".vatrate($objp->remise_percent).' %';
2276  }
2277 
2278  // Price by customer
2279  if (empty($hidepriceinlabel) && !empty($conf->global->PRODUIT_CUSTOMER_PRICES))
2280  {
2281  if (!empty($objp->idprodcustprice))
2282  {
2283  $found = 1;
2284 
2285  if ($objp->custprice_base_type == 'HT')
2286  {
2287  $opt.= ' - '.price($objp->custprice,1,$langs,0,0,-1,$conf->currency).' '.$langs->trans("HT");
2288  $outval.= ' - '.price($objp->custprice,0,$langs,0,0,-1,$conf->currency).' '.$langs->transnoentities("HT");
2289  }
2290  else
2291  {
2292  $opt.= ' - '.price($objp->custprice_ttc,1,$langs,0,0,-1,$conf->currency).' '.$langs->trans("TTC");
2293  $outval.= ' - '.price($objp->custprice_ttc,0,$langs,0,0,-1,$conf->currency).' '.$langs->transnoentities("TTC");
2294  }
2295 
2296  $outprice_ht=price($objp->custprice);
2297  $outprice_ttc=price($objp->custprice_ttc);
2298  $outpricebasetype=$objp->custprice_base_type;
2299  $outtva_tx=$objp->custtva_tx;
2300  }
2301  }
2302 
2303  // If level no defined or multiprice not found, we used the default price
2304  if (empty($hidepriceinlabel) && ! $found)
2305  {
2306  if ($objp->price_base_type == 'HT')
2307  {
2308  $opt.= ' - '.price($objp->price,1,$langs,0,0,-1,$conf->currency).' '.$langs->trans("HT");
2309  $outval.= ' - '.price($objp->price,0,$langs,0,0,-1,$conf->currency).' '.$langs->transnoentities("HT");
2310  }
2311  else
2312  {
2313  $opt.= ' - '.price($objp->price_ttc,1,$langs,0,0,-1,$conf->currency).' '.$langs->trans("TTC");
2314  $outval.= ' - '.price($objp->price_ttc,0,$langs,0,0,-1,$conf->currency).' '.$langs->transnoentities("TTC");
2315  }
2316  $outprice_ht=price($objp->price);
2317  $outprice_ttc=price($objp->price_ttc);
2318  $outpricebasetype=$objp->price_base_type;
2319  $outtva_tx=$objp->tva_tx;
2320  }
2321 
2322  if (! empty($conf->stock->enabled) && isset($objp->stock) && $objp->fk_product_type == 0)
2323  {
2324  $opt.= ' - '.$langs->trans("Stock").':'.$objp->stock;
2325 
2326  if ($objp->stock > 0) {
2327  $outval.= ' - <span class="product_line_stock_ok">'.$langs->transnoentities("Stock").':'.$objp->stock.'</span>';
2328  }elseif ($objp->stock <= 0) {
2329  $outval.= ' - <span class="product_line_stock_too_low">'.$langs->transnoentities("Stock").':'.$objp->stock.'</span>';
2330  }
2331  }
2332 
2333  if ($outdurationvalue && $outdurationunit)
2334  {
2335  $da=array("h"=>$langs->trans("Hour"),"d"=>$langs->trans("Day"),"w"=>$langs->trans("Week"),"m"=>$langs->trans("Month"),"y"=>$langs->trans("Year"));
2336  if (isset($da[$outdurationunit]))
2337  {
2338  $key = $da[$outdurationunit].($outdurationvalue > 1?'s':'');
2339  $opt.= ' - '.$outdurationvalue.' '.$langs->trans($key);
2340  $outval.=' - '.$outdurationvalue.' '.$langs->transnoentities($key);
2341  }
2342  }
2343 
2344  $opt.= "</option>\n";
2345  $optJson = array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'label2'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>$outprice_ht, 'price_ttc'=>$outprice_ttc, 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, 'discount'=>$outdiscount, 'duration_value'=>$outdurationvalue, 'duration_unit'=>$outdurationunit);
2346  }
2347 
2361  function select_produits_fournisseurs($socid, $selected='', $htmlname='productid', $filtertype='', $filtre='', $ajaxoptions=array(), $hidelabel=0, $alsoproductwithnosupplierprice=0)
2362  {
2363  global $langs,$conf;
2364  global $price_level, $status, $finished;
2365 
2366  $selected_input_value='';
2367  if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT))
2368  {
2369  if ($selected > 0)
2370  {
2371  require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
2372  $producttmpselect = new Product($this->db);
2373  $producttmpselect->fetch($selected);
2374  $selected_input_value=$producttmpselect->ref;
2375  unset($producttmpselect);
2376  }
2377 
2378  // mode=2 means suppliers products
2379  $urloption=($socid > 0?'socid='.$socid.'&':'').'htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=2&status='.$status.'&finished='.$finished.'&alsoproductwithnosupplierprice='.$alsoproductwithnosupplierprice;
2380  print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
2381  print ($hidelabel?'':$langs->trans("RefOrLabel").' : ').'<input type="text" size="20" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'">';
2382  }
2383  else
2384  {
2385  print $this->select_produits_fournisseurs_list($socid,$selected,$htmlname,$filtertype,$filtre,'',-1,0,0,$alsoproductwithnosupplierprice);
2386  }
2387  }
2388 
2404  function select_produits_fournisseurs_list($socid,$selected='',$htmlname='productid',$filtertype='',$filtre='',$filterkey='',$statut=-1,$outputmode=0,$limit=100,$alsoproductwithnosupplierprice=0)
2405  {
2406  global $langs,$conf,$db;
2407 
2408  $out='';
2409  $outarray=array();
2410 
2411  $langs->load('stocks');
2412 
2413  $sql = "SELECT p.rowid, p.label, p.ref, p.price, p.duration, p.fk_product_type,";
2414  $sql.= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice,";
2415  $sql.= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.fk_soc, s.nom as name,";
2416  $sql.= " pfp.supplier_reputation";
2417  $sql.= " FROM ".MAIN_DB_PREFIX."product as p";
2418  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
2419  if ($socid) $sql.= " AND pfp.fk_soc = ".$socid;
2420  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON pfp.fk_soc = s.rowid";
2421  $sql.= " WHERE p.entity IN (".getEntity('product').")";
2422  $sql.= " AND p.tobuy = 1";
2423  if (strval($filtertype) != '') $sql.=" AND p.fk_product_type=".$this->db->escape($filtertype);
2424  if (! empty($filtre)) $sql.=" ".$filtre;
2425  // Add criteria on ref/label
2426  if ($filterkey != '')
2427  {
2428  $sql.=' AND (';
2429  $prefix=empty($conf->global->PRODUCT_DONOTSEARCH_ANYWHERE)?'%':''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
2430  // For natural search
2431  $scrit = explode(' ', $filterkey);
2432  $i=0;
2433  if (count($scrit) > 1) $sql.="(";
2434  foreach ($scrit as $crit)
2435  {
2436  if ($i > 0) $sql.=" AND ";
2437  $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)."%')";
2438  $i++;
2439  }
2440  if (count($scrit) > 1) $sql.=")";
2441  if (! empty($conf->barcode->enabled)) $sql.= " OR p.barcode LIKE '".$this->db->escape($prefix.$filterkey)."%'";
2442  $sql.=')';
2443  }
2444  $sql.= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC";
2445  $sql.= $db->plimit($limit, 0);
2446 
2447  // Build output string
2448 
2449  dol_syslog(get_class($this)."::select_produits_fournisseurs_list", LOG_DEBUG);
2450  $result=$this->db->query($sql);
2451  if ($result)
2452  {
2453  require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
2454 
2455  $num = $this->db->num_rows($result);
2456 
2457  //$out.='<select class="flat" id="select'.$htmlname.'" name="'.$htmlname.'">'; // remove select to have id same with combo and ajax
2458  $out.='<select class="flat maxwidthonsmartphone" id="'.$htmlname.'" name="'.$htmlname.'">';
2459  if (! $selected) $out.='<option value="0" selected>&nbsp;</option>';
2460  else $out.='<option value="0">&nbsp;</option>';
2461 
2462  $i = 0;
2463  while ($i < $num)
2464  {
2465  $objp = $this->db->fetch_object($result);
2466 
2467  $outkey=$objp->idprodfournprice; // id in table of price
2468  if (! $outkey && $alsoproductwithnosupplierprice) $outkey='idprod_'.$objp->rowid; // id of product
2469 
2470  $outref=$objp->ref;
2471  $outval='';
2472  $outqty=1;
2473  $outdiscount=0;
2474  $outtype=$objp->fk_product_type;
2475  $outdurationvalue=$outtype == Product::TYPE_SERVICE?substr($objp->duration,0,dol_strlen($objp->duration)-1):'';
2476  $outdurationunit=$outtype == Product::TYPE_SERVICE?substr($objp->duration,-1):'';
2477 
2478  $opt = '<option value="'.$outkey.'"';
2479  if ($selected && $selected == $objp->idprodfournprice) $opt.= ' selected';
2480  if (empty($objp->idprodfournprice) && empty($alsoproductwithnosupplierprice)) $opt.=' disabled';
2481  $opt.= '>';
2482 
2483  $objRef = $objp->ref;
2484  if ($filterkey && $filterkey != '') $objRef=preg_replace('/('.preg_quote($filterkey).')/i','<strong>$1</strong>',$objRef,1);
2485  $objRefFourn = $objp->ref_fourn;
2486  if ($filterkey && $filterkey != '') $objRefFourn=preg_replace('/('.preg_quote($filterkey).')/i','<strong>$1</strong>',$objRefFourn,1);
2487  $label = $objp->label;
2488  if ($filterkey && $filterkey != '') $label=preg_replace('/('.preg_quote($filterkey).')/i','<strong>$1</strong>',$label,1);
2489 
2490  $opt.=$objp->ref;
2491  if (! empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn))
2492  $opt.=' ('.$objp->ref_fourn.')';
2493  $opt.=' - ';
2494  $outval.=$objRef;
2495  if (! empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn))
2496  $outval.=' ('.$objRefFourn.')';
2497  $outval.=' - ';
2498  $opt.=dol_trunc($label, 72).' - ';
2499  $outval.=dol_trunc($label, 72).' - ';
2500 
2501  if (! empty($objp->idprodfournprice))
2502  {
2503  $outqty=$objp->quantity;
2504  $outdiscount=$objp->remise_percent;
2505  if (!empty($conf->dynamicprices->enabled) && !empty($objp->fk_supplier_price_expression)) {
2506  $prod_supplier = new ProductFournisseur($this->db);
2507  $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
2508  $prod_supplier->id = $objp->fk_product;
2509  $prod_supplier->fourn_qty = $objp->quantity;
2510  $prod_supplier->fourn_tva_tx = $objp->tva_tx;
2511  $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
2512  $priceparser = new PriceParser($this->db);
2513  $price_result = $priceparser->parseProductSupplier($prod_supplier);
2514  if ($price_result >= 0) {
2515  $objp->fprice = $price_result;
2516  if ($objp->quantity >= 1)
2517  {
2518  $objp->unitprice = $objp->fprice / $objp->quantity;
2519  }
2520  }
2521  }
2522  if ($objp->quantity == 1)
2523  {
2524  $opt.= price($objp->fprice,1,$langs,0,0,-1,$conf->currency)."/";
2525  $outval.= price($objp->fprice,0,$langs,0,0,-1,$conf->currency)."/";
2526  $opt.= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding
2527  $outval.=$langs->transnoentities("Unit");
2528  }
2529  else
2530  {
2531  $opt.= price($objp->fprice,1,$langs,0,0,-1,$conf->currency)."/".$objp->quantity;
2532  $outval.= price($objp->fprice,0,$langs,0,0,-1,$conf->currency)."/".$objp->quantity;
2533  $opt.= ' '.$langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding
2534  $outval.= ' '.$langs->transnoentities("Units");
2535  }
2536 
2537  if ($objp->quantity >= 1)
2538  {
2539  $opt.=" (".price($objp->unitprice,1,$langs,0,0,-1,$conf->currency)."/".$langs->trans("Unit").")"; // Do not use strtolower because it breaks utf8 encoding
2540  $outval.=" (".price($objp->unitprice,0,$langs,0,0,-1,$conf->currency)."/".$langs->transnoentities("Unit").")"; // Do not use strtolower because it breaks utf8 encoding
2541  }
2542  if ($objp->remise_percent >= 1)
2543  {
2544  $opt.=" - ".$langs->trans("Discount")." : ".vatrate($objp->remise_percent).' %';
2545  $outval.=" - ".$langs->transnoentities("Discount")." : ".vatrate($objp->remise_percent).' %';
2546  }
2547  if ($objp->duration)
2548  {
2549  $opt .= " - ".$objp->duration;
2550  $outval.=" - ".$objp->duration;
2551  }
2552  if (! $socid)
2553  {
2554  $opt .= " - ".dol_trunc($objp->name,8);
2555  $outval.=" - ".dol_trunc($objp->name,8);
2556  }
2557  if ($objp->supplier_reputation)
2558  {
2559  //TODO dictionary
2560  $reputations=array(''=>$langs->trans('Standard'),'FAVORITE'=>$langs->trans('Favorite'),'NOTTHGOOD'=>$langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER'=>$langs->trans('DoNotOrderThisProductToThisSupplier'));
2561 
2562  $opt .= " - ".$reputations[$objp->supplier_reputation];
2563  $outval.=" - ".$reputations[$objp->supplier_reputation];
2564  }
2565  }
2566  else
2567  {
2568  if (empty($alsoproductwithnosupplierprice)) // No supplier price defined for couple product/supplier
2569  {
2570  $opt.= $langs->trans("NoPriceDefinedForThisSupplier");
2571  $outval.=$langs->transnoentities("NoPriceDefinedForThisSupplier");
2572  }
2573  else // No supplier price defined for product, even on other suppliers
2574  {
2575  $opt.= $langs->trans("NoPriceDefinedForThisSupplier");
2576  $outval.=$langs->transnoentities("NoPriceDefinedForThisSupplier");
2577  }
2578  }
2579  $opt .= "</option>\n";
2580 
2581 
2582  // Add new entry
2583  // "key" value of json key array is used by jQuery automatically as selected value
2584  // "label" value of json key array is used by jQuery automatically as text for combo box
2585  $out.=$opt;
2586  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)));
2587  // Exemple of var_dump $outarray
2588  // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp"
2589  // ["label"]=>string(76) "ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)"
2590  // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false)
2591  //}
2592  //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
2593  //$outval=array('label'=>'ppp (<strong>f</strong>ff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)');
2594  //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval));
2595 
2596  $i++;
2597  }
2598  $out.='</select>';
2599 
2600  $this->db->free($result);
2601 
2602  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2603  $out.=ajax_combobox($htmlname);
2604 
2605  if (empty($outputmode)) return $out;
2606  return $outarray;
2607  }
2608  else
2609  {
2610  dol_print_error($this->db);
2611  }
2612  }
2613 
2622  function select_product_fourn_price($productid, $htmlname='productfournpriceid', $selected_supplier='')
2623  {
2624  global $langs,$conf;
2625 
2626  $langs->load('stocks');
2627 
2628  $sql = "SELECT p.rowid, p.label, p.ref, p.price, p.duration, pfp.fk_soc,";
2629  $sql.= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.unitprice,";
2630  $sql.= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name";
2631  $sql.= " FROM ".MAIN_DB_PREFIX."product as p";
2632  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
2633  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON pfp.fk_soc = s.rowid";
2634  $sql.= " WHERE p.entity IN (".getEntity('productprice').")";
2635  $sql.= " AND p.tobuy = 1";
2636  $sql.= " AND s.fournisseur = 1";
2637  $sql.= " AND p.rowid = ".$productid;
2638  $sql.= " ORDER BY s.nom, pfp.ref_fourn DESC";
2639 
2640  dol_syslog(get_class($this)."::select_product_fourn_price", LOG_DEBUG);
2641  $result=$this->db->query($sql);
2642 
2643  if ($result)
2644  {
2645  $num = $this->db->num_rows($result);
2646 
2647  $form = '<select class="flat" name="'.$htmlname.'">';
2648 
2649  if (! $num)
2650  {
2651  $form.= '<option value="0">-- '.$langs->trans("NoSupplierPriceDefinedForThisProduct").' --</option>';
2652  }
2653  else
2654  {
2655  require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
2656  $form.= '<option value="0">&nbsp;</option>';
2657 
2658  $i = 0;
2659  while ($i < $num)
2660  {
2661  $objp = $this->db->fetch_object($result);
2662 
2663  $opt = '<option value="'.$objp->idprodfournprice.'"';
2664  //if there is only one supplier, preselect it
2665  if($num == 1 || ($selected_supplier > 0 && $objp->fk_soc == $selected_supplier)) {
2666  $opt .= ' selected';
2667  }
2668  $opt.= '>'.$objp->name.' - '.$objp->ref_fourn.' - ';
2669 
2670  if (!empty($conf->dynamicprices->enabled) && !empty($objp->fk_supplier_price_expression)) {
2671  $prod_supplier = new ProductFournisseur($this->db);
2672  $prod_supplier->product_fourn_price_id = $objp->idprodfournprice;
2673  $prod_supplier->id = $productid;
2674  $prod_supplier->fourn_qty = $objp->quantity;
2675  $prod_supplier->fourn_tva_tx = $objp->tva_tx;
2676  $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression;
2677  $priceparser = new PriceParser($this->db);
2678  $price_result = $priceparser->parseProductSupplier($prod_supplier);
2679  if ($price_result >= 0) {
2680  $objp->fprice = $price_result;
2681  if ($objp->quantity >= 1)
2682  {
2683  $objp->unitprice = $objp->fprice / $objp->quantity;
2684  }
2685  }
2686  }
2687  if ($objp->quantity == 1)
2688  {
2689  $opt.= price($objp->fprice,1,$langs,0,0,-1,$conf->currency)."/";
2690  }
2691 
2692  $opt.= $objp->quantity.' ';
2693 
2694  if ($objp->quantity == 1)
2695  {
2696  $opt.= $langs->trans("Unit");
2697  }
2698  else
2699  {
2700  $opt.= $langs->trans("Units");
2701  }
2702  if ($objp->quantity > 1)
2703  {
2704  $opt.=" - ";
2705  $opt.= price($objp->unitprice,1,$langs,0,0,-1,$conf->currency)."/".$langs->trans("Unit");
2706  }
2707  if ($objp->duration) $opt .= " - ".$objp->duration;
2708  $opt .= "</option>\n";
2709 
2710  $form.= $opt;
2711  $i++;
2712  }
2713  }
2714 
2715  $form.= '</select>';
2716  $this->db->free($result);
2717  return $form;
2718  }
2719  else
2720  {
2721  dol_print_error($this->db);
2722  }
2723  }
2724 
2734  function select_address($selected, $socid, $htmlname='address_id',$showempty=0)
2735  {
2736  // On recherche les utilisateurs
2737  $sql = "SELECT a.rowid, a.label";
2738  $sql .= " FROM ".MAIN_DB_PREFIX ."societe_address as a";
2739  $sql .= " WHERE a.fk_soc = ".$socid;
2740  $sql .= " ORDER BY a.label ASC";
2741 
2742  dol_syslog(get_class($this)."::select_address", LOG_DEBUG);
2743  $resql=$this->db->query($sql);
2744  if ($resql)
2745  {
2746  print '<select class="flat" name="'.$htmlname.'">';
2747  if ($showempty) print '<option value="0">&nbsp;</option>';
2748  $num = $this->db->num_rows($resql);
2749  $i = 0;
2750  if ($num)
2751  {
2752  while ($i < $num)
2753  {
2754  $obj = $this->db->fetch_object($resql);
2755 
2756  if ($selected && $selected == $obj->rowid)
2757  {
2758  print '<option value="'.$obj->rowid.'" selected>'.$obj->label.'</option>';
2759  }
2760  else
2761  {
2762  print '<option value="'.$obj->rowid.'">'.$obj->label.'</option>';
2763  }
2764  $i++;
2765  }
2766  }
2767  print '</select>';
2768  return $num;
2769  }
2770  else
2771  {
2772  dol_print_error($this->db);
2773  }
2774  }
2775 
2776 
2783  {
2784  global $langs;
2785 
2786  $num = count($this->cache_conditions_paiements);
2787  if ($num > 0) return 0; // Cache already loaded
2788 
2789  dol_syslog(__METHOD__, LOG_DEBUG);
2790 
2791  $sql = "SELECT rowid, code, libelle as label";
2792  $sql.= " FROM ".MAIN_DB_PREFIX.'c_payment_term';
2793  $sql.= " WHERE entity = " . getEntity('c_payment_term');
2794  $sql.= " AND active > 0";
2795  $sql.= " ORDER BY sortorder";
2796 
2797  $resql = $this->db->query($sql);
2798  if ($resql)
2799  {
2800  $num = $this->db->num_rows($resql);
2801  $i = 0;
2802  while ($i < $num)
2803  {
2804  $obj = $this->db->fetch_object($resql);
2805 
2806  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
2807  $label=($langs->trans("PaymentConditionShort".$obj->code)!=("PaymentConditionShort".$obj->code)?$langs->trans("PaymentConditionShort".$obj->code):($obj->label!='-'?$obj->label:''));
2808  $this->cache_conditions_paiements[$obj->rowid]['code'] =$obj->code;
2809  $this->cache_conditions_paiements[$obj->rowid]['label']=$label;
2810  $i++;
2811  }
2812 
2813  //$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1); // We use the field sortorder of table
2814 
2815  return $num;
2816  }
2817  else
2818  {
2819  dol_print_error($this->db);
2820  return -1;
2821  }
2822  }
2823 
2830  {
2831  global $langs;
2832 
2833  $num = count($this->cache_availability);
2834  if ($num > 0) return 0; // Cache already loaded
2835 
2836  dol_syslog(__METHOD__, LOG_DEBUG);
2837 
2838  $langs->load('propal');
2839 
2840  $sql = "SELECT rowid, code, label";
2841  $sql.= " FROM ".MAIN_DB_PREFIX.'c_availability';
2842  $sql.= " WHERE active > 0";
2843 
2844  $resql = $this->db->query($sql);
2845  if ($resql)
2846  {
2847  $num = $this->db->num_rows($resql);
2848  $i = 0;
2849  while ($i < $num)
2850  {
2851  $obj = $this->db->fetch_object($resql);
2852 
2853  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
2854  $label=($langs->trans("AvailabilityType".$obj->code)!=("AvailabilityType".$obj->code)?$langs->trans("AvailabilityType".$obj->code):($obj->label!='-'?$obj->label:''));
2855  $this->cache_availability[$obj->rowid]['code'] =$obj->code;
2856  $this->cache_availability[$obj->rowid]['label']=$label;
2857  $i++;
2858  }
2859 
2860  $this->cache_availability = dol_sort_array($this->cache_availability, 'label', 'asc', 0, 0, 1);
2861 
2862  return $num;
2863  }
2864  else
2865  {
2866  dol_print_error($this->db);
2867  return -1;
2868  }
2869  }
2870 
2880  function selectAvailabilityDelay($selected='',$htmlname='availid',$filtertype='',$addempty=0)
2881  {
2882  global $langs,$user;
2883 
2884  $this->load_cache_availability();
2885 
2886  dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG);
2887 
2888  print '<select class="flat" name="'.$htmlname.'">';
2889  if ($addempty) print '<option value="0">&nbsp;</option>';
2890  foreach($this->cache_availability as $id => $arrayavailability)
2891  {
2892  if ($selected == $id)
2893  {
2894  print '<option value="'.$id.'" selected>';
2895  }
2896  else
2897  {
2898  print '<option value="'.$id.'">';
2899  }
2900  print $arrayavailability['label'];
2901  print '</option>';
2902  }
2903  print '</select>';
2904  if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
2905  }
2906 
2913  {
2914  global $langs;
2915 
2916  $num = count($this->cache_demand_reason);
2917  if ($num > 0) return 0; // Cache already loaded
2918 
2919  $sql = "SELECT rowid, code, label";
2920  $sql.= " FROM ".MAIN_DB_PREFIX.'c_input_reason';
2921  $sql.= " WHERE active > 0";
2922 
2923  $resql = $this->db->query($sql);
2924  if ($resql)
2925  {
2926  $num = $this->db->num_rows($resql);
2927  $i = 0;
2928  $tmparray=array();
2929  while ($i < $num)
2930  {
2931  $obj = $this->db->fetch_object($resql);
2932 
2933  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
2934  $label=($langs->trans("DemandReasonType".$obj->code)!=("DemandReasonType".$obj->code)?$langs->trans("DemandReasonType".$obj->code):($obj->label!='-'?$obj->label:''));
2935  $tmparray[$obj->rowid]['id'] =$obj->rowid;
2936  $tmparray[$obj->rowid]['code'] =$obj->code;
2937  $tmparray[$obj->rowid]['label']=$label;
2938  $i++;
2939  }
2940 
2941  $this->cache_demand_reason=dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1);
2942 
2943  unset($tmparray);
2944  return $num;
2945  }
2946  else
2947  {
2948  dol_print_error($this->db);
2949  return -1;
2950  }
2951  }
2952 
2963  function selectInputReason($selected='',$htmlname='demandreasonid',$exclude='',$addempty=0)
2964  {
2965  global $langs,$user;
2966 
2967  $this->loadCacheInputReason();
2968 
2969  print '<select class="flat" name="'.$htmlname.'">';
2970  if ($addempty) print '<option value="0"'.(empty($selected)?' selected':'').'>&nbsp;</option>';
2971  foreach($this->cache_demand_reason as $id => $arraydemandreason)
2972  {
2973  if ($arraydemandreason['code']==$exclude) continue;
2974 
2975  if ($selected && ($selected == $arraydemandreason['id'] || $selected == $arraydemandreason['code']))
2976  {
2977  print '<option value="'.$arraydemandreason['id'].'" selected>';
2978  }
2979  else
2980  {
2981  print '<option value="'.$arraydemandreason['id'].'">';
2982  }
2983  print $arraydemandreason['label'];
2984  print '</option>';
2985  }
2986  print '</select>';
2987  if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
2988  }
2989 
2996  {
2997  global $langs;
2998 
2999  $num=count($this->cache_types_paiements);
3000  if ($num > 0) return $num; // Cache already loaded
3001 
3002  dol_syslog(__METHOD__, LOG_DEBUG);
3003 
3004  $this->cache_types_paiements = array();
3005 
3006  $sql = "SELECT id, code, libelle as label, type, active";
3007  $sql.= " FROM ".MAIN_DB_PREFIX."c_paiement";
3008  $sql.= " WHERE entity IN (".getEntity('c_paiement').")";
3009  //if ($active >= 0) $sql.= " AND active = ".$active;
3010 
3011  $resql = $this->db->query($sql);
3012  if ($resql)
3013  {
3014  $num = $this->db->num_rows($resql);
3015  $i = 0;
3016  while ($i < $num)
3017  {
3018  $obj = $this->db->fetch_object($resql);
3019 
3020  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
3021  $label=($langs->transnoentitiesnoconv("PaymentTypeShort".$obj->code)!=("PaymentTypeShort".$obj->code)?$langs->transnoentitiesnoconv("PaymentTypeShort".$obj->code):($obj->label!='-'?$obj->label:''));
3022  $this->cache_types_paiements[$obj->id]['id'] =$obj->id;
3023  $this->cache_types_paiements[$obj->id]['code'] =$obj->code;
3024  $this->cache_types_paiements[$obj->id]['label']=$label;
3025  $this->cache_types_paiements[$obj->id]['type'] =$obj->type;
3026  $this->cache_types_paiements[$obj->id]['active'] =$obj->active;
3027  $i++;
3028  }
3029 
3030  $this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1);
3031 
3032  return $num;
3033  }
3034  else
3035  {
3036  dol_print_error($this->db);
3037  return -1;
3038  }
3039  }
3040 
3041 
3055  function select_conditions_paiements($selected=0, $htmlname='condid', $filtertype=-1, $addempty=0, $noinfoadmin=0, $morecss='')
3056  {
3057  global $langs, $user, $conf;
3058 
3059  dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG);
3060 
3062 
3063  // Set default value if not already set by caller
3064  if (empty($selected) && ! empty($conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID)) $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID;
3065 
3066  print '<select id="'.$htmlname.'" class="flat selectpaymentterms'.($morecss?' '.$morecss:'').'" name="'.$htmlname.'">';
3067  if ($addempty) print '<option value="0">&nbsp;</option>';
3068  foreach($this->cache_conditions_paiements as $id => $arrayconditions)
3069  {
3070  if ($selected == $id)
3071  {
3072  print '<option value="'.$id.'" selected>';
3073  }
3074  else
3075  {
3076  print '<option value="'.$id.'">';
3077  }
3078  print $arrayconditions['label'];
3079  print '</option>';
3080  }
3081  print '</select>';
3082  if ($user->admin && empty($noinfoadmin)) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
3083  }
3084 
3085 
3100  function select_types_paiements($selected='', $htmlname='paiementtype', $filtertype='', $format=0, $empty=0, $noadmininfo=0, $maxlength=0, $active=1, $morecss='')
3101  {
3102  global $langs,$user;
3103 
3104  dol_syslog(__METHOD__." ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
3105 
3106  $filterarray=array();
3107  if ($filtertype == 'CRDT') $filterarray=array(0,2,3);
3108  elseif ($filtertype == 'DBIT') $filterarray=array(1,2,3);
3109  elseif ($filtertype != '' && $filtertype != '-1') $filterarray=explode(',',$filtertype);
3110 
3111  $this->load_cache_types_paiements();
3112 
3113  print '<select id="select'.$htmlname.'" class="flat selectpaymenttypes'.($morecss?' '.$morecss:'').'" name="'.$htmlname.'">';
3114  if ($empty) print '<option value="">&nbsp;</option>';
3115  foreach($this->cache_types_paiements as $id => $arraytypes)
3116  {
3117  // If not good status
3118  if ($active >= 0 && $arraytypes['active'] != $active) continue;
3119 
3120  // On passe si on a demande de filtrer sur des modes de paiments particuliers
3121  if (count($filterarray) && ! in_array($arraytypes['type'],$filterarray)) continue;
3122 
3123  // We discard empty line if showempty is on because an empty line has already been output.
3124  if ($empty && empty($arraytypes['code'])) continue;
3125 
3126  if ($format == 0) print '<option value="'.$id.'"';
3127  if ($format == 1) print '<option value="'.$arraytypes['code'].'"';
3128  if ($format == 2) print '<option value="'.$arraytypes['code'].'"';
3129  if ($format == 3) print '<option value="'.$id.'"';
3130  // Si selected est text, on compare avec code, sinon avec id
3131  if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) print ' selected';
3132  elseif ($selected == $id) print ' selected';
3133  print '>';
3134  if ($format == 0) $value=($maxlength?dol_trunc($arraytypes['label'],$maxlength):$arraytypes['label']);
3135  if ($format == 1) $value=$arraytypes['code'];
3136  if ($format == 2) $value=($maxlength?dol_trunc($arraytypes['label'],$maxlength):$arraytypes['label']);
3137  if ($format == 3) $value=$arraytypes['code'];
3138  print $value?$value:'&nbsp;';
3139  print '</option>';
3140  }
3141  print '</select>';
3142  if ($user->admin && ! $noadmininfo) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
3143  }
3144 
3145 
3153  function selectPriceBaseType($selected='',$htmlname='price_base_type')
3154  {
3155  global $langs;
3156 
3157  $return='';
3158 
3159  $return.= '<select class="flat" name="'.$htmlname.'">';
3160  $options = array(
3161  'HT'=>$langs->trans("HT"),
3162  'TTC'=>$langs->trans("TTC")
3163  );
3164  foreach($options as $id => $value)
3165  {
3166  if ($selected == $id)
3167  {
3168  $return.= '<option value="'.$id.'" selected>'.$value;
3169  }
3170  else
3171  {
3172  $return.= '<option value="'.$id.'">'.$value;
3173  }
3174  $return.= '</option>';
3175  }
3176  $return.= '</select>';
3177 
3178  return $return;
3179  }
3180 
3191  function selectShippingMethod($selected='',$htmlname='shipping_method_id',$filtre='',$useempty=0,$moreattrib='')
3192  {
3193  global $langs, $conf, $user;
3194 
3195  $langs->load("admin");
3196  $langs->load("deliveries");
3197 
3198  $sql = "SELECT rowid, code, libelle as label";
3199  $sql.= " FROM ".MAIN_DB_PREFIX."c_shipment_mode";
3200  $sql.= " WHERE active > 0";
3201  if ($filtre) $sql.=" AND ".$filtre;
3202  $sql.= " ORDER BY libelle ASC";
3203 
3204  dol_syslog(get_class($this)."::selectShippingMode", LOG_DEBUG);
3205  $result = $this->db->query($sql);
3206  if ($result) {
3207  $num = $this->db->num_rows($result);
3208  $i = 0;
3209  if ($num) {
3210  print '<select id="select'.$htmlname.'" class="flat selectshippingmethod" name="'.$htmlname.'"'.($moreattrib?' '.$moreattrib:'').'>';
3211  if ($useempty == 1 || ($useempty == 2 && $num > 1)) {
3212  print '<option value="-1">&nbsp;</option>';
3213  }
3214  while ($i < $num) {
3215  $obj = $this->db->fetch_object($result);
3216  if ($selected == $obj->rowid) {
3217  print '<option value="'.$obj->rowid.'" selected>';
3218  } else {
3219  print '<option value="'.$obj->rowid.'">';
3220  }
3221  print ($langs->trans("SendingMethod".strtoupper($obj->code)) != "SendingMethod".strtoupper($obj->code)) ? $langs->trans("SendingMethod".strtoupper($obj->code)) : $obj->label;
3222  print '</option>';
3223  $i++;
3224  }
3225  print "</select>";
3226  if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
3227  } else {
3228  print $langs->trans("NoShippingMethodDefined");
3229  }
3230  } else {
3231  dol_print_error($this->db);
3232  }
3233  }
3234 
3244  function formSelectShippingMethod($page, $selected='', $htmlname='shipping_method_id', $addempty=0)
3245  {
3246  global $langs, $db;
3247 
3248  $langs->load("deliveries");
3249 
3250  if ($htmlname != "none") {
3251  print '<form method="POST" action="'.$page.'">';
3252  print '<input type="hidden" name="action" value="setshippingmethod">';
3253  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
3254  $this->selectShippingMethod($selected, $htmlname, '', $addempty);
3255  print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
3256  print '</form>';
3257  } else {
3258  if ($selected) {
3259  $code=$langs->getLabelFromKey($db, $selected, 'c_shipment_mode', 'rowid', 'code');
3260  print $langs->trans("SendingMethod".strtoupper($code));
3261  } else {
3262  print "&nbsp;";
3263  }
3264  }
3265  }
3266 
3275  function selectSituationInvoices($selected = '', $socid = 0)
3276  {
3277  global $langs;
3278 
3279  $langs->load('bills');
3280 
3281  $opt = '<option value ="" selected></option>';
3282  $sql = 'SELECT rowid, facnumber, situation_cycle_ref, situation_counter, situation_final, fk_soc FROM ' . MAIN_DB_PREFIX . 'facture WHERE situation_counter>=1';
3283  $sql.= ' ORDER by situation_cycle_ref, situation_counter desc';
3284  $resql = $this->db->query($sql);
3285  if ($resql && $this->db->num_rows($resql) > 0) {
3286  // Last seen cycle
3287  $ref = 0;
3288  while ($res = $this->db->fetch_array($resql, MYSQL_NUM)) {
3289  //Same company ?
3290  if ($socid == $res[5]) {
3291  //Same cycle ?
3292  if ($res[2] != $ref) {
3293  // Just seen this cycle
3294  $ref = $res[2];
3295  //not final ?
3296  if ($res[4] != 1) {
3297  //Not prov?
3298  if (substr($res[1], 1, 4) != 'PROV') {
3299  if ($selected == $res[0]) {
3300  $opt .= '<option value="' . $res[0] . '" selected>' . $res[1] . '</option>';
3301  } else {
3302  $opt .= '<option value="' . $res[0] . '">' . $res[1] . '</option>';
3303  }
3304  }
3305  }
3306  }
3307  }
3308  }
3309  }
3310  else
3311  {
3312  dol_syslog("Error sql=" . $sql . ", error=" . $this->error, LOG_ERR);
3313  }
3314  if ($opt == '<option value ="" selected></option>')
3315  {
3316  $opt = '<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>';
3317  }
3318  return $opt;
3319  }
3320 
3329  function selectUnits($selected = '', $htmlname = 'units', $showempty=0)
3330  {
3331  global $langs;
3332 
3333  $langs->load('products');
3334 
3335  $return= '<select class="flat" id="'.$htmlname.'" name="'.$htmlname.'">';
3336 
3337  $sql = 'SELECT rowid, label, code from '.MAIN_DB_PREFIX.'c_units';
3338  $sql.= ' WHERE active > 0';
3339 
3340  $resql = $this->db->query($sql);
3341  if($resql && $this->db->num_rows($resql) > 0)
3342  {
3343  if ($showempty) $return .= '<option value="none"></option>';
3344 
3345  while($res = $this->db->fetch_object($resql))
3346  {
3347  if ($selected == $res->rowid)
3348  {
3349  $return.='<option value="'.$res->rowid.'" selected>'.($langs->trans('unit'.$res->code)!=$res->label?$langs->trans('unit'.$res->code):$res->label).'</option>';
3350  }
3351  else
3352  {
3353  $return.='<option value="'.$res->rowid.'">'.($langs->trans('unit'.$res->code)!=$res->label?$langs->trans('unit'.$res->code):$res->label).'</option>';
3354  }
3355  }
3356  $return.='</select>';
3357  }
3358  return $return;
3359  }
3360 
3373  function select_comptes($selected='',$htmlname='accountid',$statut=0,$filtre='',$useempty=0,$moreattrib='',$showcurrency=0)
3374  {
3375  global $langs, $conf;
3376 
3377  $langs->load("admin");
3378 
3379  $sql = "SELECT rowid, label, bank, clos as status, currency_code";
3380  $sql.= " FROM ".MAIN_DB_PREFIX."bank_account";
3381  $sql.= " WHERE entity IN (".getEntity('bank_account').")";
3382  if ($statut != 2) $sql.= " AND clos = '".$statut."'";
3383  if ($filtre) $sql.=" AND ".$filtre;
3384  $sql.= " ORDER BY label";
3385 
3386  dol_syslog(get_class($this)."::select_comptes", LOG_DEBUG);
3387  $result = $this->db->query($sql);
3388  if ($result)
3389  {
3390  $num = $this->db->num_rows($result);
3391  $i = 0;
3392  if ($num)
3393  {
3394  print '<select id="select'.$htmlname.'" class="flat selectbankaccount" name="'.$htmlname.'"'.($moreattrib?' '.$moreattrib:'').'>';
3395  if ($useempty == 1 || ($useempty == 2 && $num > 1))
3396  {
3397  print '<option value="-1">&nbsp;</option>';
3398  }
3399 
3400  while ($i < $num)
3401  {
3402  $obj = $this->db->fetch_object($result);
3403  if ($selected == $obj->rowid)
3404  {
3405  print '<option value="'.$obj->rowid.'" selected>';
3406  }
3407  else
3408  {
3409  print '<option value="'.$obj->rowid.'">';
3410  }
3411  print trim($obj->label);
3412  if ($showcurrency) print ' ('.$obj->currency_code.')';
3413  if ($statut == 2 && $obj->status == 1) print ' ('.$langs->trans("Closed").')';
3414  print '</option>';
3415  $i++;
3416  }
3417  print "</select>";
3418  }
3419  else
3420  {
3421  print $langs->trans("NoActiveBankAccountDefined");
3422  }
3423  }
3424  else {
3425  dol_print_error($this->db);
3426  }
3427  }
3428 
3438  function formSelectAccount($page, $selected='', $htmlname='fk_account', $addempty=0)
3439  {
3440  global $langs;
3441  if ($htmlname != "none") {
3442  print '<form method="POST" action="'.$page.'">';
3443  print '<input type="hidden" name="action" value="setbankaccount">';
3444  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
3445  $this->select_comptes($selected, $htmlname, 0, '', $addempty);
3446  print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
3447  print '</form>';
3448  } else {
3449 
3450  $langs->load('banks');
3451 
3452  if ($selected) {
3453  require_once DOL_DOCUMENT_ROOT .'/compta/bank/class/account.class.php';
3454  $bankstatic=new Account($this->db);
3455  $bankstatic->fetch($selected);
3456  print $bankstatic->getNomUrl(1);
3457  } else {
3458  print "&nbsp;";
3459  }
3460  }
3461  }
3462 
3475  function select_all_categories($type, $selected='', $htmlname="parent", $maxlength=64, $excludeafterid=0, $outputmode=0)
3476  {
3477  global $conf, $langs;
3478  $langs->load("categories");
3479 
3480  include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
3481 
3482  // For backward compatibility
3483  if (is_numeric($type))
3484  {
3485  dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING);
3486  }
3487 
3488  if ($type === Categorie::TYPE_BANK_LINE)
3489  {
3490  // TODO Move this into common category feature
3491  $categids=array();
3492  $sql = "SELECT c.label, c.rowid";
3493  $sql.= " FROM ".MAIN_DB_PREFIX."bank_categ as c";
3494  $sql.= " WHERE entity = ".$conf->entity;
3495  $sql.= " ORDER BY c.label";
3496  $result = $this->db->query($sql);
3497  if ($result)
3498  {
3499  $num = $this->db->num_rows($result);
3500  $i = 0;
3501  while ($i < $num)
3502  {
3503  $objp = $this->db->fetch_object($result);
3504  if ($objp) $cate_arbo[$objp->rowid]=array('id'=>$objp->rowid, 'fulllabel'=>$objp->label);
3505  $i++;
3506  }
3507  $this->db->free($result);
3508  }
3509  else dol_print_error($this->db);
3510  }
3511  else
3512  {
3513  $cat = new Categorie($this->db);
3514  $cate_arbo = $cat->get_full_arbo($type, $excludeafterid);
3515  }
3516 
3517  $output = '<select class="flat" name="'.$htmlname.'" id="'.$htmlname.'">';
3518  $outarray=array();
3519  if (is_array($cate_arbo))
3520  {
3521  if (! count($cate_arbo)) $output.= '<option value="-1" disabled>'.$langs->trans("NoCategoriesDefined").'</option>';
3522  else
3523  {
3524  $output.= '<option value="-1">&nbsp;</option>';
3525  foreach($cate_arbo as $key => $value)
3526  {
3527  if ($cate_arbo[$key]['id'] == $selected || ($selected == 'auto' && count($cate_arbo) == 1))
3528  {
3529  $add = 'selected ';
3530  }
3531  else
3532  {
3533  $add = '';
3534  }
3535  $output.= '<option '.$add.'value="'.$cate_arbo[$key]['id'].'">'.dol_trunc($cate_arbo[$key]['fulllabel'],$maxlength,'middle').'</option>';
3536 
3537  $outarray[$cate_arbo[$key]['id']] = $cate_arbo[$key]['fulllabel'];
3538  }
3539  }
3540  }
3541  $output.= '</select>';
3542  $output.= "\n";
3543 
3544  if ($outputmode) return $outarray;
3545  return $output;
3546  }
3547 
3564  function form_confirm($page, $title, $question, $action, $formquestion='', $selectedchoice="", $useajax=0, $height=170, $width=500)
3565  {
3566  print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width);
3567  }
3568 
3593  function formconfirm($page, $title, $question, $action, $formquestion='', $selectedchoice='', $useajax=0, $height=200, $width=500, $disableformtag=0)
3594  {
3595  global $langs,$conf;
3596  global $useglobalvars;
3597 
3598  $more='';
3599  $formconfirm='';
3600  $inputok=array();
3601  $inputko=array();
3602 
3603  // Clean parameters
3604  $newselectedchoice=empty($selectedchoice)?"no":$selectedchoice;
3605  if ($conf->browser->layout == 'phone') $width='95%';
3606 
3607  if (is_array($formquestion) && ! empty($formquestion))
3608  {
3609  // First add hidden fields and value
3610  foreach ($formquestion as $key => $input)
3611  {
3612  if (is_array($input) && ! empty($input))
3613  {
3614  if ($input['type'] == 'hidden')
3615  {
3616  $more.='<input type="hidden" id="'.$input['name'].'" name="'.$input['name'].'" value="'.dol_escape_htmltag($input['value']).'">'."\n";
3617  }
3618  }
3619  }
3620 
3621  // Now add questions
3622  $more.='<table class="paddingtopbottomonly" width="100%">'."\n";
3623  $more.='<tr><td colspan="3">'.(! empty($formquestion['text'])?$formquestion['text']:'').'</td></tr>'."\n";
3624  foreach ($formquestion as $key => $input)
3625  {
3626  if (is_array($input) && ! empty($input))
3627  {
3628  $size=(! empty($input['size'])?' size="'.$input['size'].'"':'');
3629  $moreattr=(! empty($input['moreattr'])?' '.$input['moreattr']:'');
3630  $morecss=(! empty($input['morecss'])?' '.$input['morecss']:'');
3631 
3632  if ($input['type'] == 'text')
3633  {
3634  $more.='<tr><td>'.$input['label'].'</td><td colspan="2" align="left"><input type="text" class="flat'.$morecss.'" id="'.$input['name'].'" name="'.$input['name'].'"'.$size.' value="'.$input['value'].'"'.$moreattr.' /></td></tr>'."\n";
3635  }
3636  else if ($input['type'] == 'password')
3637  {
3638  $more.='<tr><td>'.$input['label'].'</td><td colspan="2" align="left"><input type="password" class="flat'.$morecss.'" id="'.$input['name'].'" name="'.$input['name'].'"'.$size.' value="'.$input['value'].'"'.$moreattr.' /></td></tr>'."\n";
3639  }
3640  else if ($input['type'] == 'select')
3641  {
3642  $more.='<tr><td>';
3643  if (! empty($input['label'])) $more.=$input['label'].'</td><td valign="top" colspan="2" align="left">';
3644  $more.=$this->selectarray($input['name'],$input['values'],$input['default'],1,0,0,$moreattr,0,0,0,'',$morecss);
3645  $more.='</td></tr>'."\n";
3646  }
3647  else if ($input['type'] == 'checkbox')
3648  {
3649  $more.='<tr>';
3650  $more.='<td>'.$input['label'].' </td><td align="left">';
3651  $more.='<input type="checkbox" class="flat'.$morecss.'" id="'.$input['name'].'" name="'.$input['name'].'"'.$moreattr;
3652  if (! is_bool($input['value']) && $input['value'] != 'false') $more.=' checked';
3653  if (is_bool($input['value']) && $input['value']) $more.=' checked';
3654  if (isset($input['disabled'])) $more.=' disabled';
3655  $more.=' /></td>';
3656  $more.='<td align="left">&nbsp;</td>';
3657  $more.='</tr>'."\n";
3658  }
3659  else if ($input['type'] == 'radio')
3660  {
3661  $i=0;
3662  foreach($input['values'] as $selkey => $selval)
3663  {
3664  $more.='<tr>';
3665  if ($i==0) $more.='<td class="tdtop">'.$input['label'].'</td>';
3666  else $more.='<td>&nbsp;</td>';
3667  $more.='<td width="20"><input type="radio" class="flat'.$morecss.'" id="'.$input['name'].'" name="'.$input['name'].'" value="'.$selkey.'"'.$moreattr;
3668  if ($input['disabled']) $more.=' disabled';
3669  $more.=' /></td>';
3670  $more.='<td align="left">';
3671  $more.=$selval;
3672  $more.='</td></tr>'."\n";
3673  $i++;
3674  }
3675  }
3676  else if ($input['type'] == 'date')
3677  {
3678  $more.='<tr><td>'.$input['label'].'</td>';
3679  $more.='<td colspan="2" align="left">';
3680  $more.=$this->select_date($input['value'],$input['name'],0,0,0,'',1,0,1);
3681  $more.='</td></tr>'."\n";
3682  $formquestion[] = array('name'=>$input['name'].'day');
3683  $formquestion[] = array('name'=>$input['name'].'month');
3684  $formquestion[] = array('name'=>$input['name'].'year');
3685  $formquestion[] = array('name'=>$input['name'].'hour');
3686  $formquestion[] = array('name'=>$input['name'].'min');
3687  }
3688  else if ($input['type'] == 'other')
3689  {
3690  $more.='<tr><td>';
3691  if (! empty($input['label'])) $more.=$input['label'].'</td><td colspan="2" align="left">';
3692  $more.=$input['value'];
3693  $more.='</td></tr>'."\n";
3694  }
3695 
3696  else if ($input['type'] == 'onecolumn')
3697  {
3698  $more.='<tr><td colspan="3" align="left">';
3699  $more.=$input['value'];
3700  $more.='</td></tr>'."\n";
3701  }
3702  }
3703  }
3704  $more.='</table>'."\n";
3705  }
3706 
3707  // JQUI method dialog is broken with jmobile, we use standard HTML.
3708  // 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
3709  // See page product/card.php for example
3710  if (! empty($conf->dol_use_jmobile)) $useajax=0;
3711  if (empty($conf->use_javascript_ajax)) $useajax=0;
3712 
3713  if ($useajax)
3714  {
3715  $autoOpen=true;
3716  $dialogconfirm='dialog-confirm';
3717  $button='';
3718  if (! is_numeric($useajax))
3719  {
3720  $button=$useajax;
3721  $useajax=1;
3722  $autoOpen=false;
3723  $dialogconfirm.='-'.$button;
3724  }
3725  $pageyes=$page.(preg_match('/\?/',$page)?'&':'?').'action='.$action.'&confirm=yes';
3726  $pageno=($useajax == 2 ? $page.(preg_match('/\?/',$page)?'&':'?').'confirm=no':'');
3727  // Add input fields into list of fields to read during submit (inputok and inputko)
3728  if (is_array($formquestion))
3729  {
3730  foreach ($formquestion as $key => $input)
3731  {
3732  //print "xx ".$key." rr ".is_array($input)."<br>\n";
3733  if (is_array($input) && isset($input['name'])) array_push($inputok,$input['name']);
3734  if (isset($input['inputko']) && $input['inputko'] == 1) array_push($inputko,$input['name']);
3735  }
3736  }
3737  // Show JQuery confirm box. Note that global var $useglobalvars is used inside this template
3738  $formconfirm.= '<div id="'.$dialogconfirm.'" title="'.dol_escape_htmltag($title).'" style="display: none;">';
3739  if (! empty($more)) {
3740  $formconfirm.= '<div class="confirmquestions">'.$more.'</div>';
3741  }
3742  $formconfirm.= ($question ? '<div class="confirmmessage">'.img_help('','').' '.$question . '</div>': '');
3743  $formconfirm.= '</div>'."\n";
3744 
3745  $formconfirm.= "\n<!-- begin ajax form_confirm page=".$page." -->\n";
3746  $formconfirm.= '<script type="text/javascript">'."\n";
3747  $formconfirm.= 'jQuery(document).ready(function() {
3748  $(function() {
3749  $( "#'.$dialogconfirm.'" ).dialog(
3750  {
3751  autoOpen: '.($autoOpen ? "true" : "false").',';
3752  if ($newselectedchoice == 'no')
3753  {
3754  $formconfirm.='
3755  open: function() {
3756  $(this).parent().find("button.ui-button:eq(2)").focus();
3757  },';
3758  }
3759  $formconfirm.='
3760  resizable: false,
3761  height: "'.$height.'",
3762  width: "'.$width.'",
3763  modal: true,
3764  closeOnEscape: false,
3765  buttons: {
3766  "'.dol_escape_js($langs->transnoentities("Yes")).'": function() {
3767  var options="";
3768  var inputok = '.json_encode($inputok).';
3769  var pageyes = "'.dol_escape_js(! empty($pageyes)?$pageyes:'').'";
3770  if (inputok.length>0) {
3771  $.each(inputok, function(i, inputname) {
3772  var more = "";
3773  if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
3774  if ($("#" + inputname).attr("type") == "radio") { more = ":checked"; }
3775  var inputvalue = $("#" + inputname + more).val();
3776  if (typeof inputvalue == "undefined") { inputvalue=""; }
3777  options += "&" + inputname + "=" + inputvalue;
3778  });
3779  }
3780  var urljump = pageyes + (pageyes.indexOf("?") < 0 ? "?" : "") + options;
3781  //alert(urljump);
3782  if (pageyes.length > 0) { location.href = urljump; }
3783  $(this).dialog("close");
3784  },
3785  "'.dol_escape_js($langs->transnoentities("No")).'": function() {
3786  var options = "";
3787  var inputko = '.json_encode($inputko).';
3788  var pageno="'.dol_escape_js(! empty($pageno)?$pageno:'').'";
3789  if (inputko.length>0) {
3790  $.each(inputko, function(i, inputname) {
3791  var more = "";
3792  if ($("#" + inputname).attr("type") == "checkbox") { more = ":checked"; }
3793  var inputvalue = $("#" + inputname + more).val();
3794  if (typeof inputvalue == "undefined") { inputvalue=""; }
3795  options += "&" + inputname + "=" + inputvalue;
3796  });
3797  }
3798  var urljump=pageno + (pageno.indexOf("?") < 0 ? "?" : "") + options;
3799  //alert(urljump);
3800  if (pageno.length > 0) { location.href = urljump; }
3801  $(this).dialog("close");
3802  }
3803  }
3804  }
3805  );
3806 
3807  var button = "'.$button.'";
3808  if (button.length > 0) {
3809  $( "#" + button ).click(function() {
3810  $("#'.$dialogconfirm.'").dialog("open");
3811  });
3812  }
3813  });
3814  });
3815  </script>';
3816  $formconfirm.= "<!-- end ajax form_confirm -->\n";
3817  }
3818  else
3819  {
3820  $formconfirm.= "\n<!-- begin form_confirm page=".$page." -->\n";
3821 
3822  if (empty($disableformtag)) $formconfirm.= '<form method="POST" action="'.$page.'" class="notoptoleftroright">'."\n";
3823 
3824  $formconfirm.= '<input type="hidden" name="action" value="'.$action.'">'."\n";
3825  if (empty($disableformtag)) $formconfirm.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'."\n";
3826 
3827  $formconfirm.= '<table width="100%" class="valid">'."\n";
3828 
3829  // Line title
3830  $formconfirm.= '<tr class="validtitre"><td class="validtitre" colspan="3">'.img_picto('','recent').' '.$title.'</td></tr>'."\n";
3831 
3832  // Line form fields
3833  if ($more)
3834  {
3835  $formconfirm.='<tr class="valid"><td class="valid" colspan="3">'."\n";
3836  $formconfirm.=$more;
3837  $formconfirm.='</td></tr>'."\n";
3838  }
3839 
3840  // Line with question
3841  $formconfirm.= '<tr class="valid">';
3842  $formconfirm.= '<td class="valid">'.$question.'</td>';
3843  $formconfirm.= '<td class="valid">';
3844  $formconfirm.= $this->selectyesno("confirm",$newselectedchoice);
3845  $formconfirm.= '</td>';
3846  $formconfirm.= '<td class="valid" align="center"><input class="button valignmiddle" type="submit" value="'.$langs->trans("Validate").'"></td>';
3847  $formconfirm.= '</tr>'."\n";
3848 
3849  $formconfirm.= '</table>'."\n";
3850 
3851  if (empty($disableformtag)) $formconfirm.= "</form>\n";
3852  $formconfirm.= '<br>';
3853 
3854  $formconfirm.= "<!-- end form_confirm -->\n";
3855  }
3856 
3857  return $formconfirm;
3858  }
3859 
3860 
3874  function form_project($page, $socid, $selected='', $htmlname='projectid', $discard_closed=0, $maxlength=20, $forcefocus=0, $nooutput=0)
3875  {
3876  global $langs;
3877 
3878  require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
3879  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
3880 
3881  $out='';
3882 
3883  $formproject=new FormProjets($this->db);
3884 
3885  $langs->load("project");
3886  if ($htmlname != "none")
3887  {
3888  $out.="\n";
3889  $out.='<form method="post" action="'.$page.'">';
3890  $out.='<input type="hidden" name="action" value="classin">';
3891  $out.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
3892  $out.=$formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1);
3893  $out.='<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
3894  $out.='</form>';
3895  }
3896  else
3897  {
3898  if ($selected)
3899  {
3900  $projet = new Project($this->db);
3901  $projet->fetch($selected);
3902  //print '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$selected.'">'.$projet->title.'</a>';
3903  $out.=$projet->getNomUrl(0,'',1);
3904  }
3905  else
3906  {
3907  $out.="&nbsp;";
3908  }
3909  }
3910 
3911  if (empty($nooutput))
3912  {
3913  print $out;
3914  return '';
3915  }
3916  return $out;
3917  }
3918 
3928  function form_conditions_reglement($page, $selected='', $htmlname='cond_reglement_id', $addempty=0)
3929  {
3930  global $langs;
3931  if ($htmlname != "none")
3932  {
3933  print '<form method="post" action="'.$page.'">';
3934  print '<input type="hidden" name="action" value="setconditions">';
3935  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
3936  $this->select_conditions_paiements($selected,$htmlname,-1,$addempty);
3937  print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
3938  print '</form>';
3939  }
3940  else
3941  {
3942  if ($selected)
3943  {
3945  print $this->cache_conditions_paiements[$selected]['label'];
3946  } else {
3947  print "&nbsp;";
3948  }
3949  }
3950  }
3951 
3961  function form_availability($page, $selected='', $htmlname='availability', $addempty=0)
3962  {
3963  global $langs;
3964  if ($htmlname != "none")
3965  {
3966  print '<form method="post" action="'.$page.'">';
3967  print '<input type="hidden" name="action" value="setavailability">';
3968  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
3969  $this->selectAvailabilityDelay($selected,$htmlname,-1,$addempty);
3970  print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
3971  print '</form>';
3972  }
3973  else
3974  {
3975  if ($selected)
3976  {
3977  $this->load_cache_availability();
3978  print $this->cache_availability[$selected]['label'];
3979  } else {
3980  print "&nbsp;";
3981  }
3982  }
3983  }
3984 
3995  function formInputReason($page, $selected='', $htmlname='demandreason', $addempty=0)
3996  {
3997  global $langs;
3998  if ($htmlname != "none")
3999  {
4000  print '<form method="post" action="'.$page.'">';
4001  print '<input type="hidden" name="action" value="setdemandreason">';
4002  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4003  $this->selectInputReason($selected,$htmlname,-1,$addempty);
4004  print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
4005  print '</form>';
4006  }
4007  else
4008  {
4009  if ($selected)
4010  {
4011  $this->loadCacheInputReason();
4012  foreach ($this->cache_demand_reason as $key => $val)
4013  {
4014  if ($val['id'] == $selected)
4015  {
4016  print $val['label'];
4017  break;
4018  }
4019  }
4020  } else {
4021  print "&nbsp;";
4022  }
4023  }
4024  }
4025 
4038  function form_date($page, $selected, $htmlname, $displayhour=0, $displaymin=0, $nooutput=0)
4039  {
4040  global $langs;
4041 
4042  $ret='';
4043 
4044  if ($htmlname != "none")
4045  {
4046  $ret.='<form method="post" action="'.$page.'" name="form'.$htmlname.'">';
4047  $ret.='<input type="hidden" name="action" value="set'.$htmlname.'">';
4048  $ret.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4049  $ret.='<table class="nobordernopadding" cellpadding="0" cellspacing="0">';
4050  $ret.='<tr><td>';
4051  $ret.=$this->select_date($selected,$htmlname,$displayhour,$displaymin,1,'form'.$htmlname,1,0,1);
4052  $ret.='</td>';
4053  $ret.='<td align="left"><input type="submit" class="button" value="'.$langs->trans("Modify").'"></td>';
4054  $ret.='</tr></table></form>';
4055  }
4056  else
4057  {
4058  if ($displayhour) $ret.=dol_print_date($selected,'dayhour');
4059  else $ret.=dol_print_date($selected,'day');
4060  }
4061 
4062  if (empty($nooutput)) print $ret;
4063  return $ret;
4064  }
4065 
4066 
4077  function form_users($page, $selected='', $htmlname='userid', $exclude='', $include='')
4078  {
4079  global $langs;
4080 
4081  if ($htmlname != "none")
4082  {
4083  print '<form method="POST" action="'.$page.'" name="form'.$htmlname.'">';
4084  print '<input type="hidden" name="action" value="set'.$htmlname.'">';
4085  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4086  print $this->select_dolusers($selected,$htmlname,1,$exclude,0,$include);
4087  print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4088  print '</form>';
4089  }
4090  else
4091  {
4092  if ($selected)
4093  {
4094  require_once DOL_DOCUMENT_ROOT .'/user/class/user.class.php';
4095  $theuser=new User($this->db);
4096  $theuser->fetch($selected);
4097  print $theuser->getNomUrl(1);
4098  } else {
4099  print "&nbsp;";
4100  }
4101  }
4102  }
4103 
4104 
4115  function form_modes_reglement($page, $selected='', $htmlname='mode_reglement_id', $filtertype='', $active=1)
4116  {
4117  global $langs;
4118  if ($htmlname != "none")
4119  {
4120  print '<form method="POST" action="'.$page.'">';
4121  print '<input type="hidden" name="action" value="setmode">';
4122  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4123  $this->select_types_paiements($selected,$htmlname,$filtertype,0,0,0,0,$active);
4124  print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4125  print '</form>';
4126  }
4127  else
4128  {
4129  if ($selected)
4130  {
4131  $this->load_cache_types_paiements();
4132  print $this->cache_types_paiements[$selected]['label'];
4133  } else {
4134  print "&nbsp;";
4135  }
4136  }
4137  }
4138 
4147  function form_multicurrency_code($page, $selected='', $htmlname='multicurrency_code')
4148  {
4149  global $langs;
4150  if ($htmlname != "none")
4151  {
4152  print '<form method="POST" action="'.$page.'">';
4153  print '<input type="hidden" name="action" value="setmulticurrencycode">';
4154  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4155  print $this->selectMultiCurrency($selected, $htmlname, 0);
4156  print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4157  print '</form>';
4158  }
4159  else
4160  {
4161  dol_include_once('/core/lib/company.lib.php');
4162  print !empty($selected) ? currency_name($selected,1) : '&nbsp;';
4163  }
4164  }
4165 
4175  function form_multicurrency_rate($page, $rate='', $htmlname='multicurrency_tx', $currency='')
4176  {
4177  global $langs, $mysoc, $conf;
4178 
4179  if ($htmlname != "none")
4180  {
4181  print '<form method="POST" action="'.$page.'">';
4182  print '<input type="hidden" name="action" value="setmulticurrencyrate">';
4183  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4184  print '<input type="text" name="'.$htmlname.'" value="'.(!empty($rate) ? price($rate) : 1).'" size="10" /> ';
4185  print '<select name="calculation_mode">';
4186  print '<option value="1">'.$currency.' > '.$conf->currency.'</option>';
4187  print '<option value="2">'.$conf->currency.' > '.$currency.'</option>';
4188  print '</select> ';
4189  print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4190  print '</form>';
4191  }
4192  else
4193  {
4194  if (! empty($rate))
4195  {
4196  print price($rate, 1, $langs, 1, 0);
4197  if ($currency && $rate != 1) print ' &nbsp; ('.price($rate, 1, $langs, 1, 0).' '.$currency.' = 1 '.$conf->currency.')';
4198  }
4199  else
4200  {
4201  print 1;
4202  }
4203  }
4204  }
4205 
4206 
4221  function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter='', $maxvalue=0, $more='', $hidelist=0)
4222  {
4223  global $conf,$langs;
4224  if ($htmlname != "none")
4225  {
4226  print '<form method="post" action="'.$page.'">';
4227  print '<input type="hidden" name="action" value="setabsolutediscount">';
4228  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4229  print '<div class="inline-block">';
4230  if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS))
4231  {
4232  if (! $filter || $filter=="fk_facture_source IS NULL") print $langs->trans("CompanyHasAbsoluteDiscount",price($amount,0,$langs,0,0,-1,$conf->currency)); // If we want deposit to be substracted to payments only and not to total of final invoice
4233  else print $langs->trans("CompanyHasCreditNote",price($amount,0,$langs,0,0,-1,$conf->currency));
4234  }
4235  else
4236  {
4237  if (! $filter || $filter=="fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND (description LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%'))") print $langs->trans("CompanyHasAbsoluteDiscount",price($amount,0,$langs,0,0,-1,$conf->currency));
4238  else print $langs->trans("CompanyHasCreditNote",price($amount,0,$langs,0,0,-1,$conf->currency));
4239  }
4240  if (empty($hidelist)) print ': ';
4241  print '</div>';
4242  if (empty($hidelist))
4243  {
4244  print '<div class="inline-block" style="padding-right: 10px">';
4245  $newfilter='fk_facture IS NULL AND fk_facture_line IS NULL'; // Remises disponibles
4246  if ($filter) $newfilter.=' AND ('.$filter.')';
4247  $nbqualifiedlines=$this->select_remises($selected,$htmlname,$newfilter,$socid,$maxvalue);
4248  if ($nbqualifiedlines > 0)
4249  {
4250  print ' &nbsp; <input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("UseLine")).'"';
4251  if ($filter && $filter != "fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description LIKE '(DEPOSIT)%')") print ' title="'.$langs->trans("UseCreditNoteInInvoicePayment").'"';
4252  print '>';
4253  }
4254  print '</div>';
4255  }
4256  if ($more)
4257  {
4258  print '<div class="inline-block">';
4259  print $more;
4260  print '</div>';
4261  }
4262  print '</form>';
4263  }
4264  else
4265  {
4266  if ($selected)
4267  {
4268  print $selected;
4269  }
4270  else
4271  {
4272  print "0";
4273  }
4274  }
4275  }
4276 
4277 
4287  function form_contacts($page, $societe, $selected='', $htmlname='contactid')
4288  {
4289  global $langs, $conf;
4290 
4291  if ($htmlname != "none")
4292  {
4293  print '<form method="post" action="'.$page.'">';
4294  print '<input type="hidden" name="action" value="set_contact">';
4295  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4296  print '<table class="nobordernopadding" cellpadding="0" cellspacing="0">';
4297  print '<tr><td>';
4298  $num=$this->select_contacts($societe->id, $selected, $htmlname);
4299  if ($num==0)
4300  {
4301  $addcontact = (! empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("AddContact") : $langs->trans("AddContactAddress"));
4302  print '<a href="'.DOL_URL_ROOT.'/contact/card.php?socid='.$societe->id.'&amp;action=create&amp;backtoreferer=1">'.$addcontact.'</a>';
4303  }
4304  print '</td>';
4305  print '<td align="left"><input type="submit" class="button" value="'.$langs->trans("Modify").'"></td>';
4306  print '</tr></table></form>';
4307  }
4308  else
4309  {
4310  if ($selected)
4311  {
4312  require_once DOL_DOCUMENT_ROOT .'/contact/class/contact.class.php';
4313  $contact=new Contact($this->db);
4314  $contact->fetch($selected);
4315  print $contact->getFullName($langs);
4316  } else {
4317  print "&nbsp;";
4318  }
4319  }
4320  }
4321 
4335  function form_thirdparty($page, $selected='', $htmlname='socid', $filter='',$showempty=0, $showtype=0, $forcecombo=0, $events=array())
4336  {
4337  global $langs;
4338 
4339  if ($htmlname != "none")
4340  {
4341  print '<form method="post" action="'.$page.'">';
4342  print '<input type="hidden" name="action" value="set_thirdparty">';
4343  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
4344  print $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events);
4345  print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4346  print '</form>';
4347  }
4348  else
4349  {
4350  if ($selected)
4351  {
4352  require_once DOL_DOCUMENT_ROOT .'/societe/class/societe.class.php';
4353  $soc = new Societe($this->db);
4354  $soc->fetch($selected);
4355  print $soc->getNomUrl($langs);
4356  }
4357  else
4358  {
4359  print "&nbsp;";
4360  }
4361  }
4362  }
4363 
4371  function select_currency($selected='',$htmlname='currency_id')
4372  {
4373  print $this->selectCurrency($selected,$htmlname);
4374  }
4375 
4383  function selectCurrency($selected='',$htmlname='currency_id')
4384  {
4385  global $conf,$langs,$user;
4386 
4387  $langs->loadCacheCurrencies('');
4388 
4389  $out='';
4390 
4391  if ($selected=='euro' || $selected=='euros') $selected='EUR'; // Pour compatibilite
4392 
4393  $out.= '<select class="flat maxwidth200onsmartphone minwidth300" name="'.$htmlname.'" id="'.$htmlname.'">';
4394  foreach ($langs->cache_currencies as $code_iso => $currency)
4395  {
4396  if ($selected && $selected == $code_iso)
4397  {
4398  $out.= '<option value="'.$code_iso.'" selected>';
4399  }
4400  else
4401  {
4402  $out.= '<option value="'.$code_iso.'">';
4403  }
4404  $out.= $currency['label'];
4405  $out.= ' ('.$langs->getCurrencySymbol($code_iso).')';
4406  $out.= '</option>';
4407  }
4408  $out.= '</select>';
4409  if ($user->admin) $out.= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
4410 
4411  // Make select dynamic
4412  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
4413  $out .= ajax_combobox($htmlname);
4414 
4415  return $out;
4416  }
4417 
4426  function selectMultiCurrency($selected='', $htmlname='multicurrency_code', $useempty=0)
4427  {
4428  global $db,$conf,$langs,$user;
4429 
4430  $langs->loadCacheCurrencies(''); // Load ->cache_currencies
4431 
4432  $TCurrency = array();
4433 
4434  $sql = 'SELECT code FROM '.MAIN_DB_PREFIX.'multicurrency';
4435  $sql.= " WHERE entity IN ('".getEntity('mutlicurrency')."')";
4436  $resql = $db->query($sql);
4437  if ($resql)
4438  {
4439  while ($obj = $db->fetch_object($resql)) $TCurrency[$obj->code] = $obj->code;
4440  }
4441 
4442  $out='';
4443  $out.= '<select class="flat" name="'.$htmlname.'" id="'.$htmlname.'">';
4444  if ($useempty) $out .= '<option value=""></option>';
4445  // If company current currency not in table, we add it into list. Should always be available.
4446  if (! in_array($conf->currency, $TCurrency))
4447  {
4448  $TCurrency[$conf->currency] = $conf->currency;
4449  }
4450  if (count($TCurrency) > 0)
4451  {
4452  foreach ($langs->cache_currencies as $code_iso => $currency)
4453  {
4454  if (isset($TCurrency[$code_iso]))
4455  {
4456  if (!empty($selected) && $selected == $code_iso) $out.= '<option value="'.$code_iso.'" selected="selected">';
4457  else $out.= '<option value="'.$code_iso.'">';
4458 
4459  $out.= $currency['label'];
4460  $out.= ' ('.$langs->getCurrencySymbol($code_iso).')';
4461  $out.= '</option>';
4462  }
4463  }
4464 
4465  }
4466 
4467  $out.= '</select>';
4468  // Make select dynamic
4469  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
4470  $out.= ajax_combobox($htmlname);
4471 
4472  return $out;
4473  }
4474 
4481  function load_cache_vatrates($country_code)
4482  {
4483  global $langs;
4484 
4485  $num = count($this->cache_vatrates);
4486  if ($num > 0) return $num; // Cache already loaded
4487 
4488  dol_syslog(__METHOD__, LOG_DEBUG);
4489 
4490  $sql = "SELECT DISTINCT t.rowid, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
4491  $sql.= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
4492  $sql.= " WHERE t.fk_pays = c.rowid";
4493  $sql.= " AND t.active > 0";
4494  $sql.= " AND c.code IN (".$country_code.")";
4495  $sql.= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC";
4496 
4497  $resql=$this->db->query($sql);
4498  if ($resql)
4499  {
4500  $num = $this->db->num_rows($resql);
4501  if ($num)
4502  {
4503  for ($i = 0; $i < $num; $i++)
4504  {
4505  $obj = $this->db->fetch_object($resql);
4506  $this->cache_vatrates[$i]['rowid'] = $obj->rowid;
4507  $this->cache_vatrates[$i]['code'] = $obj->code;
4508  $this->cache_vatrates[$i]['txtva'] = $obj->taux;
4509  $this->cache_vatrates[$i]['nprtva'] = $obj->recuperableonly;
4510  $this->cache_vatrates[$i]['localtax1'] = $obj->localtax1;
4511  $this->cache_vatrates[$i]['localtax1_type'] = $obj->localtax1_type;
4512  $this->cache_vatrates[$i]['localtax2'] = $obj->localtax2;
4513  $this->cache_vatrates[$i]['localtax2_type'] = $obj->localtax1_type;
4514 
4515  $this->cache_vatrates[$i]['label'] = $obj->taux.'%'.($obj->code?' ('.$obj->code.')':''); // Label must contains only 0-9 , . % or *
4516  $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
4517  $positiverates='';
4518  if ($obj->taux) $positiverates.=($positiverates?'/':'').$obj->taux;
4519  if ($obj->localtax1) $positiverates.=($positiverates?'/':'').$obj->localtax1;
4520  if ($obj->localtax2) $positiverates.=($positiverates?'/':'').$obj->localtax2;
4521  if (empty($positiverates)) $positiverates='0';
4522  $this->cache_vatrates[$i]['labelpositiverates'] = $positiverates.($obj->code?' ('.$obj->code.')':''); // Must never be used as key, only label
4523  }
4524 
4525  return $num;
4526  }
4527  else
4528  {
4529  $this->error = '<font class="error">'.$langs->trans("ErrorNoVATRateDefinedForSellerCountry",$country_code).'</font>';
4530  return -1;
4531  }
4532  }
4533  else
4534  {
4535  $this->error = '<font class="error">'.$this->db->error().'</font>';
4536  return -2;
4537  }
4538  }
4539 
4561  function load_tva($htmlname='tauxtva', $selectedrate='', $societe_vendeuse='', $societe_acheteuse='', $idprod=0, $info_bits=0, $type='', $options_only=false, $mode=0)
4562  {
4563  global $langs,$conf,$mysoc;
4564 
4565  $langs->load('errors');
4566 
4567  $return='';
4568 
4569  // Define defaultnpr, defaultttx and defaultcode
4570  $defaultnpr=($info_bits & 0x01);
4571  $defaultnpr=(preg_match('/\*/',$selectedrate) ? 1 : $defaultnpr);
4572  $defaulttx=str_replace('*','',$selectedrate);
4573  $defaultcode='';
4574  if (preg_match('/\((.*)\)/', $defaulttx, $reg))
4575  {
4576  $defaultcode=$reg[1];
4577  $defaulttx=preg_replace('/\s*\(.*\)/','',$defaulttx);
4578  }
4579  //var_dump($selectedrate.'-'.$defaulttx.'-'.$defaultnpr.'-'.$defaultcode);
4580 
4581  // Check parameters
4582  if (is_object($societe_vendeuse) && ! $societe_vendeuse->country_code)
4583  {
4584  if ($societe_vendeuse->id == $mysoc->id)
4585  {
4586  $return.= '<font class="error">'.$langs->trans("ErrorYourCountryIsNotDefined").'</div>';
4587  }
4588  else
4589  {
4590  $return.= '<font class="error">'.$langs->trans("ErrorSupplierCountryIsNotDefined").'</div>';
4591  }
4592  return $return;
4593  }
4594 
4595  //var_dump($societe_acheteuse);
4596  //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";
4597  //exit;
4598 
4599  // Define list of countries to use to search VAT rates to show
4600  // First we defined code_country to use to find list
4601  if (is_object($societe_vendeuse))
4602  {
4603  $code_country="'".$societe_vendeuse->country_code."'";
4604  }
4605  else
4606  {
4607  $code_country="'".$mysoc->country_code."'"; // Pour compatibilite ascendente
4608  }
4609  if (! empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC)) // If option to have vat for end customer for services is on
4610  {
4611  require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
4612  if (! isInEEC($societe_vendeuse) && (! is_object($societe_acheteuse) || (isInEEC($societe_acheteuse) && ! $societe_acheteuse->isACompany())))
4613  {
4614  // We also add the buyer
4615  if (is_numeric($type))
4616  {
4617  if ($type == 1) // We know product is a service
4618  {
4619  $code_country.=",'".$societe_acheteuse->country_code."'";
4620  }
4621  }
4622  else if (! $idprod) // We don't know type of product
4623  {
4624  $code_country.=",'".$societe_acheteuse->country_code."'";
4625  }
4626  else
4627  {
4628  $prodstatic=new Product($this->db);
4629  $prodstatic->fetch($idprod);
4630  if ($prodstatic->type == Product::TYPE_SERVICE) // We know product is a service
4631  {
4632  $code_country.=",'".$societe_acheteuse->country_code."'";
4633  }
4634  }
4635  }
4636  }
4637 
4638  // Now we get list
4639  $num = $this->load_cache_vatrates($code_country); // If no vat defined, return -1 with message into this->error
4640 
4641  if ($num > 0)
4642  {
4643  // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '')
4644  if ($defaulttx < 0 || dol_strlen($defaulttx) == 0)
4645  {
4646  $tmpthirdparty=new Societe($this->db);
4647  $defaulttx=get_default_tva($societe_vendeuse, (is_object($societe_acheteuse)?$societe_acheteuse:$tmpthirdparty), $idprod);
4648  $defaultnpr=get_default_npr($societe_vendeuse, (is_object($societe_acheteuse)?$societe_acheteuse:$tmpthirdparty), $idprod);
4649  if (empty($defaulttx)) $defaultnpr=0;
4650  }
4651 
4652  // Si taux par defaut n'a pu etre determine, on prend dernier de la liste.
4653  // Comme ils sont tries par ordre croissant, dernier = plus eleve = taux courant
4654  if ($defaulttx < 0 || dol_strlen($defaulttx) == 0)
4655  {
4656  if (empty($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS)) $defaulttx = $this->cache_vatrates[$num-1]['txtva'];
4657  else $defaulttx=($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS == 'none' ? '' : $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS);
4658  }
4659 
4660  // Disabled if seller is not subject to VAT
4661  $disabled=false; $title='';
4662  if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0")
4663  {
4664  $title=' title="'.$langs->trans('VATIsNotUsed').'"';
4665  $disabled=true;
4666  }
4667 
4668  if (! $options_only) $return.= '<select class="flat minwidth75imp" id="'.$htmlname.'" name="'.$htmlname.'"'.($disabled?' disabled':'').$title.'>';
4669 
4670  $selectedfound=false;
4671  foreach ($this->cache_vatrates as $rate)
4672  {
4673  // Keep only 0 if seller is not subject to VAT
4674  if ($disabled && $rate['txtva'] != 0) continue;
4675 
4676  // Define key to use into select list
4677  $key = $rate['txtva'];
4678  $key.= $rate['nprtva'] ? '*': '';
4679  if ($mode > 0 && $rate['code']) $key.=' ('.$rate['code'].')';
4680  if ($mode < 0) $key = $rate['rowid'];
4681 
4682  $return.= '<option value="'.$key.'"';
4683  if (! $selectedfound)
4684  {
4685  if ($defaultcode) // If defaultcode is defined, we used it in priority to select combo option instead of using rate+npr flag
4686  {
4687  if ($defaultcode == $rate['code'])
4688  {
4689  $return.= ' selected';
4690  $selectedfound=true;
4691  }
4692  }
4693  elseif ($rate['txtva'] == $defaulttx && $rate['nprtva'] == $defaultnpr)
4694  {
4695  $return.= ' selected';
4696  $selectedfound=true;
4697  }
4698  }
4699  $return.= '>';
4700  //if (! empty($conf->global->MAIN_VAT_SHOW_POSITIVE_RATES))
4701  if ($mysoc->country_code == 'IN' || ! empty($conf->global->MAIN_VAT_LABEL_IS_POSITIVE_RATES))
4702  {
4703  $return.= $rate['labelpositiverates'];
4704  }
4705  else
4706  {
4707  $return.= vatrate($rate['label']);
4708  }
4709  //$return.=($rate['code']?' '.$rate['code']:'');
4710  $return.= (empty($rate['code']) && $rate['nprtva']) ? ' *': ''; // We show the * (old behaviour only if new vat code is not used)
4711 
4712  $return.= '</option>';
4713  }
4714 
4715  if (! $options_only) $return.= '</select>';
4716  }
4717  else
4718  {
4719  $return.= $this->error;
4720  }
4721 
4722  $this->num = $num;
4723  return $return;
4724  }
4725 
4726 
4750  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='')
4751  {
4752  global $conf,$langs;
4753 
4754  $retstring='';
4755 
4756  if($prefix=='') $prefix='re';
4757  if($h == '') $h=0;
4758  if($m == '') $m=0;
4759  $emptydate=0;
4760  $emptyhours=0;
4761  if ($empty == 1) { $emptydate=1; $emptyhours=1; }
4762  if ($empty == 2) { $emptydate=0; $emptyhours=1; }
4763  $orig_set_time=$set_time;
4764 
4765  if ($set_time === '' && $emptydate == 0)
4766  {
4767  include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
4768  $set_time = dol_now('tzuser')-(getServerTimeZoneInt('now')*3600); // set_time must be relative to PHP server timezone
4769  }
4770 
4771  // Analysis of the pre-selection date
4772  if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/',$set_time,$reg))
4773  {
4774  // Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'
4775  $syear = (! empty($reg[1])?$reg[1]:'');
4776  $smonth = (! empty($reg[2])?$reg[2]:'');
4777  $sday = (! empty($reg[3])?$reg[3]:'');
4778  $shour = (! empty($reg[4])?$reg[4]:'');
4779  $smin = (! empty($reg[5])?$reg[5]:'');
4780  }
4781  elseif (strval($set_time) != '' && $set_time != -1)
4782  {
4783  // set_time est un timestamps (0 possible)
4784  $syear = dol_print_date($set_time, "%Y");
4785  $smonth = dol_print_date($set_time, "%m");
4786  $sday = dol_print_date($set_time, "%d");
4787  if ($orig_set_time != '')
4788  {
4789  $shour = dol_print_date($set_time, "%H");
4790  $smin = dol_print_date($set_time, "%M");
4791  $ssec = dol_print_date($set_time, "%S");
4792  }
4793  else
4794  {
4795  $shour = '';
4796  $smin = '';
4797  $ssec = '';
4798  }
4799  }
4800  else
4801  {
4802  // Date est '' ou vaut -1
4803  $syear = '';
4804  $smonth = '';
4805  $sday = '';
4806  $shour = !isset($conf->global->MAIN_DEFAULT_DATE_HOUR) ? ($h == -1 ? '23' : '') : $conf->global->MAIN_DEFAULT_DATE_HOUR;
4807  $smin = !isset($conf->global->MAIN_DEFAULT_DATE_MIN) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_MIN;
4808  $ssec = !isset($conf->global->MAIN_DEFAULT_DATE_SEC) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_SEC;
4809  }
4810 
4811  // You can set MAIN_POPUP_CALENDAR to 'eldy' or 'jquery'
4812  $usecalendar='combo';
4813  if (! empty($conf->use_javascript_ajax) && (empty($conf->global->MAIN_POPUP_CALENDAR) || $conf->global->MAIN_POPUP_CALENDAR != "none")) {
4814  $usecalendar = ((empty($conf->global->MAIN_POPUP_CALENDAR) || $conf->global->MAIN_POPUP_CALENDAR == 'eldy')?'jquery':$conf->global->MAIN_POPUP_CALENDAR);
4815  }
4816  //if (! empty($conf->browser->phone)) $usecalendar='combo';
4817 
4818  if ($d)
4819  {
4820  // Show date with popup
4821  if ($usecalendar != 'combo')
4822  {
4823  $formated_date='';
4824  //print "e".$set_time." t ".$conf->format_date_short;
4825  if (strval($set_time) != '' && $set_time != -1)
4826  {
4827  //$formated_date=dol_print_date($set_time,$conf->format_date_short);
4828  $formated_date=dol_print_date($set_time,$langs->trans("FormatDateShortInput")); // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
4829  }
4830 
4831  // Calendrier popup version eldy
4832  if ($usecalendar == "eldy")
4833  {
4834  // Zone de saisie manuelle de la date
4835  $retstring.='<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidth75" maxlength="11" value="'.$formated_date.'"';
4836  $retstring.=($disabled?' disabled':'');
4837  $retstring.=' onChange="dpChangeDay(\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
4838  $retstring.='>';
4839 
4840  // Icone calendrier
4841  if (! $disabled)
4842  {
4843  $retstring.='<button id="'.$prefix.'Button" type="button" class="dpInvisibleButtons"';
4844  $base=DOL_URL_ROOT.'/core/';
4845  $retstring.=' onClick="showDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');"';
4846  $retstring.='>'.img_object($langs->trans("SelectDate"),'calendarday','class="datecallink"').'</button>';
4847  }
4848  else $retstring.='<button id="'.$prefix.'Button" type="button" class="dpInvisibleButtons">'.img_object($langs->trans("Disabled"),'calendarday','class="datecallink"').'</button>';
4849 
4850  $retstring.='<input type="hidden" id="'.$prefix.'day" name="'.$prefix.'day" value="'.$sday.'">'."\n";
4851  $retstring.='<input type="hidden" id="'.$prefix.'month" name="'.$prefix.'month" value="'.$smonth.'">'."\n";
4852  $retstring.='<input type="hidden" id="'.$prefix.'year" name="'.$prefix.'year" value="'.$syear.'">'."\n";
4853  }
4854  elseif ($usecalendar == 'jquery')
4855  {
4856  if (! $disabled)
4857  {
4858  // Output javascript for datepicker
4859  $retstring.="<script type='text/javascript'>";
4860  $retstring.="$(function(){ $('#".$prefix."').datepicker({
4861  dateFormat: '".$langs->trans("FormatDateShortJQueryInput")."',
4862  autoclose: true,
4863  todayHighlight: true,";
4864  if (! empty($conf->dol_use_jmobile))
4865  {
4866  $retstring.="
4867  beforeShow: function (input, datePicker) {
4868  input.disabled = true;
4869  },
4870  onClose: function (dateText, datePicker) {
4871  this.disabled = false;
4872  },
4873  ";
4874  }
4875  // Note: We don't need monthNames, monthNamesShort, dayNames, dayNamesShort, dayNamesMin, they are set globally on datepicker component in lib_head.js.php
4876  if (empty($conf->global->MAIN_POPUP_CALENDAR_ON_FOCUS))
4877  {
4878  $retstring.="
4879  showOn: 'button',
4880  buttonImage: '".DOL_URL_ROOT."/theme/".$conf->theme."/img/object_calendarday.png',
4881  buttonImageOnly: true";
4882  }
4883  $retstring.="
4884  }) });";
4885  $retstring.="</script>";
4886  }
4887 
4888  // Zone de saisie manuelle de la date
4889  $retstring.='<input id="'.$prefix.'" name="'.$prefix.'" type="text" class="maxwidth75" maxlength="11" value="'.$formated_date.'"';
4890  $retstring.=($disabled?' disabled':'');
4891  $retstring.=' onChange="dpChangeDay(\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript
4892  $retstring.='>';
4893 
4894  // Icone calendrier
4895  if (! $disabled)
4896  {
4897  /* Not required. Managed by option buttonImage of jquery
4898  $retstring.=img_object($langs->trans("SelectDate"),'calendarday','id="'.$prefix.'id" class="datecallink"');
4899  $retstring.="<script type='text/javascript'>";
4900  $retstring.="jQuery(document).ready(function() {";
4901  $retstring.=' jQuery("#'.$prefix.'id").click(function() {';
4902  $retstring.=" jQuery('#".$prefix."').focus();";
4903  $retstring.=' });';
4904  $retstring.='});';
4905  $retstring.="</script>";*/
4906  }
4907  else
4908  {
4909  $retstring.='<button id="'.$prefix.'Button" type="button" class="dpInvisibleButtons">'.img_object($langs->trans("Disabled"),'calendarday','class="datecallink"').'</button>';
4910  }
4911 
4912  $retstring.='<input type="hidden" id="'.$prefix.'day" name="'.$prefix.'day" value="'.$sday.'">'."\n";
4913  $retstring.='<input type="hidden" id="'.$prefix.'month" name="'.$prefix.'month" value="'.$smonth.'">'."\n";
4914  $retstring.='<input type="hidden" id="'.$prefix.'year" name="'.$prefix.'year" value="'.$syear.'">'."\n";
4915  }
4916  else
4917  {
4918  $retstring.="Bad value of MAIN_POPUP_CALENDAR";
4919  }
4920  }
4921  // Show date with combo selects
4922  else
4923  {
4924  //$retstring.='<div class="inline-block">';
4925  // Day
4926  $retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth50imp" id="'.$prefix.'day" name="'.$prefix.'day">';
4927 
4928  if ($emptydate || $set_time == -1)
4929  {
4930  $retstring.='<option value="0" selected>&nbsp;</option>';
4931  }
4932 
4933  for ($day = 1 ; $day <= 31; $day++)
4934  {
4935  $retstring.='<option value="'.$day.'"'.($day == $sday ? ' selected':'').'>'.$day.'</option>';
4936  }
4937 
4938  $retstring.="</select>";
4939 
4940  $retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth75imp" id="'.$prefix.'month" name="'.$prefix.'month">';
4941  if ($emptydate || $set_time == -1)
4942  {
4943  $retstring.='<option value="0" selected>&nbsp;</option>';
4944  }
4945 
4946  // Month
4947  for ($month = 1 ; $month <= 12 ; $month++)
4948  {
4949  $retstring.='<option value="'.$month.'"'.($month == $smonth?' selected':'').'>';
4950  $retstring.=dol_print_date(mktime(12,0,0,$month,1,2000),"%b");
4951  $retstring.="</option>";
4952  }
4953  $retstring.="</select>";
4954 
4955  // Year
4956  if ($emptydate || $set_time == -1)
4957  {
4958  $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.'">';
4959  }
4960  else
4961  {
4962  $retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth75imp" id="'.$prefix.'year" name="'.$prefix.'year">';
4963 
4964  for ($year = $syear - 10; $year < $syear + 10 ; $year++)
4965  {
4966  $retstring.='<option value="'.$year.'"'.($year == $syear ? ' selected':'').'>'.$year.'</option>';
4967  }
4968  $retstring.="</select>\n";
4969  }
4970  //$retstring.='</div>';
4971  }
4972  }
4973 
4974  if ($d && $h) $retstring.=($h==2?'<br>':' ');
4975 
4976  if ($h)
4977  {
4978  // Show hour
4979  $retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth50 '.($fullday?$fullday.'hour':'').'" id="'.$prefix.'hour" name="'.$prefix.'hour">';
4980  if ($emptyhours) $retstring.='<option value="-1">&nbsp;</option>';
4981  for ($hour = 0; $hour < 24; $hour++)
4982  {
4983  if (strlen($hour) < 2) $hour = "0" . $hour;
4984  $retstring.='<option value="'.$hour.'"'.(($hour == $shour)?' selected':'').'>'.$hour.(empty($conf->dol_optimize_smallscreen)?'':'H').'</option>';
4985  }
4986  $retstring.='</select>';
4987  if ($m && empty($conf->dol_optimize_smallscreen)) $retstring.=":";
4988  }
4989 
4990  if ($m)
4991  {
4992  // Show minutes
4993  $retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth50 '.($fullday?$fullday.'min':'').'" id="'.$prefix.'min" name="'.$prefix.'min">';
4994  if ($emptyhours) $retstring.='<option value="-1">&nbsp;</option>';
4995  for ($min = 0; $min < 60 ; $min++)
4996  {
4997  if (strlen($min) < 2) $min = "0" . $min;
4998  $retstring.='<option value="'.$min.'"'.(($min == $smin)?' selected':'').'>'.$min.(empty($conf->dol_optimize_smallscreen)?'':'').'</option>';
4999  }
5000  $retstring.='</select>';
5001 
5002  $retstring.='<input type="hidden" name="'.$prefix.'sec" value="'.$ssec.'">';
5003  }
5004 
5005  // Add a "Now" link
5006  if ($conf->use_javascript_ajax && $addnowlink)
5007  {
5008  // Script which will be inserted in the onClick of the "Now" link
5009  $reset_scripts = "";
5010 
5011  // Generate the date part, depending on the use or not of the javascript calendar
5012  $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date(dol_now(),'day').'\');';
5013  $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.dol_print_date(dol_now(),'%d').'\');';
5014  $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.dol_print_date(dol_now(),'%m').'\');';
5015  $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.dol_print_date(dol_now(),'%Y').'\');';
5016  /*if ($usecalendar == "eldy")
5017  {
5018  $base=DOL_URL_ROOT.'/core/';
5019  $reset_scripts .= 'resetDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');';
5020  }
5021  else
5022  {
5023  $reset_scripts .= 'this.form.elements[\''.$prefix.'day\'].value=formatDate(new Date(), \'d\'); ';
5024  $reset_scripts .= 'this.form.elements[\''.$prefix.'month\'].value=formatDate(new Date(), \'M\'); ';
5025  $reset_scripts .= 'this.form.elements[\''.$prefix.'year\'].value=formatDate(new Date(), \'yyyy\'); ';
5026  }*/
5027  // Update the hour part
5028  if ($h)
5029  {
5030  if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
5031  //$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); ';
5032  $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(),'%H').'\');';
5033  if ($fullday) $reset_scripts .= ' } ';
5034  }
5035  // Update the minute part
5036  if ($m)
5037  {
5038  if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
5039  //$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); ';
5040  $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(),'%M').'\');';
5041  if ($fullday) $reset_scripts .= ' } ';
5042  }
5043  // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
5044  if ($reset_scripts && empty($conf->dol_optimize_smallscreen))
5045  {
5046  $retstring.=' <button class="dpInvisibleButtons datenowlink" id="'.$prefix.'ButtonNow" type="button" name="_useless" value="now" onClick="'.$reset_scripts.'">';
5047  $retstring.=$langs->trans("Now");
5048  $retstring.='</button> ';
5049  }
5050  }
5051 
5052  // Add a "Plus one hour" link
5053  if ($conf->use_javascript_ajax && $addplusone)
5054  {
5055  // Script which will be inserted in the onClick of the "Add plusone" link
5056  $reset_scripts = "";
5057 
5058  // Generate the date part, depending on the use or not of the javascript calendar
5059  $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date(dol_now(),'day').'\');';
5060  $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.dol_print_date(dol_now(),'%d').'\');';
5061  $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.dol_print_date(dol_now(),'%m').'\');';
5062  $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.dol_print_date(dol_now(),'%Y').'\');';
5063  // Update the hour part
5064  if ($h)
5065  {
5066  if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
5067  $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(),'%H').'\');';
5068  if ($fullday) $reset_scripts .= ' } ';
5069  }
5070  // Update the minute part
5071  if ($m)
5072  {
5073  if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {";
5074  $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(),'%M').'\');';
5075  if ($fullday) $reset_scripts .= ' } ';
5076  }
5077  // If reset_scripts is not empty, print the link with the reset_scripts in the onClick
5078  if ($reset_scripts && empty($conf->dol_optimize_smallscreen))
5079  {
5080  $retstring.=' <button class="dpInvisibleButtons datenowlink" id="'.$prefix.'ButtonPlusOne" type="button" name="_useless2" value="plusone" onClick="'.$reset_scripts.'">';
5081  $retstring.=$langs->trans("DateStartPlusOne");
5082  $retstring.='</button> ';
5083  }
5084  }
5085 
5086  // Add a "Plus one hour" link
5087  if ($conf->use_javascript_ajax && $adddateof)
5088  {
5089  $tmparray=dol_getdate($adddateof);
5090  $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>';
5091  }
5092 
5093  if (! empty($nooutput)) return $retstring;
5094 
5095  print $retstring;
5096  return;
5097  }
5098 
5112  function select_duration($prefix, $iSecond='', $disabled=0, $typehour='select', $minunderhours=0, $nooutput=0)
5113  {
5114  global $langs;
5115 
5116  $retstring='';
5117 
5118  $hourSelected=0; $minSelected=0;
5119 
5120  // Hours
5121  if ($iSecond != '')
5122  {
5123  require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
5124 
5125  $hourSelected = convertSecondToTime($iSecond,'allhour');
5126  $minSelected = convertSecondToTime($iSecond,'min');
5127  }
5128 
5129  if ($typehour=='select' )
5130  {
5131  $retstring.='<select class="flat" name="'.$prefix.'hour"'.($disabled?' disabled':'').'>';
5132  for ($hour = 0; $hour < 25; $hour++) // For a duration, we allow 24 hours
5133  {
5134  $retstring.='<option value="'.$hour.'"';
5135  if ($hourSelected == $hour)
5136  {
5137  $retstring.=" selected";
5138  }
5139  $retstring.=">".$hour."</option>";
5140  }
5141  $retstring.="</select>";
5142  }
5143  elseif ($typehour=='text' || $typehour=='textselect')
5144  {
5145  $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):'').'">';
5146  }
5147  else return 'BadValueForParameterTypeHour';
5148 
5149  if ($typehour!='text') $retstring.=' '.$langs->trans('HourShort');
5150  else $retstring.='<span class="hideonsmartphone">:</span>';
5151 
5152  // Minutes
5153  if ($minunderhours) $retstring.='<br>';
5154  else $retstring.='<span class="hideonsmartphone">&nbsp;</span>';
5155 
5156  if ($typehour=='select' || $typehour=='textselect')
5157  {
5158  $retstring.='<select class="flat" name="'.$prefix.'min"'.($disabled?' disabled':'').'>';
5159  for ($min = 0; $min <= 55; $min=$min+5)
5160  {
5161  $retstring.='<option value="'.$min.'"';
5162  if ($minSelected == $min) $retstring.=' selected';
5163  $retstring.='>'.$min.'</option>';
5164  }
5165  $retstring.="</select>";
5166  }
5167  elseif ($typehour=='text' )
5168  {
5169  $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):'').'">';
5170  }
5171 
5172  if ($typehour!='text') $retstring.=' '.$langs->trans('MinuteShort');
5173 
5174  //$retstring.="&nbsp;";
5175 
5176  if (! empty($nooutput)) return $retstring;
5177 
5178  print $retstring;
5179  return;
5180  }
5181 
5182 
5199  function selectForForms($objectdesc, $htmlname, $preselectedvalue, $showempty='', $searchkey='', $placeholder='', $morecss='', $moreparams='', $forcecombo=0)
5200  {
5201  global $conf, $user;
5202 
5203  $objecttmp = null;
5204 
5205  $InfoFieldList = explode(":", $objectdesc);
5206  $classname=$InfoFieldList[0];
5207  $classpath=$InfoFieldList[1];
5208  if (! empty($classpath))
5209  {
5210  dol_include_once($classpath);
5211  if ($classname && class_exists($classname))
5212  {
5213  $objecttmp = new $classname($this->db);
5214  }
5215  }
5216  if (! is_object($objecttmp))
5217  {
5218  dol_syslog('Error bad setup of type for field '.$InfoFieldList, LOG_WARNING);
5219  return 'Error bad setup of type for field '.join(',', $InfoFieldList);
5220  }
5221 
5222  $prefixforautocompletemode=$objecttmp->element;
5223  if ($prefixforautocompletemode == 'societe') $prefixforautocompletemode='company';
5224  $confkeyforautocompletemode=strtoupper($prefixforautocompletemode).'_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
5225 
5226  dol_syslog(get_class($this)."::selectForForms", LOG_DEBUG);
5227 
5228  $out='';
5229  if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->$confkeyforautocompletemode) && ! $forcecombo)
5230  {
5231  $objectdesc=$classname.':'.$classpath;
5232  $urlforajaxcall = DOL_URL_ROOT.'/core/ajax/selectobject.php';
5233  //if ($objecttmp->element == 'societe') $urlforajaxcall = DOL_URL_ROOT.'/societe/ajax/company.php';
5234 
5235  // No immediate load of all database
5236  $urloption='htmlname='.$htmlname.'&outjson=1&objectdesc='.$objectdesc.($moreparams?$moreparams:'');
5237  // Activate the auto complete using ajax call.
5238  $out.= ajax_autocompleter($preselectedvalue, $htmlname, $urlforajaxcall, $urloption, $conf->global->$confkeyforautocompletemode, 0, array());
5239  $out.= '<style type="text/css">.ui-autocomplete { z-index: 250; }</style>';
5240  if ($placeholder) $placeholder=' placeholder="'.$placeholder.'"';
5241  $out.= '<input type="text" class="'.$morecss.'" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$preselectedvalue.'"'.$placeholder.' />';
5242  }
5243  else
5244  {
5245  // Immediate load of all database
5246  $out.=$this->selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo);
5247  }
5248 
5249  return $out;
5250  }
5251 
5269  function selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty='', $searchkey='', $placeholder='', $morecss='', $moreparams='', $forcecombo=0, $outputmode=0)
5270  {
5271  global $conf, $langs, $user;
5272 
5273  $prefixforautocompletemode=$objecttmp->element;
5274  if ($prefixforautocompletemode == 'societe') $prefixforautocompletemode='company';
5275  $confkeyforautocompletemode=strtoupper($prefixforautocompletemode).'_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
5276 
5277  $fieldstoshow='t.ref';
5278  if (! empty($objecttmp->fields))
5279  {
5280  $tmpfieldstoshow='';
5281  foreach($objecttmp->fields as $key => $val)
5282  {
5283  if ($val['showoncombobox']) $tmpfieldstoshow.=($tmpfieldstoshow?',':'').'t.'.$key;
5284  }
5285  if ($tmpfieldstoshow) $fieldstoshow = $tmpfieldstoshow;
5286  }
5287 
5288  $out='';
5289  $outarray=array();
5290 
5291  $num=0;
5292 
5293  // Search data
5294  $sql = "SELECT t.rowid, ".$fieldstoshow." FROM ".MAIN_DB_PREFIX .$objecttmp->table_element." as t";
5295  if ($objecttmp->ismultientitymanaged == 2)
5296  if (!$user->rights->societe->client->voir && !$user->societe_id) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
5297  $sql.= " WHERE t.entity IN (".getEntity($objecttmp->table_element).")";
5298  if ($objecttmp->ismultientitymanaged == 1 && ! empty($user->societe_id))
5299  {
5300  if ($objecttmp->element == 'societe') $sql.= " AND t.rowid = ".$user->societe_id;
5301  else $sql.= " AND t.fk_soc = ".$user->societe_id;
5302  }
5303  if ($searchkey != '') $sql.=natural_search(explode(',',$fieldstoshow), $searchkey);
5304  if ($objecttmp->ismultientitymanaged == 2)
5305  if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND t.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
5306  $sql.=$this->db->order($fieldstoshow,"ASC");
5307  //$sql.=$this->db->plimit($limit, 0);
5308 
5309  // Build output string
5310  $resql=$this->db->query($sql);
5311  if ($resql)
5312  {
5313  if (! $forcecombo)
5314  {
5315  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
5316  $out .= ajax_combobox($htmlname, null, $conf->global->$confkeyforautocompletemode);
5317  }
5318 
5319  // Construct $out and $outarray
5320  $out.= '<select id="'.$htmlname.'" class="flat'.($morecss?' '.$morecss:'').'"'.($moreparams?' '.$moreparams:'').' name="'.$htmlname.'">'."\n";
5321 
5322  // 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
5323  $textifempty='&nbsp;';
5324 
5325  //if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
5326  if (! empty($conf->global->$confkeyforautocompletemode))
5327  {
5328  if ($showempty && ! is_numeric($showempty)) $textifempty=$langs->trans($showempty);
5329  else $textifempty.=$langs->trans("All");
5330  }
5331  if ($showempty) $out.= '<option value="-1">'.$textifempty.'</option>'."\n";
5332 
5333  $num = $this->db->num_rows($resql);
5334  $i = 0;
5335  if ($num)
5336  {
5337  while ($i < $num)
5338  {
5339  $obj = $this->db->fetch_object($resql);
5340  $label='';
5341  $tmparray=explode(',', $fieldstoshow);
5342  foreach($tmparray as $key => $val)
5343  {
5344  $val = preg_replace('/t\./','',$val);
5345  $label .= (($label && $obj->$val)?' - ':'').$obj->$val;
5346  }
5347  if (empty($outputmode))
5348  {
5349  if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid)
5350  {
5351  $out.= '<option value="'.$obj->rowid.'" selected>'.$label.'</option>';
5352  }
5353  else
5354  {
5355  $out.= '<option value="'.$obj->rowid.'">'.$label.'</option>';
5356  }
5357  }
5358  else
5359  {
5360  array_push($outarray, array('key'=>$obj->rowid, 'value'=>$label, 'label'=>$label));
5361  }
5362 
5363  $i++;
5364  if (($i % 10) == 0) $out.="\n";
5365  }
5366  }
5367 
5368  $out.= '</select>'."\n";
5369  }
5370  else
5371  {
5372  dol_print_error($this->db);
5373  }
5374 
5375  $this->result=array('nbofelement'=>$num);
5376 
5377  if ($outputmode) return $outarray;
5378  return $out;
5379  }
5380 
5381 
5405  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)
5406  {
5407  global $conf, $langs;
5408 
5409  // Do we want a multiselect ?
5410  //$jsbeautify = 0;
5411  //if (preg_match('/^multi/',$htmlname)) $jsbeautify = 1;
5412  $jsbeautify = 1;
5413 
5414  if ($value_as_key) $array=array_combine($array, $array);
5415 
5416  $out='';
5417 
5418  // Add code for jquery to use multiselect
5419  if ($addjscombo && $jsbeautify)
5420  {
5421  $minLengthToAutocomplete=0;
5422  $tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?(constant('REQUIRE_JQUERY_MULTISELECT')?constant('REQUIRE_JQUERY_MULTISELECT'):'select2'):$conf->global->MAIN_USE_JQUERY_MULTISELECT;
5423 
5424  // Enhance with select2
5425  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
5426  $out .= ajax_combobox($htmlname);
5427  }
5428 
5429  $out.='<select id="'.preg_replace('/^\./','',$htmlname).'" '.($disabled?'disabled ':'').'class="flat '.(preg_replace('/^\./','',$htmlname)).($morecss?' '.$morecss:'').'"';
5430  $out.=' name="'.preg_replace('/^\./','',$htmlname).'" '.($moreparam?$moreparam:'');
5431  $out.='>';
5432 
5433  if ($show_empty)
5434  {
5435  $textforempty=' ';
5436  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.
5437  if (! is_numeric($show_empty)) $textforempty=$show_empty;
5438  $out.='<option class="optiongrey" '.($moreparamonempty?$moreparamonempty.' ':'').'value="'.($show_empty < 0 ? $show_empty : -1).'"'.($id == $show_empty ?' selected':'').'>'.$textforempty.'</option>'."\n";
5439  }
5440 
5441  if (is_array($array))
5442  {
5443  // Translate
5444  if ($translate)
5445  {
5446  foreach($array as $key => $value)
5447  {
5448  $array[$key]=$langs->trans($value);
5449  }
5450  }
5451 
5452  // Sort
5453  if ($sort == 'ASC') asort($array);
5454  elseif ($sort == 'DESC') arsort($array);
5455 
5456  foreach($array as $key => $value)
5457  {
5458  $disabled=''; $style='';
5459  if (! empty($disablebademail))
5460  {
5461  if (! preg_match('/&lt;.+@.+&gt;/', $value))
5462  {
5463  //$value=preg_replace('/'.preg_quote($a,'/').'/', $b, $value);
5464  $disabled=' disabled';
5465  $style=' class="warning"';
5466  }
5467  }
5468 
5469  if ($key_in_label)
5470  {
5471  if (empty($nohtmlescape)) $selectOptionValue = dol_escape_htmltag($key.' - '.($maxlen?dol_trunc($value,$maxlen):$value));
5472  else $selectOptionValue = $key.' - '.($maxlen?dol_trunc($value,$maxlen):$value);
5473  }
5474  else
5475  {
5476  if (empty($nohtmlescape)) $selectOptionValue = dol_escape_htmltag($maxlen?dol_trunc($value,$maxlen):$value);
5477  else $selectOptionValue = $maxlen?dol_trunc($value,$maxlen):$value;
5478  if ($value == '' || $value == '-') $selectOptionValue='&nbsp;';
5479  }
5480 
5481  $out.='<option value="'.$key.'"';
5482  $out.=$style.$disabled;
5483  if ($id != '' && $id == $key && ! $disabled) $out.=' selected'; // To preselect a value
5484  if ($nohtmlescape) $out.=' data-html="'.dol_escape_htmltag($selectOptionValue).'"';
5485  $out.='>';
5486  //var_dump($selectOptionValue);
5487  $out.=$selectOptionValue;
5488  $out.="</option>\n";
5489  }
5490  }
5491 
5492  $out.="</select>";
5493  return $out;
5494  }
5495 
5496 
5515  static function selectArrayAjax($htmlname, $url, $id='', $moreparam='', $moreparamtourl='', $disabled=0, $minimumInputLength=1, $morecss='', $callurlonselect=0, $placeholder='', $acceptdelayedhtml=0)
5516  {
5517  global $conf, $langs;
5518  global $delayedhtmlcontent;
5519 
5520  // TODO Use an internal dolibarr component instead of select2
5521  if (empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && ! defined('REQUIRE_JQUERY_MULTISELECT')) return '';
5522 
5523  $out='<select type="text" class="'.$htmlname.($morecss?' '.$morecss:'').'" '.($moreparam?$moreparam.' ':'').'name="'.$htmlname.'"></select>';
5524 
5525  $tmpplugin='select2';
5526  $outdelayed="\n".'<!-- JS CODE TO ENABLE '.$tmpplugin.' for id '.$htmlname.' -->
5527  <script type="text/javascript">
5528  $(document).ready(function () {
5529 
5530  '.($callurlonselect ? 'var saveRemoteData = [];':'').'
5531 
5532  $(".'.$htmlname.'").select2({
5533  ajax: {
5534  dir: "ltr",
5535  url: "'.$url.'",
5536  dataType: \'json\',
5537  delay: 250,
5538  data: function (params) {
5539  return {
5540  q: params.term, // search term
5541  page: params.page
5542  };
5543  },
5544  processResults: function (data) {
5545  // parse the results into the format expected by Select2.
5546  // since we are using custom formatting functions we do not need to alter the remote JSON data
5547  //console.log(data);
5548  saveRemoteData = data;
5549  /* format json result for select2 */
5550  result = []
5551  $.each( data, function( key, value ) {
5552  result.push({id: key, text: value.text});
5553  });
5554  //return {results:[{id:\'none\', text:\'aa\'}, {id:\'rrr\', text:\'Red\'},{id:\'bbb\', text:\'Search a into projects\'}], more:false}
5555  //console.log(result);
5556  return {results: result, more: false}
5557  },
5558  cache: true
5559  },
5560  language: select2arrayoflanguage,
5561  containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
5562  placeholder: "'.dol_escape_js($placeholder).'",
5563  escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
5564  minimumInputLength: '.$minimumInputLength.',
5565  formatResult: function(result, container, query, escapeMarkup) {
5566  return escapeMarkup(result.text);
5567  },
5568  });
5569 
5570  '.($callurlonselect ? '
5571  /* Code to execute a GET when we select a value */
5572  $(".'.$htmlname.'").change(function() {
5573  var selected = $(".'.$htmlname.'").val();
5574  console.log("We select "+selected)
5575  $(".'.$htmlname.'").val(""); /* reset visible combo value */
5576  $.each( saveRemoteData, function( key, value ) {
5577  if (key == selected)
5578  {
5579  console.log("selectArrayAjax - Do a redirect to "+value.url)
5580  location.assign(value.url);
5581  }
5582  });
5583  });' : '' ) . '
5584 
5585  });
5586  </script>';
5587 
5588  if ($acceptdelayedhtml)
5589  {
5590  $delayedhtmlcontent.=$outdelayed;
5591  }
5592  else
5593  {
5594  $out.=$outdelayed;
5595  }
5596  return $out;
5597  }
5598 
5615  static function multiselectarray($htmlname, $array, $selected=array(), $key_in_label=0, $value_as_key=0, $morecss='', $translate=0, $width=0, $moreattrib='',$elemtype='')
5616  {
5617  global $conf, $langs;
5618 
5619  $out = '';
5620 
5621  // Add code for jquery to use multiselect
5622  if (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT'))
5623  {
5624  $tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT;
5625  $out.="\n".'<!-- JS CODE TO ENABLE '.$tmpplugin.' for id '.$htmlname.' -->
5626  <script type="text/javascript">
5627  function formatResult(record) {'."\n";
5628  if ($elemtype == 'category')
5629  {
5630  $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>\';
5631  return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> \'+record.text+\'</span>\';';
5632  }
5633  else
5634  {
5635  $out.='return record.text;';
5636  }
5637  $out.= ' };
5638  function formatSelection(record) {'."\n";
5639  if ($elemtype == 'category')
5640  {
5641  $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>\';
5642  return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> \'+record.text+\'</span>\';';
5643  }
5644  else
5645  {
5646  $out.='return record.text;';
5647  }
5648  $out.= ' };
5649  $(document).ready(function () {
5650  $(\'#'.$htmlname.'\').'.$tmpplugin.'({
5651  dir: \'ltr\',
5652  // Specify format function for dropdown item
5653  formatResult: formatResult,
5654  templateResult: formatResult, /* For 4.0 */
5655  // Specify format function for selected item
5656  formatSelection: formatSelection,
5657  templateResult: formatSelection /* For 4.0 */
5658  });
5659  });
5660  </script>';
5661  }
5662 
5663  // Try also magic suggest
5664 
5665  $out .= '<select id="'.$htmlname.'" class="multiselect'.($morecss?' '.$morecss:'').'" multiple name="'.$htmlname.'[]"'.($moreattrib?' '.$moreattrib:'').($width?' style="width: '.(preg_match('/%/',$width)?$width:$width.'px').'"':'').'>'."\n";
5666  if (is_array($array) && ! empty($array))
5667  {
5668  if ($value_as_key) $array=array_combine($array, $array);
5669 
5670  if (! empty($array))
5671  {
5672  foreach ($array as $key => $value)
5673  {
5674  $out.= '<option value="'.$key.'"';
5675  if (is_array($selected) && ! empty($selected) && in_array($key, $selected) && !empty($key))
5676  {
5677  $out.= ' selected';
5678  }
5679  $out.= '>';
5680 
5681  $newval = ($translate ? $langs->trans($value) : $value);
5682  $newval = ($key_in_label ? $key.' - '.$newval : $newval);
5683  $out.= dol_htmlentitiesbr($newval);
5684  $out.= '</option>'."\n";
5685  }
5686  }
5687  }
5688  $out.= '</select>'."\n";
5689 
5690  return $out;
5691  }
5692 
5693 
5703  static function multiSelectArrayWithCheckbox($htmlname, &$array, $varpage)
5704  {
5705  global $conf,$langs,$user;
5706 
5707  if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) return '';
5708 
5709  $tmpvar="MAIN_SELECTEDFIELDS_".$varpage;
5710  if (! empty($user->conf->$tmpvar))
5711  {
5712  $tmparray=explode(',', $user->conf->$tmpvar);
5713  foreach($array as $key => $val)
5714  {
5715  //var_dump($key);
5716  //var_dump($tmparray);
5717  if (in_array($key, $tmparray)) $array[$key]['checked']=1;
5718  else $array[$key]['checked']=0;
5719  }
5720  }
5721  //var_dump($array);
5722 
5723  $lis='';
5724  $listcheckedstring='';
5725 
5726  foreach($array as $key => $val)
5727  {
5728  /* var_dump($val);
5729  var_dump(array_key_exists('enabled', $val));
5730  var_dump(!$val['enabled']);*/
5731  if (array_key_exists('enabled', $val) && isset($val['enabled']) && ! $val['enabled'])
5732  {
5733  unset($array[$key]); // We don't want this field
5734  continue;
5735  }
5736  if ($val['label'])
5737  {
5738  $lis.='<li><input type="checkbox" value="'.$key.'"'.(empty($val['checked'])?'':' checked="checked"').'/>'.dol_escape_htmltag($langs->trans($val['label'])).'</li>';
5739  $listcheckedstring.=(empty($val['checked'])?'':$key.',');
5740  }
5741  }
5742 
5743  $out ='<!-- Component multiSelectArrayWithCheckbox '.$htmlname.' -->
5744 
5745  <dl class="dropdown">
5746  <dt>
5747  <a href="#">
5748  '.img_picto('','list').'
5749  </a>
5750  <input type="hidden" class="'.$htmlname.'" name="'.$htmlname.'" value="'.$listcheckedstring.'">
5751  </dt>
5752  <dd class="dropowndd">
5753  <div class="multiselectcheckbox'.$htmlname.'">
5754  <ul class="ul'.$htmlname.'">
5755  '.$lis.'
5756  </ul>
5757  </div>
5758  </dd>
5759  </dl>
5760 
5761  <script type="text/javascript">
5762  jQuery(document).ready(function () {
5763  $(\'.multiselectcheckbox'.$htmlname.' input[type="checkbox"]\').on(\'click\', function () {
5764  console.log("A new field was added/removed")
5765  $("input:hidden[name=formfilteraction]").val(\'listafterchangingselectedfields\')
5766  var title = $(this).val() + ",";
5767  if ($(this).is(\':checked\')) {
5768  $(\'.'.$htmlname.'\').val(title + $(\'.'.$htmlname.'\').val());
5769  }
5770  else {
5771  $(\'.'.$htmlname.'\').val( $(\'.'.$htmlname.'\').val().replace(title, \'\') )
5772  }
5773  // Now, we submit page
5774  $(this).parents(\'form:first\').submit();
5775  });
5776  });
5777  </script>
5778 
5779  ';
5780  return $out;
5781  }
5782 
5791  function showCategories($id, $type, $rendermode=0)
5792  {
5793  global $db;
5794 
5795  include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
5796 
5797  $cat = new Categorie($db);
5798  $categories = $cat->containing($id, $type);
5799 
5800  if ($rendermode == 1)
5801  {
5802  $toprint = array();
5803  foreach($categories as $c)
5804  {
5805  $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formated text
5806  foreach($ways as $way)
5807  {
5808  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"'.($c->color?' style="background: #'.$c->color.';"':' style="background: #aaa"').'>'.img_object('','category').' '.$way.'</li>';
5809  }
5810  }
5811  return '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
5812  }
5813 
5814  if ($rendermode == 0)
5815  {
5816  $cate_arbo = $this->select_all_categories($type, '', 'parent', 64, 0, 1);
5817  foreach($categories as $c) {
5818  $arrayselected[] = $c->id;
5819  }
5820 
5821  return $this->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, '', 0, '100%', 'disabled', 'category');
5822  }
5823 
5824  return 'ErrorBadValueForParameterRenderMode'; // Should not happened
5825  }
5826 
5827 
5835  function showLinkedObjectBlock($object, $morehtmlright='')
5836  {
5837  global $conf,$langs,$hookmanager;
5838  global $bc;
5839 
5840  $object->fetchObjectLinked();
5841 
5842  // Bypass the default method
5843  $hookmanager->initHooks(array('commonobject'));
5844  $parameters=array();
5845  $reshook=$hookmanager->executeHooks('showLinkedObjectBlock',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
5846 
5847  if (empty($reshook))
5848  {
5849  $nbofdifferenttypes = count($object->linkedObjects);
5850 
5851  print '<!-- showLinkedObjectBlock -->';
5852  print load_fiche_titre($langs->trans('RelatedObjects'), $morehtmlright, '', 0, 0, 'showlinkedobjectblock');
5853 
5854 
5855  print '<div class="div-table-responsive-no-min">';
5856  print '<table class="noborder allwidth">';
5857 
5858  print '<tr class="liste_titre">';
5859  print '<td>'.$langs->trans("Type").'</td>';
5860  print '<td>'.$langs->trans("Ref").'</td>';
5861  print '<td align="center"></td>';
5862  print '<td align="center">'.$langs->trans("Date").'</td>';
5863  print '<td align="right">'.$langs->trans("AmountHTShort").'</td>';
5864  print '<td align="right">'.$langs->trans("Status").'</td>';
5865  print '<td></td>';
5866  print '</tr>';
5867 
5868  $nboftypesoutput=0;
5869 
5870  foreach($object->linkedObjects as $objecttype => $objects)
5871  {
5872  $tplpath = $element = $subelement = $objecttype;
5873 
5874  if ($objecttype != 'supplier_proposal' && preg_match('/^([^_]+)_([^_]+)/i',$objecttype,$regs))
5875  {
5876  $element = $regs[1];
5877  $subelement = $regs[2];
5878  $tplpath = $element.'/'.$subelement;
5879  }
5880  $tplname='linkedobjectblock';
5881 
5882  // To work with non standard path
5883  if ($objecttype == 'facture') {
5884  $tplpath = 'compta/'.$element;
5885  if (empty($conf->facture->enabled)) continue; // Do not show if module disabled
5886  }
5887  else if ($objecttype == 'facturerec') {
5888  $tplpath = 'compta/facture';
5889  $tplname = 'linkedobjectblockForRec';
5890  if (empty($conf->facture->enabled)) continue; // Do not show if module disabled
5891  }
5892  else if ($objecttype == 'propal') {
5893  $tplpath = 'comm/'.$element;
5894  if (empty($conf->propal->enabled)) continue; // Do not show if module disabled
5895  }
5896  else if ($objecttype == 'supplier_proposal') {
5897  if (empty($conf->supplier_proposal->enabled)) continue; // Do not show if module disabled
5898  }
5899  else if ($objecttype == 'shipping' || $objecttype == 'shipment') {
5900  $tplpath = 'expedition';
5901  if (empty($conf->expedition->enabled)) continue; // Do not show if module disabled
5902  }
5903  else if ($objecttype == 'delivery') {
5904  $tplpath = 'livraison';
5905  if (empty($conf->expedition->enabled)) continue; // Do not show if module disabled
5906  }
5907  else if ($objecttype == 'invoice_supplier') {
5908  $tplpath = 'fourn/facture';
5909  }
5910  else if ($objecttype == 'order_supplier') {
5911  $tplpath = 'fourn/commande';
5912  }
5913  else if ($objecttype == 'expensereport') {
5914  $tplpath = 'expensereport';
5915  }
5916  else if ($objecttype == 'subscription') {
5917  $tplpath = 'adherents';
5918  }
5919 
5920  global $linkedObjectBlock;
5921  $linkedObjectBlock = $objects;
5922 
5923 
5924  // Output template part (modules that overwrite templates must declare this into descriptor)
5925  $dirtpls=array_merge($conf->modules_parts['tpl'],array('/'.$tplpath.'/tpl'));
5926  foreach($dirtpls as $reldir)
5927  {
5928  if ($nboftypesoutput == ($nbofdifferenttypes - 1)) // No more type to show after
5929  {
5930  global $noMoreLinkedObjectBlockAfter;
5931  $noMoreLinkedObjectBlockAfter=1;
5932  }
5933 
5934  $res=@include dol_buildpath($reldir.'/'.$tplname.'.tpl.php');
5935  if ($res)
5936  {
5937  $nboftypesoutput++;
5938  break;
5939  }
5940  }
5941  }
5942 
5943  if (! $nboftypesoutput)
5944  {
5945  print '<tr><td class="impair opacitymedium" colspan="7">'.$langs->trans("None").'</td></tr>';
5946  }
5947 
5948  print '</table>';
5949  print '</div>';
5950 
5951  return $nbofdifferenttypes;
5952  }
5953  }
5954 
5963  function showLinkToObjectBlock($object, $restrictlinksto=array(), $excludelinksto=array())
5964  {
5965  global $conf, $langs, $hookmanager;
5966  global $bc;
5967 
5968  $linktoelem='';
5969  $linktoelemlist='';
5970 
5971  if (! is_object($object->thirdparty)) $object->fetch_thirdparty();
5972 
5973  $possiblelinks=array();
5974  if (is_object($object->thirdparty) && ! empty($object->thirdparty->id) && $object->thirdparty->id > 0)
5975  {
5976  $listofidcompanytoscan=$object->thirdparty->id;
5977  if (($object->thirdparty->parent > 0) && ! empty($conf->global->THIRDPARTY_INCLUDE_PARENT_IN_LINKTO)) $listofidcompanytoscan.=','.$object->thirdparty->parent;
5978  if (($object->fk_project > 0) && ! empty($conf->global->THIRDPARTY_INCLUDE_PROJECT_THIRDPARY_IN_LINKTO))
5979  {
5980  include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
5981  $tmpproject=new Project($this->db);
5982  $tmpproject->fetch($object->fk_project);
5983  if ($tmpproject->socid > 0 && ($tmpproject->socid != $object->thirdparty->id)) $listofidcompanytoscan.=','.$tmpproject->socid;
5984  unset($tmpproject);
5985  }
5986 
5987  $possiblelinks=array(
5988  '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').')'),
5989  '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').')'),
5990  '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.facnumber as 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('facture').')'),
5991  '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').')'),
5992  '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').')'),
5993  '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').')'),
5994  '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').')'),
5995  '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').')')
5996  );
5997  }
5998 
5999  global $action;
6000 
6001  // Can complete the possiblelink array
6002  $hookmanager->initHooks(array('commonobject'));
6003  $parameters=array();
6004  $reshook=$hookmanager->executeHooks('showLinkToObjectBlock',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
6005  if (empty($reshook))
6006  {
6007  if (is_array($hookmanager->resArray) && count($hookmanager->resArray))
6008  {
6009  $possiblelinks=array_merge($possiblelinks, $hookmanager->resArray);
6010  }
6011  }
6012  else if ($reshook > 0)
6013  {
6014  if (is_array($hookmanager->resArray) && count($hookmanager->resArray))
6015  {
6016  $possiblelinks=$hookmanager->resArray;
6017  }
6018  }
6019 
6020  foreach($possiblelinks as $key => $possiblelink)
6021  {
6022  $num = 0;
6023 
6024  if (empty($possiblelink['enabled'])) continue;
6025 
6026  if (! empty($possiblelink['perms']) && (empty($restrictlinksto) || in_array($key, $restrictlinksto)) && (empty($excludelinksto) || ! in_array($key, $excludelinksto)))
6027  {
6028  print '<div id="'.$key.'list"'.(empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)?' style="display:none"':'').'>';
6029  $sql = $possiblelink['sql'];
6030 
6031  $resqllist = $this->db->query($sql);
6032  if ($resqllist)
6033  {
6034  $num = $this->db->num_rows($resqllist);
6035  $i = 0;
6036 
6037  print '<br><form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formlinked'.$key.'">';
6038  print '<input type="hidden" name="id" value="'.$object->id.'">';
6039  print '<input type="hidden" name="action" value="addlink">';
6040  print '<input type="hidden" name="addlink" value="'.$key.'">';
6041  print '<table class="noborder">';
6042  print '<tr class="liste_titre">';
6043  print '<td class="nowrap"></td>';
6044  print '<td align="center">' . $langs->trans("Ref") . '</td>';
6045  print '<td align="left">' . $langs->trans("RefCustomer") . '</td>';
6046  print '<td align="right">' . $langs->trans("AmountHTShort") . '</td>';
6047  print '<td align="left">' . $langs->trans("Company") . '</td>';
6048  print '</tr>';
6049  while ($i < $num)
6050  {
6051  $objp = $this->db->fetch_object($resqlorderlist);
6052 
6053  $var = ! $var;
6054  print '<tr ' . $bc [$var] . '>';
6055  print '<td aling="left">';
6056  print '<input type="radio" name="idtolinkto" value=' . $objp->rowid . '>';
6057  print '</td>';
6058  print '<td align="center">' . $objp->ref . '</td>';
6059  print '<td>' . $objp->ref_client . '</td>';
6060  print '<td align="right">' . price($objp->total_ht) . '</td>';
6061  print '<td>' . $objp->name . '</td>';
6062  print '</tr>';
6063  $i++;
6064  }
6065  print '</table>';
6066  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>';
6067 
6068  print '</form>';
6069  $this->db->free($resqllist);
6070  } else {
6071  dol_print_error($this->db);
6072  }
6073  print '</div>';
6074  if ($num > 0)
6075  {
6076  }
6077 
6078  //$linktoelem.=($linktoelem?' &nbsp; ':'');
6079  if ($num > 0) $linktoelemlist.='<li><a href="#linkto'.$key.'" class="linkto dropdowncloseonclick" rel="'.$key.'">' . $langs->trans($possiblelink['label']) .' ('.$num.')</a></li>';
6080  //else $linktoelem.=$langs->trans($possiblelink['label']);
6081  else $linktoelemlist.='<li><span class="linktodisabled">' . $langs->trans($possiblelink['label']) . ' (0)</span></li>';
6082  }
6083  }
6084 
6085  if ($linktoelemlist)
6086  {
6087  $linktoelem='
6088  <dl class="dropdown" id="linktoobjectname">
6089  <dt><a href="#linktoobjectname">'.$langs->trans("LinkTo").'...</a></dt>
6090  <dd>
6091  <div class="multiselectlinkto">
6092  <ul class="ulselectedfields">'.$linktoelemlist.'
6093  </ul>
6094  </div>
6095  </dd>
6096  </dl>';
6097  }
6098  else
6099  {
6100  $linktoelem='';
6101  }
6102 
6103  print '<!-- Add js to show linkto box -->
6104  <script type="text/javascript" language="javascript">
6105  jQuery(document).ready(function() {
6106  jQuery(".linkto").click(function() {
6107  console.log("We choose to show/hide link for rel="+jQuery(this).attr(\'rel\'));
6108  jQuery("#"+jQuery(this).attr(\'rel\')+"list").toggle();
6109  jQuery(this).toggle();
6110  });
6111  });
6112  </script>
6113  ';
6114 
6115  return $linktoelem;
6116  }
6117 
6128  function selectyesno($htmlname, $value='', $option=0, $disabled=false, $useempty='')
6129  {
6130  global $langs;
6131 
6132  $yes="yes"; $no="no";
6133  if ($option)
6134  {
6135  $yes="1";
6136  $no="0";
6137  }
6138 
6139  $disabled = ($disabled ? ' disabled' : '');
6140 
6141  $resultyesno = '<select class="flat" id="'.$htmlname.'" name="'.$htmlname.'"'.$disabled.'>'."\n";
6142  if ($useempty) $resultyesno .= '<option value="-1"'.(($value < 0)?' selected':'').'>&nbsp;</option>'."\n";
6143  if (("$value" == 'yes') || ($value == 1))
6144  {
6145  $resultyesno .= '<option value="'.$yes.'" selected>'.$langs->trans("Yes").'</option>'."\n";
6146  $resultyesno .= '<option value="'.$no.'">'.$langs->trans("No").'</option>'."\n";
6147  }
6148  else
6149  {
6150  $selected=(($useempty && $value != '0' && $value != 'no')?'':' selected');
6151  $resultyesno .= '<option value="'.$yes.'">'.$langs->trans("Yes").'</option>'."\n";
6152  $resultyesno .= '<option value="'.$no.'"'.$selected.'>'.$langs->trans("No").'</option>'."\n";
6153  }
6154  $resultyesno .= '</select>'."\n";
6155  return $resultyesno;
6156  }
6157 
6158 
6159 
6169  function select_export_model($selected='',$htmlname='exportmodelid',$type='',$useempty=0)
6170  {
6171 
6172  $sql = "SELECT rowid, label";
6173  $sql.= " FROM ".MAIN_DB_PREFIX."export_model";
6174  $sql.= " WHERE type = '".$type."'";
6175  $sql.= " ORDER BY rowid";
6176  $result = $this->db->query($sql);
6177  if ($result)
6178  {
6179  print '<select class="flat" name="'.$htmlname.'">';
6180  if ($useempty)
6181  {
6182  print '<option value="-1">&nbsp;</option>';
6183  }
6184 
6185  $num = $this->db->num_rows($result);
6186  $i = 0;
6187  while ($i < $num)
6188  {
6189  $obj = $this->db->fetch_object($result);
6190  if ($selected == $obj->rowid)
6191  {
6192  print '<option value="'.$obj->rowid.'" selected>';
6193  }
6194  else
6195  {
6196  print '<option value="'.$obj->rowid.'">';
6197  }
6198  print $obj->label;
6199  print '</option>';
6200  $i++;
6201  }
6202  print "</select>";
6203  }
6204  else {
6205  dol_print_error($this->db);
6206  }
6207  }
6208 
6227  function showrefnav($object,$paramid,$morehtml='',$shownav=1,$fieldid='rowid',$fieldref='ref',$morehtmlref='',$moreparam='',$nodbprefix=0,$morehtmlleft='',$morehtmlstatus='',$morehtmlright='')
6228  {
6229  global $langs,$conf,$hookmanager;
6230 
6231  $ret='';
6232  if (empty($fieldid)) $fieldid='rowid';
6233  if (empty($fieldref)) $fieldref='ref';
6234 
6235  // Add where from hooks
6236  if (is_object($hookmanager))
6237  {
6238  $parameters=array();
6239  $reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters, $object); // Note that $action and $object may have been modified by hook
6240  $object->next_prev_filter.=$hookmanager->resPrint;
6241  }
6242  $previous_ref = $next_ref = '';
6243  if ($shownav)
6244  {
6245  //print "paramid=$paramid,morehtml=$morehtml,shownav=$shownav,$fieldid,$fieldref,$morehtmlref,$moreparam";
6246  $object->load_previous_next_ref((isset($object->next_prev_filter)?$object->next_prev_filter:''), $fieldid, $nodbprefix);
6247 
6248  $navurl = $_SERVER["PHP_SELF"];
6249  // Special case for project/task page
6250  if ($paramid == 'project_ref')
6251  {
6252  $navurl = preg_replace('/\/tasks\/(task|contact|time|note|document)\.php/','/tasks.php',$navurl);
6253  $paramid='ref';
6254  }
6255  $previous_ref = $object->ref_previous?'<a 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>';
6256  $next_ref = $object->ref_next?'<a 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>';
6257  }
6258 
6259  //print "xx".$previous_ref."x".$next_ref;
6260  $ret.='<!-- Start banner content --><div style="vertical-align: middle">';
6261 
6262  // Right part of banner
6263  if ($morehtmlright) $ret.='<div class="inline-block floatleft">'.$morehtmlright.'</div>';
6264 
6265  if ($previous_ref || $next_ref || $morehtml)
6266  {
6267  $ret.='<div class="pagination paginationref"><ul class="right">';
6268  }
6269  if ($morehtml)
6270  {
6271  $ret.='<li class="noborder litext">'.$morehtml.'</li>';
6272  }
6273  if ($shownav && ($previous_ref || $next_ref))
6274  {
6275  $ret.='<li class="pagination">'.$previous_ref.'</li>';
6276  $ret.='<li class="pagination">'.$next_ref.'</li>';
6277  }
6278  if ($previous_ref || $next_ref || $morehtml)
6279  {
6280  $ret.='</ul></div>';
6281  }
6282  if ($morehtmlstatus) $ret.='<div class="statusref">'.$morehtmlstatus.'</div>';
6283 
6284  // Left part of banner
6285  if ($morehtmlleft)
6286  {
6287  if ($conf->browser->layout == 'phone') $ret.='<div class="floatleft">'.$morehtmlleft.'</div>'; // class="center" to have photo in middle
6288  else $ret.='<div class="inline-block floatleft">'.$morehtmlleft.'</div>';
6289  }
6290 
6291  //if ($conf->browser->layout == 'phone') $ret.='<div class="clearboth"></div>';
6292  $ret.='<div class="inline-block floatleft valignmiddle refid'.(($shownav && ($previous_ref || $next_ref))?' refidpadding':'').'">';
6293 
6294  // For thirdparty, contact, user, member, the ref is the id, so we show something else
6295  if ($object->element == 'societe')
6296  {
6297  $ret.=dol_htmlentities($object->name);
6298  }
6299  else if ($object->element == 'member')
6300  {
6301  $fullname=$object->getFullName($langs);
6302  if ($object->morphy == 'mor') {
6303  $ret.= dol_htmlentities($object->societe) . ((! empty($fullname) && $object->societe != $fullname)?' ('.dol_htmlentities($fullname).')':'');
6304  } else {
6305  $ret.= dol_htmlentities($fullname) . ((! empty($object->societe) && $object->societe != $fullname)?' ('.dol_htmlentities($object->societe).')':'');
6306  }
6307  }
6308  else if (in_array($object->element, array('contact', 'user', 'usergroup')))
6309  {
6310  $ret.=dol_htmlentities($object->getFullName($langs));
6311  }
6312  else if (in_array($object->element, array('action', 'agenda')))
6313  {
6314  $ret.=$object->ref.'<br>'.$object->label;
6315  }
6316  else if (in_array($object->element, array('adherent_type')))
6317  {
6318  $ret.=$object->label;
6319  }
6320  else if ($object->element == 'ecm_directories')
6321  {
6322  $ret.='';
6323  }
6324  else if ($fieldref != 'none') $ret.=dol_htmlentities($object->$fieldref);
6325 
6326 
6327  if ($morehtmlref)
6328  {
6329  $ret.=' '.$morehtmlref;
6330  }
6331  $ret.='</div>';
6332 
6333  $ret.='</div><!-- End banner content -->';
6334 
6335  return $ret;
6336  }
6337 
6338 
6346  function showbarcode(&$object,$width=100)
6347  {
6348  global $conf;
6349 
6350  //Check if barcode is filled in the card
6351  if (empty($object->barcode)) return '';
6352 
6353  // Complete object if not complete
6354  if (empty($object->barcode_type_code) || empty($object->barcode_type_coder))
6355  {
6356  $result = $object->fetch_barcode();
6357  //Check if fetch_barcode() failed
6358  if ($result < 1) return '<!-- ErrorFetchBarcode -->';
6359  }
6360 
6361  // Barcode image
6362  $url=DOL_URL_ROOT.'/viewimage.php?modulepart=barcode&generator='.urlencode($object->barcode_type_coder).'&code='.urlencode($object->barcode).'&encoding='.urlencode($object->barcode_type_code);
6363  $out ='<!-- url barcode = '.$url.' -->';
6364  $out.='<img src="'.$url.'">';
6365  return $out;
6366  }
6367 
6382  static function showphoto($modulepart, $object, $width=100, $height=0, $caneditfield=0, $cssclass='photowithmargin', $imagesize='', $addlinktofullsize=1, $cache=0)
6383  {
6384  global $conf,$langs;
6385 
6386  $entity = (! empty($object->entity) ? $object->entity : $conf->entity);
6387  $id = (! empty($object->id) ? $object->id : $object->rowid);
6388 
6389  $ret='';$dir='';$file='';$originalfile='';$altfile='';$email='';
6390  if ($modulepart=='societe')
6391  {
6392  $dir=$conf->societe->multidir_output[$entity];
6393  if (! empty($object->logo))
6394  {
6395  if ((string) $imagesize == 'mini') $file=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.getImageFileNameForSize($object->logo, '_mini'); // getImageFileNameForSize include the thumbs
6396  else if ((string) $imagesize == 'small') $file=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.getImageFileNameForSize($object->logo, '_small');
6397  else $file=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.$object->logo;
6398  $originalfile=get_exdir(0, 0, 0, 0, $object, 'thirdparty').'/logos/'.$object->logo;
6399  }
6400  $email=$object->email;
6401  }
6402  else if ($modulepart=='contact')
6403  {
6404  $dir=$conf->societe->multidir_output[$entity].'/contact';
6405  if (! empty($object->photo))
6406  {
6407  if ((string) $imagesize == 'mini') $file=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.getImageFileNameForSize($object->photo, '_mini');
6408  else if ((string) $imagesize == 'small') $file=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.getImageFileNameForSize($object->photo, '_small');
6409  else $file=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.$object->photo;
6410  $originalfile=get_exdir(0, 0, 0, 0, $object, 'contact').'/photos/'.$object->photo;
6411  }
6412  $email=$object->email;
6413  }
6414  else if ($modulepart=='userphoto')
6415  {
6416  $dir=$conf->user->dir_output;
6417  if (! empty($object->photo))
6418  {
6419  if ((string) $imagesize == 'mini') $file=get_exdir($id, 2, 0, 0, $object, 'user').getImageFileNameForSize($object->photo, '_mini');
6420  else if ((string) $imagesize == 'small') $file=get_exdir($id, 2, 0, 0, $object, 'user').getImageFileNameForSize($object->photo, '_small');
6421  else $file=get_exdir($id, 2, 0, 0, $object, 'user').$object->photo;
6422  $originalfile=get_exdir($id, 2, 0, 0, $object, 'user').$object->photo;
6423  }
6424  if (! empty($conf->global->MAIN_OLD_IMAGE_LINKS)) $altfile=$object->id.".jpg"; // For backward compatibility
6425  $email=$object->email;
6426  }
6427  else if ($modulepart=='memberphoto')
6428  {
6429  $dir=$conf->adherent->dir_output;
6430  if (! empty($object->photo))
6431  {
6432  if ((string) $imagesize == 'mini') $file=get_exdir(0, 0, 0, 0, $object, 'member').'photos/'.getImageFileNameForSize($object->photo, '_mini');
6433  else if ((string) $imagesize == 'small') $file=get_exdir(0, 0, 0, 0, $object, 'member').'photos/'.getImageFileNameForSize($object->photo, '_small');
6434  else $file=get_exdir(0, 0, 0, 0, $object, 'member').'photos/'.$object->photo;
6435  $originalfile=get_exdir(0, 0, 0, 0, $object, 'member').'photos/'.$object->photo;
6436  }
6437  if (! empty($conf->global->MAIN_OLD_IMAGE_LINKS)) $altfile=$object->id.".jpg"; // For backward compatibility
6438  $email=$object->email;
6439  }
6440  else
6441  {
6442  // Generic case to show photos
6443  $dir=$conf->$modulepart->dir_output;
6444  if (! empty($object->photo))
6445  {
6446  if ((string) $imagesize == 'mini') $file=get_exdir($id, 2, 0, 0, $object, $modulepart).'photos/'.getImageFileNameForSize($object->photo, '_mini');
6447  else if ((string) $imagesize == 'small') $file=get_exdir($id, 2, 0, 0, $object, $modulepart).'photos/'.getImageFileNameForSize($object->photo, '_small');
6448  else $file=get_exdir($id, 2, 0, 0, $object, $modulepart).'photos/'.$object->photo;
6449  $originalfile=get_exdir($id, 2, 0, 0, $object, $modulepart).'photos/'.$object->photo;
6450  }
6451  if (! empty($conf->global->MAIN_OLD_IMAGE_LINKS)) $altfile=$object->id.".jpg"; // For backward compatibility
6452  $email=$object->email;
6453  }
6454 
6455  if ($dir)
6456  {
6457  if ($file && file_exists($dir."/".$file))
6458  {
6459  if ($addlinktofullsize)
6460  {
6461  $urladvanced=getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity='.$entity);
6462  if ($urladvanced) $ret.='<a href="'.$urladvanced.'">';
6463  else $ret.='<a href="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$entity.'&file='.urlencode($originalfile).'&cache='.$cache.'">';
6464  }
6465  $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.'">';
6466  if ($addlinktofullsize) $ret.='</a>';
6467  }
6468  else if ($altfile && file_exists($dir."/".$altfile))
6469  {
6470  if ($addlinktofullsize)
6471  {
6472  $urladvanced=getAdvancedPreviewUrl($modulepart, $originalfile, 0, '&entity='.$entity);
6473  if ($urladvanced) $ret.='<a href="'.$urladvanced.'">';
6474  else $ret.='<a href="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$entity.'&file='.urlencode($originalfile).'&cache='.$cache.'">';
6475  }
6476  $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.'">';
6477  if ($addlinktofullsize) $ret.='</a>';
6478  }
6479  else
6480  {
6481  $nophoto='/public/theme/common/nophoto.png';
6482  if (in_array($modulepart,array('userphoto','contact'))) // For module that are "physical" users
6483  {
6484  $nophoto='/public/theme/common/user_anonymous.png';
6485  if ($object->gender == 'man') $nophoto='/public/theme/common/user_man.png';
6486  if ($object->gender == 'woman') $nophoto='/public/theme/common/user_woman.png';
6487  }
6488 
6489  if (! empty($conf->gravatar->enabled) && $email)
6490  {
6494  global $dolibarr_main_url_root;
6495  $ret.='<!-- Put link to gravatar -->';
6496  //$defaultimg=urlencode(dol_buildpath($nophoto,3));
6497  $defaultimg='mm';
6498  $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
6499  }
6500  else
6501  {
6502  $ret.='<img class="photo'.$modulepart.($cssclass?' '.$cssclass:'').'" alt="No photo" '.($width?' width="'.$width.'"':'').($height?' height="'.$height.'"':'').' src="'.DOL_URL_ROOT.$nophoto.'">';
6503  }
6504  }
6505 
6506  if ($caneditfield)
6507  {
6508  if ($object->photo) $ret.="<br>\n";
6509  $ret.='<table class="nobordernopadding centpercent">';
6510  if ($object->photo) $ret.='<tr><td><input type="checkbox" class="flat photodelete" name="deletephoto" id="photodelete"> '.$langs->trans("Delete").'<br><br></td></tr>';
6511  $ret.='<tr><td class="tdoverflow"><input type="file" class="flat maxwidth200onsmartphone" name="photo" id="photoinput"></td></tr>';
6512  $ret.='</table>';
6513  }
6514 
6515  }
6516  else dol_print_error('','Call of showphoto with wrong parameters modulepart='.$modulepart);
6517 
6518  return $ret;
6519  }
6520 
6535  function select_dolgroups($selected='', $htmlname='groupid', $show_empty=0, $exclude='', $disabled=0, $include='', $enableonly='', $force_entity=0)
6536  {
6537  global $conf,$user,$langs;
6538 
6539  // Permettre l'exclusion de groupes
6540  if (is_array($exclude)) $excludeGroups = implode("','",$exclude);
6541  // Permettre l'inclusion de groupes
6542  if (is_array($include)) $includeGroups = implode("','",$include);
6543 
6544  $out='';
6545 
6546  // On recherche les groupes
6547  $sql = "SELECT ug.rowid, ug.nom as name";
6548  if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
6549  {
6550  $sql.= ", e.label";
6551  }
6552  $sql.= " FROM ".MAIN_DB_PREFIX."usergroup as ug ";
6553  if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
6554  {
6555  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entity as e ON e.rowid=ug.entity";
6556  if ($force_entity) $sql.= " WHERE ug.entity IN (0,".$force_entity.")";
6557  else $sql.= " WHERE ug.entity IS NOT NULL";
6558  }
6559  else
6560  {
6561  $sql.= " WHERE ug.entity IN (0,".$conf->entity.")";
6562  }
6563  if (is_array($exclude) && $excludeGroups) $sql.= " AND ug.rowid NOT IN ('".$excludeGroups."')";
6564  if (is_array($include) && $includeGroups) $sql.= " AND ug.rowid IN ('".$includeGroups."')";
6565  $sql.= " ORDER BY ug.nom ASC";
6566 
6567  dol_syslog(get_class($this)."::select_dolgroups", LOG_DEBUG);
6568  $resql=$this->db->query($sql);
6569  if ($resql)
6570  {
6571  // Enhance with select2
6572  include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
6573  $out .= ajax_combobox($htmlname);
6574 
6575  $out.= '<select class="flat minwidth200" id="'.$htmlname.'" name="'.$htmlname.'"'.($disabled?' disabled':'').'>';
6576 
6577  $num = $this->db->num_rows($resql);
6578  $i = 0;
6579  if ($num)
6580  {
6581  if ($show_empty) $out.= '<option value="-1"'.($selected==-1?' selected':'').'>&nbsp;</option>'."\n";
6582 
6583  while ($i < $num)
6584  {
6585  $obj = $this->db->fetch_object($resql);
6586  $disableline=0;
6587  if (is_array($enableonly) && count($enableonly) && ! in_array($obj->rowid,$enableonly)) $disableline=1;
6588 
6589  $out.= '<option value="'.$obj->rowid.'"';
6590  if ($disableline) $out.= ' disabled';
6591  if ((is_object($selected) && $selected->id == $obj->rowid) || (! is_object($selected) && $selected == $obj->rowid))
6592  {
6593  $out.= ' selected';
6594  }
6595  $out.= '>';
6596 
6597  $out.= $obj->name;
6598  if (! empty($conf->multicompany->enabled) && empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $conf->entity == 1)
6599  {
6600  $out.= " (".$obj->label.")";
6601  }
6602 
6603  $out.= '</option>';
6604  $i++;
6605  }
6606  }
6607  else
6608  {
6609  if ($show_empty) $out.= '<option value="-1"'.($selected==-1?' selected':'').'></option>'."\n";
6610  $out.= '<option value="" disabled>'.$langs->trans("NoUserGroupDefined").'</option>';
6611  }
6612  $out.= '</select>';
6613  }
6614  else
6615  {
6616  dol_print_error($this->db);
6617  }
6618 
6619  return $out;
6620  }
6621 
6622 
6629  {
6630  global $conf, $langs;
6631 
6632  $out='<div class="nowrap">';
6633  $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")).'">';
6634  $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")).'">';
6635  $out.='</div>';
6636 
6637  return $out;
6638  }
6639 
6647  function showCheckAddButtons($cssclass='checkforaction', $calljsfunction=0)
6648  {
6649  global $conf, $langs;
6650 
6651  $out='';
6652  if (! empty($conf->use_javascript_ajax)) $out.='<div class="inline-block checkallactions"><input type="checkbox" id="checkalla