* Copyright (C) 2004-2012 Laurent Destailleur * Copyright (C) 2004 Benoit Mortier * Copyright (C) 2004 Sebastien Di Cintio * Copyright (C) 2004 Eric Seigne * Copyright (C) 2005-2017 Regis Houssin * Copyright (C) 2006 Andre Cianfarani * Copyright (C) 2006 Marc Barilley/Ocebo * Copyright (C) 2007 Franky Van Liedekerke * Copyright (C) 2007 Patrick Raguin * Copyright (C) 2010 Juanjo Menent * Copyright (C) 2010-2019 Philippe Grand * Copyright (C) 2011 Herve Prot * Copyright (C) 2012-2016 Marcos García * Copyright (C) 2012 Cedric Salvador * Copyright (C) 2012-2015 Raphaël Doursenaud * Copyright (C) 2014 Alexandre Spangaro * Copyright (C) 2018 Ferran Marcet * Copyright (C) 2018-2019 Frédéric France * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2018 Christophe Battarel * Copyright (C) 2018 Josep Lluis Amador * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/core/class/html.form.class.php * \ingroup core * \brief File of class with all html predefined components */ /** * Class to manage generation of HTML components * Only common components must be here. * * TODO Merge all function load_cache_* and loadCache* (except load_cache_vatrates) into one generic function loadCacheTable */ class Form { /** * @var DoliDB Database handler. */ public $db; /** * @var string Error code (or message) */ public $error = ''; /** * @var string[] Array of error strings */ public $errors = array(); public $num; // Cache arrays public $cache_types_paiements = array(); public $cache_conditions_paiements = array(); public $cache_availability = array(); public $cache_demand_reason = array(); public $cache_types_fees = array(); public $cache_vatrates = array(); /** * Constructor * * @param DoliDB $db Database handler */ public function __construct($db) { $this->db = $db; } /** * Output key field for an editable field * * @param string $text Text of label or key to translate * @param string $htmlname Name of select field ('edit' prefix will be added) * @param string $preselected Value to show/edit (not used in this function) * @param object $object Object * @param boolean $perm Permission to allow button to edit parameter. Set it to 0 to have a not edited field. * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols', 'datepicker' ('day' do not work, don't know why), 'ckeditor:dolibarr_zzz:width:height:savemethod:1:rows:cols', 'select;xxx[:class]'...) * @param string $moreparam More param to add on a href URL. * @param int $fieldrequired 1 if we want to show field as mandatory using the "fieldrequired" CSS. * @param int $notabletag 1=Do not output table tags but output a ':', 2=Do not output table tags and no ':', 3=Do not output table tags but output a ' ' * @param string $paramid Key of parameter for id ('id', 'socid') * @param string $help Tooltip help * @return string HTML edit field */ public function editfieldkey($text, $htmlname, $preselected, $object, $perm, $typeofdata = 'string', $moreparam = '', $fieldrequired = 0, $notabletag = 0, $paramid = 'id', $help = '') { global $conf, $langs; $ret = ''; // TODO change for compatibility if (!empty($conf->global->MAIN_USE_JQUERY_JEDITABLE) && !preg_match('/^select;/', $typeofdata)) { if (!empty($perm)) { $tmp = explode(':', $typeofdata); $ret .= '
'; if ($fieldrequired) $ret .= ''; if ($help) { $ret .= $this->textwithpicto($langs->trans($text), $help); } else { $ret .= $langs->trans($text); } if ($fieldrequired) $ret .= ''; $ret .= '
'."\n"; } else { if ($fieldrequired) $ret .= ''; if ($help) { $ret .= $this->textwithpicto($langs->trans($text), $help); } else { $ret .= $langs->trans($text); } if ($fieldrequired) $ret .= ''; } } else { if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret .= ''; if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret .= ''; if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret .= '
'; if ($fieldrequired) $ret .= ''; if ($help) { $ret .= $this->textwithpicto($langs->trans($text), $help); } else { $ret .= $langs->trans($text); } if ($fieldrequired) $ret .= ''; if (!empty($notabletag)) $ret .= ' '; if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret .= ''; if ($htmlname && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret .= 'id.$moreparam.'">'.img_edit($langs->trans('Edit'), ($notabletag ? 0 : 1)).''; if (!empty($notabletag) && $notabletag == 1) $ret .= ' : '; if (!empty($notabletag) && $notabletag == 3) $ret .= ' '; if (empty($notabletag) && GETPOST('action', 'aZ09') != 'edit'.$htmlname && $perm) $ret .= '
'; } return $ret; } /** * Output value of a field for an editable field * * @param string $text Text of label (not used in this function) * @param string $htmlname Name of select field * @param string $value Value to show/edit * @param object $object Object * @param boolean $perm Permission to allow button to edit parameter * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols%', 'datepicker' ('day' do not work, don't know why), 'dayhour' or 'datepickerhour', 'ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols', 'select;xkey:xval,ykey:yval,...') * @param string $editvalue When in edit mode, use this value as $value instead of value (for example, you can provide here a formated price instead of value). Use '' to use same than $value * @param object $extObject External object * @param mixed $custommsg String or Array of custom messages : eg array('success' => 'MyMessage', 'error' => 'MyMessage') * @param string $moreparam More param to add on the form action href URL * @param int $notabletag Do no output table tags * @param string $formatfunc Call a specific function to output field * @param string $paramid Key of parameter for id ('id', 'socid') * @return string HTML edit field */ public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 0, $formatfunc = '', $paramid = 'id') { global $conf, $langs, $db; $ret = ''; // Check parameters if (empty($typeofdata)) return 'ErrorBadParameter'; // When option to edit inline is activated if (!empty($conf->global->MAIN_USE_JQUERY_JEDITABLE) && !preg_match('/^select;|datehourpicker/', $typeofdata)) // TODO add jquery timepicker and support select { $ret .= $this->editInPlace($object, $value, $htmlname, $perm, $typeofdata, $editvalue, $extObject, $custommsg); } else { if (GETPOST('action', 'aZ09') == 'edit'.$htmlname) { $ret .= "\n"; $ret .= '
'; $ret .= ''; $ret .= ''; $ret .= ''; if (empty($notabletag)) $ret .= ''; if (empty($notabletag)) $ret .= ''; if (empty($notabletag)) $ret .= ''; if (empty($notabletag)) $ret .= '
'; if (preg_match('/^(string|safehtmlstring|email)/', $typeofdata)) { $tmp = explode(':', $typeofdata); $ret .= ''; } elseif (preg_match('/^(numeric|amount)/', $typeofdata)) { $tmp = explode(':', $typeofdata); $valuetoshow = price2num($editvalue ? $editvalue : $value); $ret .= ''; } elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) // if wysiwyg is enabled $typeofdata = 'ckeditor' { $tmp = explode(':', $typeofdata); $cols = $tmp[2]; $morealt = ''; if (preg_match('/%/', $cols)) { $morealt = ' style="width: '.$cols.'"'; $cols = ''; } $valuetoshow = ($editvalue ? $editvalue : $value); $ret .= ''; } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') { $ret .= $this->selectDate($value, $htmlname, 0, 0, 1, 'form'.$htmlname, 1, 0); } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') { $ret .= $this->selectDate($value, $htmlname, 1, 1, 1, 'form'.$htmlname, 1, 0); } elseif (preg_match('/^select;/', $typeofdata)) { $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata)); $arraylist = array(); foreach ($arraydata as $val) { $tmp = explode(':', $val); $tmpkey = str_replace('|', ':', $tmp[0]); $arraylist[$tmpkey] = $tmp[1]; } $ret .= $this->selectarray($htmlname, $arraylist, $value); } elseif (preg_match('/^ckeditor/', $typeofdata)) { $tmp = explode(':', $typeofdata); // Example: ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols:uselocalbrowser require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $doleditor = new DolEditor($htmlname, ($editvalue ? $editvalue : $value), ($tmp[2] ? $tmp[2] : ''), ($tmp[3] ? $tmp[3] : '100'), ($tmp[1] ? $tmp[1] : 'dolibarr_notes'), 'In', ($tmp[5] ? $tmp[5] : 0), (isset($tmp[8]) ? ($tmp[8] ?true:false) : true), true, ($tmp[6] ? $tmp[6] : '20'), ($tmp[7] ? $tmp[7] : '100')); $ret .= $doleditor->Create(1); } if (empty($notabletag)) $ret .= ''; //else $ret.='
'; $ret .= ''; if (preg_match('/ckeditor|textarea/', $typeofdata) && empty($notabletag)) $ret .= '
'."\n"; $ret .= ''; if (empty($notabletag)) $ret .= '
'."\n"; $ret .= '
'."\n"; } else { if (preg_match('/^(email)/', $typeofdata)) $ret .= dol_print_email($value, 0, 0, 0, 0, 1); elseif (preg_match('/^(amount|numeric)/', $typeofdata)) $ret .= ($value != '' ? price($value, '', $langs, 0, -1, -1, $conf->currency) : ''); elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) $ret .= dol_htmlentitiesbr($value); elseif (preg_match('/^safehtmlstring/', $typeofdata)) $ret .= dol_string_onlythesehtmltags($value); elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') $ret .= dol_print_date($value, 'day'); elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') $ret .= dol_print_date($value, 'dayhour'); elseif (preg_match('/^select;/', $typeofdata)) { $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata)); $arraylist = array(); foreach ($arraydata as $val) { $tmp = explode(':', $val); $arraylist[$tmp[0]] = $tmp[1]; } $ret .= $arraylist[$value]; } elseif (preg_match('/^ckeditor/', $typeofdata)) { $tmpcontent = dol_htmlentitiesbr($value); if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB)) { $firstline = preg_replace('/
.*/', '', $tmpcontent); $firstline = preg_replace('/[\n\r].*/', '', $firstline); $tmpcontent = $firstline.((strlen($firstline) != strlen($tmpcontent)) ? '...' : ''); } // We dont use dol_escape_htmltag to get the html formating active, but this need we must also // clean data from some dangerous html $ret .= dol_string_onlythesehtmltags(dol_htmlentitiesbr($tmpcontent)); } else { $ret .= dol_escape_htmltag($value); } if ($formatfunc && method_exists($object, $formatfunc)) { $ret = $object->$formatfunc($ret); } } } return $ret; } /** * Output edit in place form * * @param string $fieldname Name of the field * @param object $object Object * @param boolean $perm Permission to allow button to edit parameter. Set it to 0 to have a not edited field. * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols', 'datepicker' ('day' do not work, don't know why), 'ckeditor:dolibarr_zzz:width:height:savemethod:1:rows:cols', 'select;xxx[:class]'...) * @param string $check Same coe than $check parameter of GETPOST() * @param string $morecss More CSS * @return string HTML code for the edit of alternative language */ public function widgetForTranslation($fieldname, $object, $perm, $typeofdata = 'string', $check = '', $morecss = '') { global $conf, $langs, $extralanguages; $result = ''; // List of extra languages $arrayoflangcode = array(); if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE)) $arrayoflangcode[] = $conf->global->PDF_USE_ALSO_LANGUAGE_CODE; if (is_array($arrayoflangcode) && count($arrayoflangcode)) { if (!is_object($extralanguages)) { include_once DOL_DOCUMENT_ROOT.'/core/class/extralanguages.class.php'; $extralanguages = new ExtraLanguages($this->db); } $extralanguages->fetch_name_extralanguages('societe'); if (!is_array($extralanguages->attributes[$object->element]) || empty($extralanguages->attributes[$object->element][$fieldname])) { return ''; // No extralang field to show } $result .= ''."\n"; $result .= '
'; $s = img_picto($langs->trans("ShowOtherLanguages"), 'language', '', false, 0, 0, '', 'fa-15 editfieldlang'); $result .= $s; $result .= '
'; $result .= ''; $result .= ''; } return $result; } /** * Output edit in place form * * @param object $object Object * @param string $value Value to show/edit * @param string $htmlname DIV ID (field name) * @param int $condition Condition to edit * @param string $inputType Type of input ('string', 'numeric', 'datepicker' ('day' do not work, don't know why), 'textarea:rows:cols', 'ckeditor:dolibarr_zzz:width:height:?:1:rows:cols', 'select:loadmethod:savemethod:buttononly') * @param string $editvalue When in edit mode, use this value as $value instead of value * @param object $extObject External object * @param mixed $custommsg String or Array of custom messages : eg array('success' => 'MyMessage', 'error' => 'MyMessage') * @return string HTML edit in place */ protected function editInPlace($object, $value, $htmlname, $condition, $inputType = 'textarea', $editvalue = null, $extObject = null, $custommsg = null) { global $conf; $out = ''; // Check parameters if (preg_match('/^text/', $inputType)) $value = dol_nl2br($value); elseif (preg_match('/^numeric/', $inputType)) $value = price($value); elseif ($inputType == 'day' || $inputType == 'datepicker') $value = dol_print_date($value, 'day'); if ($condition) { $element = false; $table_element = false; $fk_element = false; $loadmethod = false; $savemethod = false; $ext_element = false; $button_only = false; $inputOption = ''; if (is_object($object)) { $element = $object->element; $table_element = $object->table_element; $fk_element = $object->id; } if (is_object($extObject)) { $ext_element = $extObject->element; } if (preg_match('/^(string|email|numeric)/', $inputType)) { $tmp = explode(':', $inputType); $inputType = $tmp[0]; if (!empty($tmp[1])) $inputOption = $tmp[1]; if (!empty($tmp[2])) $savemethod = $tmp[2]; $out .= ''."\n"; } elseif ((preg_match('/^day$/', $inputType)) || (preg_match('/^datepicker/', $inputType)) || (preg_match('/^datehourpicker/', $inputType))) { $tmp = explode(':', $inputType); $inputType = $tmp[0]; if (!empty($tmp[1])) $inputOption = $tmp[1]; if (!empty($tmp[2])) $savemethod = $tmp[2]; $out .= ''."\n"; // Use for timestamp format } elseif (preg_match('/^(select|autocomplete)/', $inputType)) { $tmp = explode(':', $inputType); $inputType = $tmp[0]; $loadmethod = $tmp[1]; if (!empty($tmp[2])) $savemethod = $tmp[2]; if (!empty($tmp[3])) $button_only = true; } elseif (preg_match('/^textarea/', $inputType)) { $tmp = explode(':', $inputType); $inputType = $tmp[0]; $rows = (empty($tmp[1]) ? '8' : $tmp[1]); $cols = (empty($tmp[2]) ? '80' : $tmp[2]); } elseif (preg_match('/^ckeditor/', $inputType)) { $tmp = explode(':', $inputType); $inputType = $tmp[0]; $toolbar = $tmp[1]; if (!empty($tmp[2])) $width = $tmp[2]; if (!empty($tmp[3])) $heigth = $tmp[3]; if (!empty($tmp[4])) $savemethod = $tmp[4]; if (!empty($conf->fckeditor->enabled)) { $out .= ''."\n"; } else { $inputType = 'textarea'; } } $out .= ''."\n"; $out .= ''."\n"; $out .= ''."\n"; $out .= ''."\n"; if (!empty($savemethod)) $out .= ''."\n"; if (!empty($ext_element)) $out .= ''."\n"; if (!empty($custommsg)) { if (is_array($custommsg)) { if (!empty($custommsg['success'])) $out .= ''."\n"; if (!empty($custommsg['error'])) $out .= ''."\n"; } else $out .= ''."\n"; } if ($inputType == 'textarea') { $out .= ''."\n"; $out .= ''."\n"; } $out .= ''.$value.''."\n"; $out .= ''.(!empty($editvalue) ? $editvalue : $value).''."\n"; } else { $out = $value; } return $out; } /** * Show a text and picto with tooltip on text or picto. * Can be called by an instancied $form->textwithtooltip or by a static call Form::textwithtooltip * * @param string $text Text to show * @param string $htmltext HTML content of tooltip. Must be HTML/UTF8 encoded. * @param int $tooltipon 1=tooltip on text, 2=tooltip on image, 3=tooltip sur les 2 * @param int $direction -1=image is before, 0=no image, 1=image is after * @param string $img Html code for image (use img_xxx() function to get it) * @param string $extracss Add a CSS style to td tags * @param int $notabs 0=Include table and tr tags, 1=Do not include table and tr tags, 2=use div, 3=use span * @param string $incbefore Include code before the text * @param int $noencodehtmltext Do not encode into html entity the htmltext * @param string $tooltiptrigger ''=Tooltip on hover, 'abc'=Tooltip on click (abc is a unique key) * @param int $forcenowrap Force no wrap between text and picto (works with notabs=2 only) * @return string Code html du tooltip (texte+picto) * @see textwithpicto() Use thisfunction if you can. * TODO Move this as static as soon as everybody use textwithpicto or @Form::textwithtooltip */ public function textwithtooltip($text, $htmltext, $tooltipon = 1, $direction = 0, $img = '', $extracss = '', $notabs = 3, $incbefore = '', $noencodehtmltext = 0, $tooltiptrigger = '', $forcenowrap = 0) { if ($incbefore) $text = $incbefore.$text; if (!$htmltext) return $text; $tag = 'td'; if ($notabs == 2) $tag = 'div'; if ($notabs == 3) $tag = 'span'; // Sanitize tooltip $htmltext = str_replace(array("\r", "\n"), '', $htmltext); $extrastyle = ''; if ($direction < 0) { $extracss = ($extracss ? $extracss.' ' : '').($notabs != 3 ? 'inline-block' : ''); $extrastyle = 'padding: 0px; padding-left: 3px !important;'; } if ($direction > 0) { $extracss = ($extracss ? $extracss.' ' : '').($notabs != 3 ? 'inline-block' : ''); $extrastyle = 'padding: 0px; padding-right: 3px !important;'; } $classfortooltip = 'classfortooltip'; $s = ''; $textfordialog = ''; if ($tooltiptrigger == '') { $htmltext = str_replace('"', '"', $htmltext); } else { $classfortooltip = 'classfortooltiponclick'; $textfordialog .= ''; } if ($tooltipon == 2 || $tooltipon == 3) { $paramfortooltipimg = ' class="'.$classfortooltip.($notabs != 3 ? ' inline-block' : '').($extracss ? ' '.$extracss : '').'" style="padding: 0px;'.($extrastyle ? ' '.$extrastyle : '').'"'; if ($tooltiptrigger == '') $paramfortooltipimg .= ' title="'.($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)).'"'; // Attribut to put on img tag to store tooltip else $paramfortooltipimg .= ' dolid="'.$tooltiptrigger.'"'; } else $paramfortooltipimg = ($extracss ? ' class="'.$extracss.'"' : '').($extrastyle ? ' style="'.$extrastyle.'"' : ''); // Attribut to put on td text tag if ($tooltipon == 1 || $tooltipon == 3) { $paramfortooltiptd = ' class="'.($tooltipon == 3 ? 'cursorpointer ' : '').$classfortooltip.' inline-block'.($extracss ? ' '.$extracss : '').'" style="padding: 0px;'.($extrastyle ? ' '.$extrastyle : '').'" '; if ($tooltiptrigger == '') $paramfortooltiptd .= ' title="'.($noencodehtmltext ? $htmltext : dol_escape_htmltag($htmltext, 1)).'"'; // Attribut to put on td tag to store tooltip else $paramfortooltiptd .= ' dolid="'.$tooltiptrigger.'"'; } else $paramfortooltiptd = ($extracss ? ' class="'.$extracss.'"' : '').($extrastyle ? ' style="'.$extrastyle.'"' : ''); // Attribut to put on td text tag if (empty($notabs)) $s .= ''; elseif ($notabs == 2) $s .= '
'; // Define value if value is before if ($direction < 0) { $s .= '<'.$tag.$paramfortooltipimg; if ($tag == 'td') { $s .= ' class=valigntop" width="14"'; } $s .= '>'.$textfordialog.$img.''; } // Use another method to help avoid having a space in value in order to use this value with jquery // Define label if ((string) $text != '') $s .= '<'.$tag.$paramfortooltiptd.'>'.$text.''; // Define value if value is after if ($direction > 0) { $s .= '<'.$tag.$paramfortooltipimg; if ($tag == 'td') $s .= ' class="valignmiddle" width="14"'; $s .= '>'.$textfordialog.$img.''; } if (empty($notabs)) $s .= '
'; elseif ($notabs == 2) $s .= ''; return $s; } /** * Show a text with a picto and a tooltip on picto * * @param string $text Text to show * @param string $htmltext Content of tooltip * @param int $direction 1=Icon is after text, -1=Icon is before text, 0=no icon * @param string $type Type of picto ('info', 'infoclickable', 'help', 'helpclickable', 'warning', 'superadmin', 'mypicto@mymodule', ...) or image filepath or 'none' * @param string $extracss Add a CSS style to td, div or span tag * @param int $noencodehtmltext Do not encode into html entity the htmltext * @param int $notabs 0=Include table and tr tags, 1=Do not include table and tr tags, 2=use div, 3=use span * @param string $tooltiptrigger ''=Tooltip on hover, 'abc'=Tooltip on click (abc is a unique key, clickable link is on image or on link if param $type='none' or on both if $type='xxxclickable') * @param int $forcenowrap Force no wrap between text and picto (works with notabs=2 only) * @return string HTML code of text, picto, tooltip */ public function textwithpicto($text, $htmltext, $direction = 1, $type = 'help', $extracss = '', $noencodehtmltext = 0, $notabs = 3, $tooltiptrigger = '', $forcenowrap = 0) { global $conf, $langs; $alt = ''; if ($tooltiptrigger) $alt = $langs->transnoentitiesnoconv("ClickToShowHelp"); //For backwards compatibility if ($type == '0') $type = 'info'; elseif ($type == '1') $type = 'help'; // If info or help with no javascript, show only text if (empty($conf->use_javascript_ajax)) { if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') return $text; else { $alt = $htmltext; $htmltext = ''; } } // If info or help with smartphone, show only text (tooltip hover can't works) if (!empty($conf->dol_no_mouse_hover) && empty($tooltiptrigger)) { if ($type == 'info' || $type == 'infoclickable' || $type == 'help' || $type == 'helpclickable') return $text; } // If info or help with smartphone, show only text (tooltip on click does not works with dialog on smaprtphone) //if (! empty($conf->dol_no_mouse_hover) && ! empty($tooltiptrigger)) //{ //if ($type == 'info' || $type == 'help') return ''.$text.'''; //} $img = ''; if ($type == 'info') $img = img_help(0, $alt); elseif ($type == 'help') $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt); elseif ($type == 'helpclickable') $img = img_help(($tooltiptrigger != '' ? 2 : 1), $alt); elseif ($type == 'superadmin') $img = img_picto($alt, 'redstar'); elseif ($type == 'admin') $img = img_picto($alt, 'star'); elseif ($type == 'warning') $img = img_warning($alt); elseif ($type != 'none') $img = img_picto($alt, $type); // $type can be an image path return $this->textwithtooltip($text, $htmltext, ((($tooltiptrigger && !$img) || strpos($type, 'clickable')) ? 3 : 2), $direction, $img, $extracss, $notabs, '', $noencodehtmltext, $tooltiptrigger, $forcenowrap); } /** * Generate select HTML to choose massaction * * @param string $selected Value auto selected when at least one record is selected. Not a preselected value. Use '0' by default. * @param array $arrayofaction array('code'=>'label', ...). The code is the key stored into the GETPOST('massaction') when submitting action. * @param int $alwaysvisible 1=select button always visible * @param string $name Name for massaction * @param string $cssclass CSS class used to check for select * @return string|void Select list */ public function selectMassAction($selected, $arrayofaction, $alwaysvisible = 0, $name = 'massaction', $cssclass = 'checkforselect') { global $conf, $langs, $hookmanager; $disabled = 0; $ret = '
'; $ret .= ''; if (empty($conf->dol_optimize_smallscreen)) $ret .= ajax_combobox('.'.$name.'select'); // 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 $ret .= ''; // Hidden button BEFORE so it is the one used when we submit with ENTER. $ret .= ''; $ret .= '
'; if (!empty($conf->use_javascript_ajax)) { $ret .= ' '; } return $ret; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return combo list of activated countries, into language of user * * @param string $selected Id or Code or Label of preselected country * @param string $htmlname Name of html select object * @param string $htmloption More html options on select object * @param integer $maxlength Max length for labels (0=no limit) * @param string $morecss More css class * @param string $usecodeaskey ''=Use id as key (default), 'code3'=Use code on 3 alpha as key, 'code2"=Use code on 2 alpha as key * @param int $showempty Show empty choice * @param int $disablefavorites 1=Disable favorites, * @param int $addspecialentries 1=Add dedicated entries for group of countries (like 'European Economic Community', ...) * @param array $exclude_country_code Array of country code (iso2) to exclude * @return string HTML string with select */ public function select_country($selected = '', $htmlname = 'country_id', $htmloption = '', $maxlength = 0, $morecss = 'minwidth300', $usecodeaskey = '', $showempty = 1, $disablefavorites = 0, $addspecialentries = 0, $exclude_country_code = array()) { // phpcs:enable global $conf, $langs, $mysoc; $langs->load("dict"); $out = ''; $countryArray = array(); $favorite = array(); $label = array(); $atleastonefavorite = 0; $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite"; $sql .= " FROM ".MAIN_DB_PREFIX."c_country"; $sql .= " WHERE active > 0"; //$sql.= " ORDER BY code ASC"; dol_syslog(get_class($this)."::select_country", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $out .= ''; } else { dol_print_error($this->db); } // Make select dynamic include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox('select'.$htmlname); return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return select list of incoterms * * @param string $selected Id or Code of preselected incoterm * @param string $location_incoterms Value of input location * @param string $page Defined the form action * @param string $htmlname Name of html select object * @param string $htmloption Options html on select object * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification) * @param array $events Event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @return string HTML string with select and input */ public function select_incoterms($selected = '', $location_incoterms = '', $page = '', $htmlname = 'incoterm_id', $htmloption = '', $forcecombo = 1, $events = array()) { // phpcs:enable global $conf, $langs; $langs->load("dict"); $out = ''; $incotermArray = array(); $sql = "SELECT rowid, code"; $sql .= " FROM ".MAIN_DB_PREFIX."c_incoterms"; $sql .= " WHERE active > 0"; $sql .= " ORDER BY code ASC"; dol_syslog(get_class($this)."::select_incoterm", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { if ($conf->use_javascript_ajax && !$forcecombo) { include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname, $events); } if (!empty($page)) { $out .= '
'; $out .= ''; $out .= ''; } $out .= ''; $out .= ''; if (!empty($page)) { $out .= '
'; } } else { dol_print_error($this->db); } return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of types of lines (product or service) * Example: 0=product, 1=service, 9=other (for external module) * * @param string $selected Preselected type * @param string $htmlname Name of field in html form * @param int $showempty Add an empty field * @param int $hidetext Do not show label 'Type' before combo box (used only if there is at least 2 choices to select) * @param integer $forceall 1=Force to show products and services in combo list, whatever are activated modules, 0=No force, 2=Force to show only Products, 3=Force to show only services, -1=Force none (and set hidden field to 'service') * @return void */ public function select_type_of_lines($selected = '', $htmlname = 'type', $showempty = 0, $hidetext = 0, $forceall = 0) { // phpcs:enable global $db, $langs, $user, $conf; // If product & services are enabled or both disabled. if ($forceall == 1 || (empty($forceall) && !empty($conf->product->enabled) && !empty($conf->service->enabled)) || (empty($forceall) && empty($conf->product->enabled) && empty($conf->service->enabled))) { if (empty($hidetext)) print $langs->trans("Type").': '; print ''; //if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1); } if ((empty($forceall) && empty($conf->product->enabled) && !empty($conf->service->enabled)) || $forceall == 3) { print $langs->trans("Service"); print ''; } if ((empty($forceall) && !empty($conf->product->enabled) && empty($conf->service->enabled)) || $forceall == 2) { print $langs->trans("Product"); print ''; } if ($forceall < 0) // This should happened only for contracts when both predefined product and service are disabled. { print ''; // By default we set on service for contract. If CONTRACT_SUPPORT_PRODUCTS is set, forceall should be 1 not -1 } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Load into cache cache_types_fees, array of types of fees * * @return int Nb of lines loaded, <0 if KO */ public function load_cache_types_fees() { // phpcs:enable global $langs; $num = count($this->cache_types_fees); if ($num > 0) return 0; // Cache already loaded dol_syslog(__METHOD__, LOG_DEBUG); $langs->load("trips"); $sql = "SELECT c.code, c.label"; $sql .= " FROM ".MAIN_DB_PREFIX."c_type_fees as c"; $sql .= " WHERE active > 0"; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); $i = 0; while ($i < $num) { $obj = $this->db->fetch_object($resql); // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut $label = ($obj->code != $langs->trans($obj->code) ? $langs->trans($obj->code) : $langs->trans($obj->label)); $this->cache_types_fees[$obj->code] = $label; $i++; } asort($this->cache_types_fees); return $num; } else { dol_print_error($this->db); return -1; } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of types of notes * * @param string $selected Preselected type * @param string $htmlname Name of field in form * @param int $showempty Add an empty field * @return void */ public function select_type_fees($selected = '', $htmlname = 'type', $showempty = 0) { // phpcs:enable global $user, $langs; dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG); $this->load_cache_types_fees(); print ''; if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return HTML code to select a company. * * @param int $selected Preselected products * @param string $htmlname Name of HTML select field (must be unique in page) * @param int $filter Filter on thirdparty * @param int $limit Limit on number of returned lines * @param array $ajaxoptions Options for ajax_autocompleter * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification) * @return string Return select box for thirdparty. * @deprecated 3.8 Use select_company instead. For exemple $form->select_thirdparty(GETPOST('socid'),'socid','',0) => $form->select_company(GETPOST('socid'),'socid','',1,0,0,array(),0) */ public function select_thirdparty($selected = '', $htmlname = 'socid', $filter = '', $limit = 20, $ajaxoptions = array(), $forcecombo = 0) { // phpcs:enable return $this->select_thirdparty_list($selected, $htmlname, $filter, 1, 0, $forcecombo, array(), '', 0, $limit); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Output html form to select a third party * * @param string $selected Preselected type * @param string $htmlname Name of field in form * @param string $filter Optional filters criteras. WARNING: To avoid SQL injection, only few chars [.a-z0-9 =<>] are allowed here (example: 's.rowid <> x', 's.client IN (1,3)') * @param string $showempty Add an empty field (Can be '1' or text key to use on empty line like 'SelectThirdParty') * @param int $showtype Show third party type in combolist (customer, prospect or supplier) * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification) * @param array $events Ajax event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param int $limit Maximum number of elements * @param string $morecss Add more css styles to the SELECT component * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container * @param string $selected_input_value Value of preselected input text (for use with ajax) * @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after) * @param array $ajaxoptions Options for ajax_autocompleter * @param bool $multiple add [] in the name of element and add 'multiple' attribut (not working with ajax_autocompleter) * @return string HTML string with select box for thirdparty. */ public function select_company($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $limit = 0, $morecss = 'minwidth100', $moreparam = '', $selected_input_value = '', $hidelabel = 1, $ajaxoptions = array(), $multiple = false) { // phpcs:enable global $conf, $user, $langs; $out = ''; if (!empty($conf->use_javascript_ajax) && !empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT) && !$forcecombo) { // No immediate load of all database $placeholder = ''; if ($selected && empty($selected_input_value)) { require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; $societetmp = new Societe($this->db); $societetmp->fetch($selected); $selected_input_value = $societetmp->name; unset($societetmp); } // mode 1 $urloption = 'htmlname='.urlencode($htmlname).'&outjson=1&filter='.urlencode($filter).($showtype ? '&showtype='.urlencode($showtype) : ''); $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/societe/ajax/company.php', $urloption, $conf->global->COMPANY_USE_SEARCH_TO_SELECT, 0, $ajaxoptions); $out .= ''; if (empty($hidelabel)) print $langs->trans("RefOrLabel").' : '; elseif ($hidelabel > 1) { $placeholder = ' placeholder="'.$langs->trans("RefOrLabel").'"'; if ($hidelabel == 2) { $out .= img_picto($langs->trans("Search"), 'search'); } } $out .= 'global->THIRDPARTY_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />'; if ($hidelabel == 3) { $out .= img_picto($langs->trans("Search"), 'search'); } } else { // Immediate load of all database $out .= $this->select_thirdparty_list($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events, '', 0, $limit, $morecss, $moreparam, $multiple); } return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Output html form to select a third party. * Note, you must use the select_company to get the component to select a third party. This function must only be called by select_company. * * @param string $selected Preselected type * @param string $htmlname Name of field in form * @param string $filter Optional filters criteras (example: 's.rowid <> x', 's.client in (1,3)') * @param string $showempty Add an empty field (Can be '1' or text to use on empty line like 'SelectThirdParty') * @param int $showtype Show third party type in combolist (customer, prospect or supplier) * @param int $forcecombo Force to use standard HTML select component without beautification * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param string $filterkey Filter on key value * @param int $outputmode 0=HTML select string, 1=Array * @param int $limit Limit number of answers * @param string $morecss Add more css styles to the SELECT component * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container * @param bool $multiple add [] in the name of element and add 'multiple' attribut * @return string HTML string with */ public function select_thirdparty_list($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $filterkey = '', $outputmode = 0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $multiple = false) { // phpcs:enable global $conf, $user, $langs; $out = ''; $num = 0; $outarray = array(); if ($selected === '') $selected = array(); elseif (!is_array($selected)) $selected = array($selected); // Clean $filter that may contains sql conditions so sql code if (function_exists('testSqlAndScriptInject')) { if (testSqlAndScriptInject($filter, 3) > 0) { $filter = ''; } } // On recherche les societes $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.client, s.fournisseur, s.code_client, s.code_fournisseur"; if ($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST) { $sql .= ", s.address, s.zip, s.town"; $sql .= ", dictp.code as country_code"; } $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$user->socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; if ($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST) { $sql .= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."c_country as dictp ON dictp.rowid=s.fk_pays"; } $sql .= " WHERE s.entity IN (".getEntity('societe').")"; if (!empty($user->socid)) $sql .= " AND s.rowid = ".$user->socid; if ($filter) $sql .= " AND (".$filter.")"; if (!$user->rights->societe->client->voir && !$user->socid) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; if (!empty($conf->global->COMPANY_HIDE_INACTIVE_IN_COMBOBOX)) $sql .= " AND s.status <> 0"; // Add criteria if ($filterkey && $filterkey != '') { $sql .= " AND ("; $prefix = empty($conf->global->COMPANY_DONOTSEARCH_ANYWHERE) ? '%' : ''; // Can use index if COMPANY_DONOTSEARCH_ANYWHERE is on // For natural search $scrit = explode(' ', $filterkey); $i = 0; if (count($scrit) > 1) $sql .= "("; foreach ($scrit as $crit) { if ($i > 0) $sql .= " AND "; $sql .= "(s.nom LIKE '".$this->db->escape($prefix.$crit)."%')"; $i++; } if (count($scrit) > 1) $sql .= ")"; if (!empty($conf->barcode->enabled)) { $sql .= " OR s.barcode LIKE '".$this->db->escape($prefix.$filterkey)."%'"; } $sql .= " OR s.code_client LIKE '".$this->db->escape($prefix.$filterkey)."%' OR s.code_fournisseur LIKE '".$this->db->escape($prefix.$filterkey)."%'"; $sql .= ")"; } $sql .= $this->db->order("nom", "ASC"); $sql .= $this->db->plimit($limit, 0); // Build output string dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { if (!$forcecombo) { include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname, $events, $conf->global->COMPANY_USE_SEARCH_TO_SELECT); } // Construct $out and $outarray $out .= ''."\n"; } else { dol_print_error($this->db); } $this->result = array('nbofthirdparties'=>$num); if ($outputmode) return $outarray; return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return HTML combo list of absolute discounts * * @param string $selected Id remise fixe pre-selectionnee * @param string $htmlname Nom champ formulaire * @param string $filter Criteres optionnels de filtre * @param int $socid Id of thirdparty * @param int $maxvalue Max value for lines that can be selected * @return int Return number of qualifed lines in list */ public function select_remises($selected, $htmlname, $filter, $socid, $maxvalue = 0) { // phpcs:enable global $langs, $conf; // On recherche les remises $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,"; $sql .= " re.description, re.fk_facture_source"; $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re"; $sql .= " WHERE re.fk_soc = ".(int) $socid; $sql .= " AND re.entity = ".$conf->entity; if ($filter) $sql .= " AND ".$filter; $sql .= " ORDER BY re.description ASC"; dol_syslog(get_class($this)."::select_remises", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { print ''; return $qualifiedlines; } else { dol_print_error($this->db); return -1; } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of all contacts (for a third party or all) * * @param int $socid Id ot third party or 0 for all * @param string $selected Id contact pre-selectionne * @param string $htmlname Name of HTML field ('none' for a not editable field) * @param int $showempty 0=no empty value, 1=add an empty value, 2=add line 'Internal' (used by user edit), 3=add an empty value only if more than one record into list * @param string $exclude List of contacts id to exclude * @param string $limitto Disable answers that are not id in this array list * @param integer $showfunction Add function into label * @param string $moreclass Add more class to class style * @param integer $showsoc Add company into label * @param int $forcecombo Force to use combo box * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param bool $options_only Return options only (for ajax treatment) * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container * @param string $htmlid Html id to use instead of htmlname * @return int <0 if KO, Nb of contact in list if OK * @deprected You can use selectcontacts directly (warning order of param was changed) */ public function select_contacts($socid, $selected = '', $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $moreclass = '', $showsoc = 0, $forcecombo = 0, $events = array(), $options_only = false, $moreparam = '', $htmlid = '') { // phpcs:enable print $this->selectcontacts($socid, $selected, $htmlname, $showempty, $exclude, $limitto, $showfunction, $moreclass, $options_only, $showsoc, $forcecombo, $events, $moreparam, $htmlid); return $this->num; } /** * Return HTML code of the SELECT of list of all contacts (for a third party or all). * This also set the number of contacts found into $this->num * * @since 9.0 Add afterSelectContactOptions hook * * @param int $socid Id ot third party or 0 for all or -1 for empty list * @param array|int $selected Array of ID of pre-selected contact id * @param string $htmlname Name of HTML field ('none' for a not editable field) * @param int $showempty 0=no empty value, 1=add an empty value, 2=add line 'Internal' (used by user edit), 3=add an empty value only if more than one record into list * @param string $exclude List of contacts id to exclude * @param string $limitto Disable answers that are not id in this array list * @param integer $showfunction Add function into label * @param string $moreclass Add more class to class style * @param bool $options_only Return options only (for ajax treatment) * @param integer $showsoc Add company into label * @param int $forcecombo Force to use combo box (so no ajax beautify effect) * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container * @param string $htmlid Html id to use instead of htmlname * @param bool $multiple add [] in the name of element and add 'multiple' attribut * @return int <0 if KO, Nb of contact in list if OK */ public function selectcontacts($socid, $selected = '', $htmlname = 'contactid', $showempty = 0, $exclude = '', $limitto = '', $showfunction = 0, $moreclass = '', $options_only = false, $showsoc = 0, $forcecombo = 0, $events = array(), $moreparam = '', $htmlid = '', $multiple = false) { global $conf, $langs, $hookmanager, $action; $langs->load('companies'); if (empty($htmlid)) $htmlid = $htmlname; if ($selected === '') $selected = array(); elseif (!is_array($selected)) $selected = array($selected); $out = ''; if (!is_object($hookmanager)) { include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; $hookmanager = new HookManager($this->db); } // We search third parties $sql = "SELECT sp.rowid, sp.lastname, sp.statut, sp.firstname, sp.poste"; if ($showsoc > 0) $sql .= " , s.nom as company"; $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as sp"; if ($showsoc > 0) $sql .= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid=sp.fk_soc"; $sql .= " WHERE sp.entity IN (".getEntity('socpeople').")"; if ($socid > 0 || $socid == -1) $sql .= " AND sp.fk_soc=".$socid; if (!empty($conf->global->CONTACT_HIDE_INACTIVE_IN_COMBOBOX)) $sql .= " AND sp.statut <> 0"; $sql .= " ORDER BY sp.lastname ASC"; dol_syslog(get_class($this)."::select_contacts", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); if ($conf->use_javascript_ajax && !$forcecombo && !$options_only) { include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlid, $events, $conf->global->CONTACT_USE_SEARCH_TO_SELECT); } if ($htmlname != 'none' && !$options_only) $out .= ''; } $this->num = $num; return $out; } else { dol_print_error($this->db); return -1; } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return the HTML select list of users * * @param string $selected Id user preselected * @param string $htmlname Field name in form * @param int $show_empty 0=liste sans valeur nulle, 1=ajoute valeur inconnue * @param array $exclude Array list of users id to exclude * @param int $disabled If select list must be disabled * @param array|string $include Array list of users id to include. User '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me * @param int $enableonly Array list of users id to be enabled. All other must be disabled * @param string $force_entity '0' or Ids of environment to force * @return void * @deprecated Use select_dolusers instead * @see select_dolusers() */ public function select_users($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '0') { // phpcs:enable print $this->select_dolusers($selected, $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return select list of users * * @param string $selected User id or user object of user preselected. If 0 or < -2, we use id of current user. If -1, keep unselected (if empty is allowed) * @param string $htmlname Field name in form * @param int $show_empty 0=list with no empty value, 1=add also an empty value into list * @param array $exclude Array list of users id to exclude * @param int $disabled If select list must be disabled * @param array|string $include Array list of users id to include. User '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me * @param array $enableonly Array list of users id to be enabled. If defined, it means that others will be disabled * @param string $force_entity '0' or Ids of environment to force * @param int $maxlength Maximum length of string into list (0=no limit) * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status * @param string $morefilter Add more filters into sql request (Example: 'employee = 1') * @param integer $show_every 0=default list, 1=add also a value "Everybody" at beginning of list * @param string $enableonlytext If option $enableonlytext is set, we use this text to explain into label why record is disabled. Not used if enableonly is empty. * @param string $morecss More css * @param int $noactive Show only active users (this will also happened whatever is this option if USER_HIDE_INACTIVE_IN_COMBOBOX is on). * @param int $outputmode 0=HTML select string, 1=Array * @param bool $multiple add [] in the name of element and add 'multiple' attribut * @return string HTML select string * @see select_dolgroups() */ public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $show_every = 0, $enableonlytext = '', $morecss = '', $noactive = 0, $outputmode = 0, $multiple = false) { // phpcs:enable global $conf, $user, $langs, $hookmanager; // If no preselected user defined, we take current user if ((is_numeric($selected) && ($selected < -2 || empty($selected))) && empty($conf->global->SOCIETE_DISABLE_DEFAULT_SALESREPRESENTATIVE)) $selected = $user->id; if ($selected === '') $selected = array(); elseif (!is_array($selected)) $selected = array($selected); $excludeUsers = null; $includeUsers = null; // Permettre l'exclusion d'utilisateurs if (is_array($exclude)) $excludeUsers = implode(",", $exclude); // Permettre l'inclusion d'utilisateurs if (is_array($include)) $includeUsers = implode(",", $include); elseif ($include == 'hierarchy') { // Build list includeUsers to have only hierarchy $includeUsers = implode(",", $user->getAllChildIds(0)); } elseif ($include == 'hierarchyme') { // Build list includeUsers to have only hierarchy and current user $includeUsers = implode(",", $user->getAllChildIds(1)); } $out = ''; $outarray = array(); // Forge request to select users $sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut, u.login, u.admin, u.entity"; if (!empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && !$user->entity) { $sql .= ", e.label"; } $sql .= " FROM ".MAIN_DB_PREFIX."user as u"; if (!empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && !$user->entity) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."entity as e ON e.rowid=u.entity"; if ($force_entity) $sql .= " WHERE u.entity IN (0,".$force_entity.")"; else $sql .= " WHERE u.entity IS NOT NULL"; } else { if (!empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."usergroup_user as ug"; $sql .= " ON ug.fk_user = u.rowid"; $sql .= " WHERE ug.entity = ".$conf->entity; } else { $sql .= " WHERE u.entity IN (0,".$conf->entity.")"; } } if (!empty($user->socid)) $sql .= " AND u.fk_soc = ".$user->socid; if (is_array($exclude) && $excludeUsers) $sql .= " AND u.rowid NOT IN (".$excludeUsers.")"; if ($includeUsers) $sql .= " AND u.rowid IN (".$includeUsers.")"; if (!empty($conf->global->USER_HIDE_INACTIVE_IN_COMBOBOX) || $noactive) $sql .= " AND u.statut <> 0"; if (!empty($morefilter)) $sql .= " ".$morefilter; //Add hook to filter on user (for exemple on usergroup define in custom modules) $reshook = $hookmanager->executeHooks('addSQLWhereFilterOnSelectUsers', array(), $this, $action); if (!empty($reshook)) $sql .= $hookmanager->resPrint; if (empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION)) // MAIN_FIRSTNAME_NAME_POSITION is 0 means firstname+lastname { $sql .= " ORDER BY u.firstname ASC"; } else { $sql .= " ORDER BY u.lastname ASC"; } dol_syslog(get_class($this)."::select_dolusers", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); $i = 0; if ($num) { // Enhance with select2 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname); // do not use maxwidthonsmartphone by default. Set it by caller so auto size to 100% will work when not defined $out .= ''; $out .= ''; } $out .= ''; } else { dol_print_error($this->db); } if ($outputmode) return $outarray; return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return select list of users. Selected users are stored into session. * List of users are provided into $_SESSION['assignedtouser']. * * @param string $action Value for $action * @param string $htmlname Field name in form * @param int $show_empty 0=list without the empty value, 1=add empty value * @param array $exclude Array list of users id to exclude * @param int $disabled If select list must be disabled * @param array $include Array list of users id to include or 'hierarchy' to have only supervised users * @param array $enableonly Array list of users id to be enabled. All other must be disabled * @param int $force_entity '0' or Ids of environment to force * @param int $maxlength Maximum length of string into list (0=no limit) * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status * @param string $morefilter Add more filters into sql request * @param int $showproperties Show properties of each attendees * @param array $listofuserid Array with properties of each user * @param array $listofcontactid Array with properties of each contact * @param array $listofotherid Array with properties of each other contact * @return string HTML select string * @see select_dolgroups() */ public function select_dolusers_forevent($action = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $showproperties = 0, $listofuserid = array(), $listofcontactid = array(), $listofotherid = array()) { // phpcs:enable global $conf, $user, $langs; $userstatic = new User($this->db); $out = ''; $assignedtouser = array(); if (!empty($_SESSION['assignedtouser'])) { $assignedtouser = json_decode($_SESSION['assignedtouser'], true); } $nbassignetouser = count($assignedtouser); //if ($nbassignetouser && $action != 'view') $out .= '
'; if ($nbassignetouser) $out .= '
    '; $i = 0; $ownerid = 0; foreach ($assignedtouser as $key => $value) { if ($value['id'] == $ownerid) continue; $out .= '
  • '; $userstatic->fetch($value['id']); $out .= $userstatic->getNomUrl(-1); if ($i == 0) { $ownerid = $value['id']; $out .= ' ('.$langs->trans("Owner").')'; } if ($nbassignetouser > 1 && $action != 'view') { $out .= ' '; } // Show my availability if ($showproperties) { if ($ownerid == $value['id'] && is_array($listofuserid) && count($listofuserid) && in_array($ownerid, array_keys($listofuserid))) { $out .= '
    '; $out .= ' - '.$langs->trans("Availability").': '.$langs->trans("Busy"); $out .= '
    '; } } //$out.=' '.($value['mandatory']?$langs->trans("Mandatory"):$langs->trans("Optional")); //$out.=' '.($value['transparency']?$langs->trans("Busy"):$langs->trans("NotBusy")); $out .= '
  • '; $i++; } if ($nbassignetouser) $out .= '
'; // Method with no ajax if ($action != 'view') { $out .= ''; $out .= ''; $out .= $this->select_dolusers('', $htmlname, $show_empty, $exclude, $disabled, $include, $enableonly, $force_entity, $maxlength, $showstatus, $morefilter); $out .= ' '; $out .= '
'; } return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of products for customer in Ajax if Ajax activated or go to select_produits_list * * @param int $selected Preselected products * @param string $htmlname Name of HTML select field (must be unique in page) * @param int $filtertype Filter on product type (''=nofilter, 0=product, 1=service) * @param int $limit Limit on number of returned lines * @param int $price_level Level of price to show * @param int $status Sell status -1=Return all products, 0=Products not on sell, 1=Products on sell * @param int $finished 2=all, 1=finished, 0=raw material * @param string $selected_input_value Value of preselected input text (for use with ajax) * @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after) * @param array $ajaxoptions Options for ajax_autocompleter * @param int $socid Thirdparty Id (to get also price dedicated to this customer) * @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. * @param int $forcecombo Force to use combo box * @param string $morecss Add more css on select * @param int $hidepriceinlabel 1=Hide prices in label * @param string $warehouseStatus Warehouse status filter to count the quantity in stock. Following comma separated filter options can be used * 'warehouseopen' = count products from open warehouses, * 'warehouseclosed' = count products from closed warehouses, * 'warehouseinternal' = count products from warehouses for internal correct/transfer only * @param array $selected_combinations Selected combinations. Format: array([attrid] => attrval, [...]) * @param string $nooutput No print, return the output into a string * @return void|string */ public function select_produits($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $status = 1, $finished = 2, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '', $selected_combinations = array(), $nooutput = 0) { // phpcs:enable global $langs, $conf; $out = ''; // check parameters $price_level = (!empty($price_level) ? $price_level : 0); if (is_null($ajaxoptions)) $ajaxoptions = array(); if (strval($filtertype) === '' && (!empty($conf->product->enabled) || !empty($conf->service->enabled))) { if (!empty($conf->product->enabled) && empty($conf->service->enabled)) { $filtertype = '0'; } elseif (empty($conf->product->enabled) && !empty($conf->service->enabled)) { $filtertype = '1'; } } if (!empty($conf->use_javascript_ajax) && !empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) { $placeholder = ''; if ($selected && empty($selected_input_value)) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; $producttmpselect = new Product($this->db); $producttmpselect->fetch($selected); $selected_input_value = $producttmpselect->ref; unset($producttmpselect); } // handle case where product or service module is disabled + no filter specified if ($filtertype == '') { if (empty($conf->product->enabled)) { // when product module is disabled, show services only $filtertype = 1; } elseif (empty($conf->service->enabled)) { // when service module is disabled, show products only $filtertype = 0; } } // mode=1 means customers products $urloption = 'htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&finished='.$finished.'&hidepriceinlabel='.$hidepriceinlabel.'&warehousestatus='.$warehouseStatus; //Price by customer if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $urloption .= '&socid='.$socid; } $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions); if (!empty($conf->variants->enabled)) { $out .= ' '; } if (empty($hidelabel)) $out .= $langs->trans("RefOrLabel").' : '; elseif ($hidelabel > 1) { $placeholder = ' placeholder="'.$langs->trans("RefOrLabel").'"'; if ($hidelabel == 2) { $out .= img_picto($langs->trans("Search"), 'search'); } } $out .= 'global->PRODUCT_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />'; if ($hidelabel == 3) { $out .= img_picto($langs->trans("Search"), 'search'); } } else { $out .= $this->select_produits_list($selected, $htmlname, $filtertype, $limit, $price_level, '', $status, $finished, 0, $socid, $showempty, $forcecombo, $morecss, $hidepriceinlabel, $warehouseStatus); } if (empty($nooutput)) print $out; else return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of products for a customer. * Called by select_produits. * * @param int $selected Preselected product * @param string $htmlname Name of select html * @param string $filtertype Filter on product type (''=nofilter, 0=product, 1=service) * @param int $limit Limit on number of returned lines * @param int $price_level Level of price to show * @param string $filterkey Filter on product * @param int $status -1=Return all products, 0=Products not on sell, 1=Products on sell * @param int $finished Filter on finished field: 2=No filter * @param int $outputmode 0=HTML select string, 1=Array * @param int $socid Thirdparty Id (to get also price dedicated to this customer) * @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. * @param int $forcecombo Force to use combo box * @param string $morecss Add more css on select * @param int $hidepriceinlabel 1=Hide prices in label * @param string $warehouseStatus Warehouse status filter to group/count stock. Following comma separated filter options can be used. * 'warehouseopen' = count products from open warehouses, * 'warehouseclosed' = count products from closed warehouses, * 'warehouseinternal' = count products from warehouses for internal correct/transfer only * @return array Array of keys for json */ public function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '') { // phpcs:enable global $langs, $conf, $user, $db; $out = ''; $outarray = array(); // Units if ($conf->global->PRODUCT_USE_UNITS) { $langs->load('other'); } $warehouseStatusArray = array(); if (!empty($warehouseStatus)) { require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; if (preg_match('/warehouseclosed/', $warehouseStatus)) { $warehouseStatusArray[] = Entrepot::STATUS_CLOSED; } if (preg_match('/warehouseopen/', $warehouseStatus)) { $warehouseStatusArray[] = Entrepot::STATUS_OPEN_ALL; } if (preg_match('/warehouseinternal/', $warehouseStatus)) { $warehouseStatusArray[] = Entrepot::STATUS_OPEN_INTERNAL; } } $selectFields = " p.rowid, p.ref, p.label, p.description, p.barcode, p.fk_country, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.duration, p.fk_price_expression"; if (count($warehouseStatusArray)) { $selectFieldsGrouped = ", sum(".$this->db->ifsql("e.statut IS NULL", "0", "ps.reel").") as stock"; // e.statut is null if there is no record in stock } else { $selectFieldsGrouped = ", ".$this->db->ifsql("p.stock IS NULL", 0, "p.stock")." AS stock"; } $sql = "SELECT "; $sql .= $selectFields.$selectFieldsGrouped; if (!empty($conf->global->PRODUCT_SORT_BY_CATEGORY)) { //Product category $sql .= ", (SELECT ".MAIN_DB_PREFIX."categorie_product.fk_categorie FROM ".MAIN_DB_PREFIX."categorie_product WHERE ".MAIN_DB_PREFIX."categorie_product.fk_product=p.rowid LIMIT 1 ) AS categorie_product_id "; } //Price by customer if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $sql .= ', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,'; $sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx'; $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx"; } // Units if (!empty($conf->global->PRODUCT_USE_UNITS)) { $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units"; $selectFields .= ', unit_long, unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units'; } // Multilang : we add translation if (!empty($conf->global->MAIN_MULTILANGS)) { $sql .= ", pl.label as label_translated"; $selectFields .= ", label_translated"; } // Price by quantity if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) { $sql .= ", (SELECT pp.rowid FROM ".MAIN_DB_PREFIX."product_price as pp WHERE pp.fk_product = p.rowid"; if ($price_level >= 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) $sql .= " AND price_level=".$price_level; $sql .= " ORDER BY date_price"; $sql .= " DESC LIMIT 1) as price_rowid"; $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 if ($price_level >= 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) $sql .= " AND price_level=".$price_level; $sql .= " ORDER BY date_price"; $sql .= " DESC LIMIT 1) as price_by_qty"; $selectFields .= ", price_rowid, price_by_qty"; } $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; if (count($warehouseStatusArray)) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps on ps.fk_product = p.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (".getEntity('stock').")"; $sql .= ' AND e.statut IN ('.$this->db->sanitize($this->db->escape(implode(',', $warehouseStatusArray))).')'; // Return line if product is inside the selected stock. If not, an empty line will be returned so we will count 0. } // include search in supplier ref if (!empty($conf->global->MAIN_SEARCH_PRODUCT_BY_FOURN_REF)) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product"; } //Price by customer if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_customer_price as pcp ON pcp.fk_soc=".$socid." AND pcp.fk_product=p.rowid"; } // Units if (!empty($conf->global->PRODUCT_USE_UNITS)) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_units u ON u.rowid = p.fk_unit"; } // Multilang : we add translation if (!empty($conf->global->MAIN_MULTILANGS)) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND pl.lang='".$this->db->escape($langs->getDefaultLang())."'"; } if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination pac ON pac.fk_product_child = p.rowid"; } $sql .= ' WHERE p.entity IN ('.getEntity('product').')'; if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) { $sql .= " AND pac.rowid IS NULL"; } if ($finished == 0) { $sql .= " AND p.finished = ".$finished; } elseif ($finished == 1) { $sql .= " AND p.finished = ".$finished; if ($status >= 0) $sql .= " AND p.tosell = ".$status; } elseif ($status >= 0) { $sql .= " AND p.tosell = ".$status; } // Filter by product type if (strval($filtertype) != '') $sql .= " AND p.fk_product_type = ".$filtertype; elseif (empty($conf->product->enabled)) { // when product module is disabled, show services only $sql .= " AND p.fk_product_type = 1"; } elseif (empty($conf->service->enabled)) { // when service module is disabled, show products only $sql .= " AND p.fk_product_type = 0"; } // Add criteria on ref/label if ($filterkey != '') { $sql .= ' AND ('; $prefix = empty($conf->global->PRODUCT_DONOTSEARCH_ANYWHERE) ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on // For natural search $scrit = explode(' ', $filterkey); $i = 0; if (count($scrit) > 1) $sql .= "("; foreach ($scrit as $crit) { if ($i > 0) $sql .= " AND "; $sql .= "(p.ref LIKE '".$this->db->escape($prefix.$crit)."%' OR p.label LIKE '".$this->db->escape($prefix.$crit)."%'"; if (!empty($conf->global->MAIN_MULTILANGS)) $sql .= " OR pl.label LIKE '".$this->db->escape($prefix.$crit)."%'"; if (!empty($conf->global->PRODUCT_AJAX_SEARCH_ON_DESCRIPTION)) { $sql .= " OR p.description LIKE '".$this->db->escape($prefix.$crit)."%'"; if (!empty($conf->global->MAIN_MULTILANGS)) $sql .= " OR pl.description LIKE '".$this->db->escape($prefix.$crit)."%'"; } if (!empty($conf->global->MAIN_SEARCH_PRODUCT_BY_FOURN_REF)) $sql .= " OR pfp.ref_fourn LIKE '".$this->db->escape($prefix.$crit)."%'"; $sql .= ")"; $i++; } if (count($scrit) > 1) $sql .= ")"; if (!empty($conf->barcode->enabled)) $sql .= " OR p.barcode LIKE '".$this->db->escape($prefix.$filterkey)."%'"; $sql .= ')'; } if (count($warehouseStatusArray)) { $sql .= ' GROUP BY'.$selectFields; } //Sort by category if (!empty($conf->global->PRODUCT_SORT_BY_CATEGORY)) { $sql .= " ORDER BY categorie_product_id "; //ASC OR DESC order ($conf->global->PRODUCT_SORT_BY_CATEGORY == 1) ? $sql .= "ASC" : $sql .= "DESC"; } else { $sql .= $this->db->order("p.ref"); } $sql .= $this->db->plimit($limit, 0); // Build output string dol_syslog(get_class($this)."::select_produits_list search products", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; $num = $this->db->num_rows($result); $events = null; if (!$forcecombo) { include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname, $events, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT); } $out .= ''; $this->db->free($result); if (empty($outputmode)) return $out; return $outarray; } else { dol_print_error($db); } } /** * constructProductListOption. * This define value for &$opt and &$optJson. * * @param resource $objp Resultset of fetch * @param string $opt Option (var used for returned value in string option format) * @param string $optJson Option (var used for returned value in json format) * @param int $price_level Price level * @param string $selected Preselected value * @param int $hidepriceinlabel Hide price in label * @param string $filterkey Filter key to highlight * @param int $novirtualstock Do not load virtual stock, even if slow option STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO is on. * @return void */ protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_level, $selected, $hidepriceinlabel = 0, $filterkey = '', $novirtualstock = 0) { global $langs, $conf, $user, $db; $outkey = ''; $outval = ''; $outref = ''; $outlabel = ''; $outdesc = ''; $outbarcode = ''; $outorigin = ''; $outtype = ''; $outprice_ht = ''; $outprice_ttc = ''; $outpricebasetype = ''; $outtva_tx = ''; $outqty = 1; $outdiscount = 0; $maxlengtharticle = (empty($conf->global->PRODUCT_MAX_LENGTH_COMBO) ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO); $label = $objp->label; if (!empty($objp->label_translated)) $label = $objp->label_translated; if (!empty($filterkey) && $filterkey != '') $label = preg_replace('/('.preg_quote($filterkey, '/').')/i', '$1', $label, 1); $outkey = $objp->rowid; $outref = $objp->ref; $outlabel = $objp->label; $outdesc = $objp->description; $outbarcode = $objp->barcode; $outorigin = $objp->fk_country; $outpbq = empty($objp->price_by_qty_rowid) ? '' : $objp->price_by_qty_rowid; $outtype = $objp->fk_product_type; $outdurationvalue = $outtype == Product::TYPE_SERVICE ?substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : ''; $outdurationunit = $outtype == Product::TYPE_SERVICE ?substr($objp->duration, -1) : ''; if ($outorigin && !empty($conf->global->PRODUCT_SHOW_ORIGIN_IN_COMBO)) require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; // Units $outvalUnits = ''; if (!empty($conf->global->PRODUCT_USE_UNITS)) { if (!empty($objp->unit_short)) { $outvalUnits .= ' - '.$objp->unit_short; } } if (!empty($conf->global->PRODUCT_SHOW_DIMENSIONS_IN_COMBO)) { if (!empty($objp->weight) && $objp->weight_units !== null) { $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs); $outvalUnits .= ' - '.$unitToShow; } if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) { $unitToShow = $objp->length.' x '.$objp->width.' x '.$objp->height.' '.measuringUnitString(0, 'size', $objp->length_units); $outvalUnits .= ' - '.$unitToShow; } if (!empty($objp->surface) && $objp->surface_units !== null) { $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs); $outvalUnits .= ' - '.$unitToShow; } if (!empty($objp->volume) && $objp->volume_units !== null) { $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs); $outvalUnits .= ' - '.$unitToShow; } } if ($outdurationvalue && $outdurationunit) { $da = array( 'h' => $langs->trans('Hour'), 'd' => $langs->trans('Day'), 'w' => $langs->trans('Week'), 'm' => $langs->trans('Month'), 'y' => $langs->trans('Year') ); if (isset($da[$outdurationunit])) { $outvalUnits .= ' - '.$outdurationvalue.' '.$langs->transnoentities($da[$outdurationunit].($outdurationvalue > 1 ? 's' : '')); } } $opt = '\n"; $optJson = array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'label2'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>price2num($outprice_ht), 'price_ttc'=>price2num($outprice_ttc), 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, 'discount'=>$outdiscount, 'duration_value'=>$outdurationvalue, 'duration_unit'=>$outdurationunit, 'pbq'=>$outpbq); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of products for customer (in Ajax if Ajax activated or go to select_produits_fournisseurs_list) * * @param int $socid Id third party * @param string $selected Preselected product * @param string $htmlname Name of HTML Select * @param string $filtertype Filter on product type (''=nofilter, 0=product, 1=service) * @param string $filtre For a SQL filter * @param array $ajaxoptions Options for ajax_autocompleter * @param int $hidelabel Hide label (0=no, 1=yes) * @param int $alsoproductwithnosupplierprice 1=Add also product without supplier prices * @param string $morecss More CSS * @return void */ public function select_produits_fournisseurs($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $ajaxoptions = array(), $hidelabel = 0, $alsoproductwithnosupplierprice = 0, $morecss = '') { // phpcs:enable global $langs, $conf; global $price_level, $status, $finished; $selected_input_value = ''; if (!empty($conf->use_javascript_ajax) && !empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) { if ($selected > 0) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; $producttmpselect = new Product($this->db); $producttmpselect->fetch($selected); $selected_input_value = $producttmpselect->ref; unset($producttmpselect); } // mode=2 means suppliers products $urloption = ($socid > 0 ? 'socid='.$socid.'&' : '').'htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=2&status='.$status.'&finished='.$finished.'&alsoproductwithnosupplierprice='.$alsoproductwithnosupplierprice; print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions); print ($hidelabel ? '' : $langs->trans("RefOrLabel").' : ').''; } else { print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', -1, 0, 0, $alsoproductwithnosupplierprice, $morecss); } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of suppliers products * * @param int $socid Id societe fournisseur (0 pour aucun filtre) * @param int $selected Product price pre-selected (must be 'id' in product_fournisseur_price or 'idprod_IDPROD') * @param string $htmlname Nom de la zone select * @param string $filtertype Filter on product type (''=nofilter, 0=product, 1=service) * @param string $filtre Pour filtre sql * @param string $filterkey Filtre des produits * @param int $statut -1=Return all products, 0=Products not on sell, 1=Products on sell (not used here, a filter on tobuy is already hard coded in request) * @param int $outputmode 0=HTML select string, 1=Array * @param int $limit Limit of line number * @param int $alsoproductwithnosupplierprice 1=Add also product without supplier prices * @param string $morecss Add more CSS * @return array Array of keys for json */ public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '') { // phpcs:enable global $langs, $conf, $db; $out = ''; $outarray = array(); $maxlengtharticle = (empty($conf->global->PRODUCT_MAX_LENGTH_COMBO) ? 48 : $conf->global->PRODUCT_MAX_LENGTH_COMBO); $langs->load('stocks'); // Units if ($conf->global->PRODUCT_USE_UNITS) { $langs->load('other'); } $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, p.fk_product_type,"; $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.quantity, pfp.remise_percent, pfp.remise, pfp.unitprice,"; $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, pfp.fk_soc, s.nom as name,"; $sql .= " pfp.supplier_reputation"; // Units if ($conf->global->PRODUCT_USE_UNITS) { $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units"; } if (!empty($conf->barcode->enabled)) $sql .= ", pfp.barcode"; $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON ( p.rowid = pfp.fk_product AND pfp.entity IN (".getEntity('product').") )"; if ($socid) $sql .= " AND pfp.fk_soc = ".$socid; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON pfp.fk_soc = s.rowid"; // Units if ($conf->global->PRODUCT_USE_UNITS) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_units u ON u.rowid = p.fk_unit"; } $sql .= " WHERE p.entity IN (".getEntity('product').")"; $sql .= " AND p.tobuy = 1"; if (strval($filtertype) != '') $sql .= " AND p.fk_product_type=".$this->db->escape($filtertype); if (!empty($filtre)) $sql .= " ".$filtre; // Add criteria on ref/label if ($filterkey != '') { $sql .= ' AND ('; $prefix = empty($conf->global->PRODUCT_DONOTSEARCH_ANYWHERE) ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on // For natural search $scrit = explode(' ', $filterkey); $i = 0; if (count($scrit) > 1) $sql .= "("; foreach ($scrit as $crit) { if ($i > 0) $sql .= " AND "; $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)."%')"; $i++; } if (count($scrit) > 1) $sql .= ")"; if (!empty($conf->barcode->enabled)) { $sql .= " OR p.barcode LIKE '".$this->db->escape($prefix.$filterkey)."%'"; $sql .= " OR pfp.barcode LIKE '".$this->db->escape($prefix.$filterkey)."%'"; } $sql .= ')'; } $sql .= " ORDER BY pfp.ref_fourn DESC, pfp.quantity ASC"; $sql .= $this->db->plimit($limit, 0); // Build output string dol_syslog(get_class($this)."::select_produits_fournisseurs_list", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; $num = $this->db->num_rows($result); //$out.=''; if (!$selected) $out .= ''; else $out .= ''; $i = 0; while ($i < $num) { $objp = $this->db->fetch_object($result); $outkey = $objp->idprodfournprice; // id in table of price if (!$outkey && $alsoproductwithnosupplierprice) $outkey = 'idprod_'.$objp->rowid; // id of product $outref = $objp->ref; $outval = ''; $outbarcode = $objp->barcode; $outqty = 1; $outdiscount = 0; $outtype = $objp->fk_product_type; $outdurationvalue = $outtype == Product::TYPE_SERVICE ?substr($objp->duration, 0, dol_strlen($objp->duration) - 1) : ''; $outdurationunit = $outtype == Product::TYPE_SERVICE ?substr($objp->duration, -1) : ''; // Units $outvalUnits = ''; if ($conf->global->PRODUCT_USE_UNITS) { if (!empty($objp->unit_short)) { $outvalUnits .= ' - '.$objp->unit_short; } if (!empty($objp->weight) && $objp->weight_units !== null) { $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs); $outvalUnits .= ' - '.$unitToShow; } if ((!empty($objp->length) || !empty($objp->width) || !empty($objp->height)) && $objp->length_units !== null) { $unitToShow = $objp->length.' x '.$objp->width.' x '.$objp->height.' '.measuringUnitString(0, 'size', $objp->length_units); $outvalUnits .= ' - '.$unitToShow; } if (!empty($objp->surface) && $objp->surface_units !== null) { $unitToShow = showDimensionInBestUnit($objp->surface, $objp->surface_units, 'surface', $langs); $outvalUnits .= ' - '.$unitToShow; } if (!empty($objp->volume) && $objp->volume_units !== null) { $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs); $outvalUnits .= ' - '.$unitToShow; } if ($outdurationvalue && $outdurationunit) { $da = array( 'h' => $langs->trans('Hour'), 'd' => $langs->trans('Day'), 'w' => $langs->trans('Week'), 'm' => $langs->trans('Month'), 'y' => $langs->trans('Year') ); if (isset($da[$outdurationunit])) { $outvalUnits .= ' - '.$outdurationvalue.' '.$langs->transnoentities($da[$outdurationunit].($outdurationvalue > 1 ? 's' : '')); } } } $objRef = $objp->ref; if ($filterkey && $filterkey != '') $objRef = preg_replace('/('.preg_quote($filterkey, '/').')/i', '$1', $objRef, 1); $objRefFourn = $objp->ref_fourn; if ($filterkey && $filterkey != '') $objRefFourn = preg_replace('/('.preg_quote($filterkey, '/').')/i', '$1', $objRefFourn, 1); $label = $objp->label; if ($filterkey && $filterkey != '') $label = preg_replace('/('.preg_quote($filterkey, '/').')/i', '$1', $label, 1); $optlabel = $objp->ref; if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) { $optlabel .= ' ('.$objp->ref_fourn.')'; } if (!empty($conf->barcode->enabled) && !empty($objp->barcode)) { $optlabel .= ' ('.$outbarcode.')'; } $optlabel .= ' - '.dol_trunc($label, $maxlengtharticle); $outvallabel = $objRef; if (!empty($objp->idprodfournprice) && ($objp->ref != $objp->ref_fourn)) { $outvallabel .= ' ('.$objRefFourn.')'; } if (!empty($conf->barcode->enabled) && !empty($objp->barcode)) { $outvallabel .= ' ('.$outbarcode.')'; } $outvallabel .= ' - '.dol_trunc($label, $maxlengtharticle); // Units $optlabel .= $outvalUnits; $outvallabel .= $outvalUnits; if (!empty($objp->idprodfournprice)) { $outqty = $objp->quantity; $outdiscount = $objp->remise_percent; if (!empty($conf->dynamicprices->enabled) && !empty($objp->fk_supplier_price_expression)) { $prod_supplier = new ProductFournisseur($this->db); $prod_supplier->product_fourn_price_id = $objp->idprodfournprice; $prod_supplier->id = $objp->fk_product; $prod_supplier->fourn_qty = $objp->quantity; $prod_supplier->fourn_tva_tx = $objp->tva_tx; $prod_supplier->fk_supplier_price_expression = $objp->fk_supplier_price_expression; $priceparser = new PriceParser($this->db); $price_result = $priceparser->parseProductSupplier($prod_supplier); if ($price_result >= 0) { $objp->fprice = $price_result; if ($objp->quantity >= 1) { $objp->unitprice = $objp->fprice / $objp->quantity; // Replace dynamically unitprice } } } if ($objp->quantity == 1) { $optlabel .= ' - '.price($objp->fprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE) ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency)."/"; $outvallabel .= ' - '.price($objp->fprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE) ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency)."/"; $optlabel .= $langs->trans("Unit"); // Do not use strtolower because it breaks utf8 encoding $outvallabel .= $langs->transnoentities("Unit"); } else { $optlabel .= ' - '.price($objp->fprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE) ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency)."/".$objp->quantity; $outvallabel .= ' - '.price($objp->fprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE) ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency)."/".$objp->quantity; $optlabel .= ' '.$langs->trans("Units"); // Do not use strtolower because it breaks utf8 encoding $outvallabel .= ' '.$langs->transnoentities("Units"); } if ($objp->quantity > 1) { $optlabel .= " (".price($objp->unitprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE) ? (1 - $objp->remise_percent / 100) : 1), 1, $langs, 0, 0, -1, $conf->currency)."/".$langs->trans("Unit").")"; // Do not use strtolower because it breaks utf8 encoding $outvallabel .= " (".price($objp->unitprice * (!empty($conf->global->DISPLAY_DISCOUNTED_SUPPLIER_PRICE) ? (1 - $objp->remise_percent / 100) : 1), 0, $langs, 0, 0, -1, $conf->currency)."/".$langs->transnoentities("Unit").")"; // Do not use strtolower because it breaks utf8 encoding } if ($objp->remise_percent >= 1) { $optlabel .= " - ".$langs->trans("Discount")." : ".vatrate($objp->remise_percent).' %'; $outvallabel .= " - ".$langs->transnoentities("Discount")." : ".vatrate($objp->remise_percent).' %'; } if ($objp->duration) { $optlabel .= " - ".$objp->duration; $outvallabel .= " - ".$objp->duration; } if (!$socid) { $optlabel .= " - ".dol_trunc($objp->name, 8); $outvallabel .= " - ".dol_trunc($objp->name, 8); } if ($objp->supplier_reputation) { //TODO dictionary $reputations = array(''=>$langs->trans('Standard'), 'FAVORITE'=>$langs->trans('Favorite'), 'NOTTHGOOD'=>$langs->trans('NotTheGoodQualitySupplier'), 'DONOTORDER'=>$langs->trans('DoNotOrderThisProductToThisSupplier')); $optlabel .= " - ".$reputations[$objp->supplier_reputation]; $outvallabel .= " - ".$reputations[$objp->supplier_reputation]; } } else { if (empty($alsoproductwithnosupplierprice)) // No supplier price defined for couple product/supplier { $optlabel .= " - ".$langs->trans("NoPriceDefinedForThisSupplier").''; $outvallabel .= ' - '.$langs->transnoentities("NoPriceDefinedForThisSupplier"); } else // No supplier price defined for product, even on other suppliers { $optlabel .= " - ".$langs->trans("NoPriceDefinedForThisSupplier").''; $outvallabel .= ' - '.$langs->transnoentities("NoPriceDefinedForThisSupplier"); } } $opt = '\n"; // Add new entry // "key" value of json key array is used by jQuery automatically as selected value // "label" value of json key array is used by jQuery automatically as text for combo box $out .= $opt; array_push($outarray, array('key'=>$outkey, 'value'=>$outref, 'label'=>$outval, 'qty'=>$outqty, 'up'=>$objp->unitprice, 'discount'=>$outdiscount, 'type'=>$outtype, 'duration_value'=>$outdurationvalue, 'duration_unit'=>$outdurationunit, 'disabled'=>(empty($objp->idprodfournprice) ?true:false))); // Exemple of var_dump $outarray // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp" // ["label"]=>string(76) "ppp (fff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)" // ["qty"]=>string(1) "1" ["discount"]=>string(1) "0" ["disabled"]=>bool(false) //} //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval)); //$outval=array('label'=>'ppp (fff2) - ppp - 20,00 Euros/ Unité (20,00 Euros/unité)'); //var_dump($outval); var_dump(utf8_check($outval)); var_dump(json_encode($outval)); $i++; } $out .= ''; $this->db->free($result); include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname); if (empty($outputmode)) return $out; return $outarray; } else { dol_print_error($this->db); } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of suppliers prices for a product * * @param int $productid Id of product * @param string $htmlname Name of HTML field * @param int $selected_supplier Pre-selected supplier if more than 1 result * @return string */ public function select_product_fourn_price($productid, $htmlname = 'productfournpriceid', $selected_supplier = '') { // phpcs:enable global $langs, $conf; $langs->load('stocks'); $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, pfp.fk_soc,"; $sql .= " pfp.ref_fourn, pfp.rowid as idprodfournprice, pfp.price as fprice, pfp.remise_percent, pfp.quantity, pfp.unitprice,"; $sql .= " pfp.fk_supplier_price_expression, pfp.fk_product, pfp.tva_tx, s.nom as name"; $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON pfp.fk_soc = s.rowid"; $sql .= " WHERE pfp.entity IN (".getEntity('productsupplierprice').")"; $sql .= " AND p.tobuy = 1"; $sql .= " AND s.fournisseur = 1"; $sql .= " AND p.rowid = ".$productid; $sql .= " ORDER BY s.nom, pfp.ref_fourn DESC"; dol_syslog(get_class($this)."::select_product_fourn_price", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { $num = $this->db->num_rows($result); $form = ''; $this->db->free($result); return $form; } else { dol_print_error($this->db); } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of delivery address * * @param string $selected Id contact pre-selectionn * @param int $socid Id of company * @param string $htmlname Name of HTML field * @param int $showempty Add an empty field * @return integer|null */ public function select_address($selected, $socid, $htmlname = 'address_id', $showempty = 0) { // phpcs:enable // looking for users $sql = "SELECT a.rowid, a.label"; $sql .= " FROM ".MAIN_DB_PREFIX."societe_address as a"; $sql .= " WHERE a.fk_soc = ".$socid; $sql .= " ORDER BY a.label ASC"; dol_syslog(get_class($this)."::select_address", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { print ''; return $num; } else { dol_print_error($this->db); } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Load into cache list of payment terms * * @return int Nb of lines loaded, <0 if KO */ public function load_cache_conditions_paiements() { // phpcs:enable global $langs; $num = count($this->cache_conditions_paiements); if ($num > 0) return 0; // Cache already loaded dol_syslog(__METHOD__, LOG_DEBUG); $sql = "SELECT rowid, code, libelle as label"; $sql .= " FROM ".MAIN_DB_PREFIX.'c_payment_term'; $sql .= " WHERE entity IN (".getEntity('c_payment_term').")"; $sql .= " AND active > 0"; $sql .= " ORDER BY sortorder"; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); $i = 0; while ($i < $num) { $obj = $this->db->fetch_object($resql); // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut $label = ($langs->trans("PaymentConditionShort".$obj->code) != ("PaymentConditionShort".$obj->code) ? $langs->trans("PaymentConditionShort".$obj->code) : ($obj->label != '-' ? $obj->label : '')); $this->cache_conditions_paiements[$obj->rowid]['code'] = $obj->code; $this->cache_conditions_paiements[$obj->rowid]['label'] = $label; $i++; } //$this->cache_conditions_paiements=dol_sort_array($this->cache_conditions_paiements, 'label', 'asc', 0, 0, 1); // We use the field sortorder of table return $num; } else { dol_print_error($this->db); return -1; } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Charge dans cache la liste des délais de livraison possibles * * @return int Nb of lines loaded, <0 if KO */ public function load_cache_availability() { // phpcs:enable global $langs; $num = count($this->cache_availability); if ($num > 0) return 0; // Cache already loaded dol_syslog(__METHOD__, LOG_DEBUG); $langs->load('propal'); $sql = "SELECT rowid, code, label"; $sql .= " FROM ".MAIN_DB_PREFIX.'c_availability'; $sql .= " WHERE active > 0"; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); $i = 0; while ($i < $num) { $obj = $this->db->fetch_object($resql); // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut $label = ($langs->trans("AvailabilityType".$obj->code) != ("AvailabilityType".$obj->code) ? $langs->trans("AvailabilityType".$obj->code) : ($obj->label != '-' ? $obj->label : '')); $this->cache_availability[$obj->rowid]['code'] = $obj->code; $this->cache_availability[$obj->rowid]['label'] = $label; $i++; } $this->cache_availability = dol_sort_array($this->cache_availability, 'label', 'asc', 0, 0, 1); return $num; } else { dol_print_error($this->db); return -1; } } /** * Retourne la liste des types de delais de livraison possibles * * @param int $selected Id du type de delais pre-selectionne * @param string $htmlname Nom de la zone select * @param string $filtertype To add a filter * @param int $addempty Add empty entry * @return void */ public function selectAvailabilityDelay($selected = '', $htmlname = 'availid', $filtertype = '', $addempty = 0) { global $langs, $user; $this->load_cache_availability(); dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG); print ''; if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); } /** * Load into cache cache_demand_reason, array of input reasons * * @return int Nb of lines loaded, <0 if KO */ public function loadCacheInputReason() { global $langs; $num = count($this->cache_demand_reason); if ($num > 0) return 0; // Cache already loaded $sql = "SELECT rowid, code, label"; $sql .= " FROM ".MAIN_DB_PREFIX.'c_input_reason'; $sql .= " WHERE active > 0"; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); $i = 0; $tmparray = array(); while ($i < $num) { $obj = $this->db->fetch_object($resql); // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut $label = ($obj->label != '-' ? $obj->label : ''); if ($langs->trans("DemandReasonType".$obj->code) != ("DemandReasonType".$obj->code)) $label = $langs->trans("DemandReasonType".$obj->code); // So translation key DemandReasonTypeSRC_XXX will work if ($langs->trans($obj->code) != $obj->code) $label = $langs->trans($obj->code); // So translation key SRC_XXX will work $tmparray[$obj->rowid]['id'] = $obj->rowid; $tmparray[$obj->rowid]['code'] = $obj->code; $tmparray[$obj->rowid]['label'] = $label; $i++; } $this->cache_demand_reason = dol_sort_array($tmparray, 'label', 'asc', 0, 0, 1); unset($tmparray); return $num; } else { dol_print_error($this->db); return -1; } } /** * Return list of input reason (events that triggered an object creation, like after sending an emailing, making an advert, ...) * List found into table c_input_reason loaded by loadCacheInputReason * * @param int $selected Id or code of type origin to select by default * @param string $htmlname Nom de la zone select * @param string $exclude To exclude a code value (Example: SRC_PROP) * @param int $addempty Add an empty entry * @return void */ public function selectInputReason($selected = '', $htmlname = 'demandreasonid', $exclude = '', $addempty = 0) { global $langs, $user; $this->loadCacheInputReason(); print ''; if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Charge dans cache la liste des types de paiements possibles * * @return int Nb of lines loaded, <0 if KO */ public function load_cache_types_paiements() { // phpcs:enable global $langs; $num = count($this->cache_types_paiements); if ($num > 0) return $num; // Cache already loaded dol_syslog(__METHOD__, LOG_DEBUG); $this->cache_types_paiements = array(); $sql = "SELECT id, code, libelle as label, type, active"; $sql .= " FROM ".MAIN_DB_PREFIX."c_paiement"; $sql .= " WHERE entity IN (".getEntity('c_paiement').")"; //if ($active >= 0) $sql.= " AND active = ".$active; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); $i = 0; while ($i < $num) { $obj = $this->db->fetch_object($resql); // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut $label = ($langs->transnoentitiesnoconv("PaymentTypeShort".$obj->code) != ("PaymentTypeShort".$obj->code) ? $langs->transnoentitiesnoconv("PaymentTypeShort".$obj->code) : ($obj->label != '-' ? $obj->label : '')); $this->cache_types_paiements[$obj->id]['id'] = $obj->id; $this->cache_types_paiements[$obj->id]['code'] = $obj->code; $this->cache_types_paiements[$obj->id]['label'] = $label; $this->cache_types_paiements[$obj->id]['type'] = $obj->type; $this->cache_types_paiements[$obj->id]['active'] = $obj->active; $i++; } $this->cache_types_paiements = dol_sort_array($this->cache_types_paiements, 'label', 'asc', 0, 0, 1); return $num; } else { dol_print_error($this->db); return -1; } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of payment modes. * Constant MAIN_DEFAULT_PAYMENT_TERM_ID can used to set default value but scope is all application, probably not what you want. * See instead to force the default value by the caller. * * @param int $selected Id of payment term to preselect by default * @param string $htmlname Nom de la zone select * @param int $filtertype Not used * @param int $addempty Add an empty entry * @param int $noinfoadmin 0=Add admin info, 1=Disable admin info * @param string $morecss Add more CSS on select tag * @return void */ public function select_conditions_paiements($selected = 0, $htmlname = 'condid', $filtertype = -1, $addempty = 0, $noinfoadmin = 0, $morecss = '') { // phpcs:enable global $langs, $user, $conf; dol_syslog(__METHOD__." selected=".$selected.", htmlname=".$htmlname, LOG_DEBUG); $this->load_cache_conditions_paiements(); // Set default value if not already set by caller if (empty($selected) && !empty($conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID)) $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TERM_ID; print ''; if ($user->admin && empty($noinfoadmin)) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of payment methods * Constant MAIN_DEFAULT_PAYMENT_TYPE_ID can used to set default value but scope is all application, probably not what you want. * * @param string $selected Id or code or preselected payment mode * @param string $htmlname Name of select field * @param string $filtertype To filter on field type in llx_c_paiement ('CRDT' or 'DBIT' or array('code'=>xx,'label'=>zz)) * @param int $format 0=id+label, 1=code+code, 2=code+label, 3=id+code * @param int $empty 1=can be empty, 0 otherwise * @param int $noadmininfo 0=Add admin info, 1=Disable admin info * @param int $maxlength Max length of label * @param int $active Active or not, -1 = all * @param string $morecss Add more CSS on select tag * @return void */ public function select_types_paiements($selected = '', $htmlname = 'paiementtype', $filtertype = '', $format = 0, $empty = 1, $noadmininfo = 0, $maxlength = 0, $active = 1, $morecss = '') { // phpcs:enable global $langs, $user, $conf; dol_syslog(__METHOD__." ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG); $filterarray = array(); if ($filtertype == 'CRDT') $filterarray = array(0, 2, 3); elseif ($filtertype == 'DBIT') $filterarray = array(1, 2, 3); elseif ($filtertype != '' && $filtertype != '-1') $filterarray = explode(',', $filtertype); $this->load_cache_types_paiements(); // Set default value if not already set by caller if (empty($selected) && !empty($conf->global->MAIN_DEFAULT_PAYMENT_TYPE_ID)) $selected = $conf->global->MAIN_DEFAULT_PAYMENT_TYPE_ID; print ''; if ($user->admin && !$noadmininfo) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); } /** * Selection HT or TTC * * @param string $selected Id pre-selectionne * @param string $htmlname Nom de la zone select * @return string Code of HTML select to chose tax or not */ public function selectPriceBaseType($selected = '', $htmlname = 'price_base_type') { global $langs; $return = ''; $return .= ''; return $return; } /** * Return a HTML select list of shipping mode * * @param string $selected Id shipping mode pre-selected * @param string $htmlname Name of select zone * @param string $filtre To filter list * @param int $useempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. * @param string $moreattrib To add more attribute on select * @return void */ public function selectShippingMethod($selected = '', $htmlname = 'shipping_method_id', $filtre = '', $useempty = 0, $moreattrib = '') { global $langs, $conf, $user; $langs->load("admin"); $langs->load("deliveries"); $sql = "SELECT rowid, code, libelle as label"; $sql .= " FROM ".MAIN_DB_PREFIX."c_shipment_mode"; $sql .= " WHERE active > 0"; if ($filtre) $sql .= " AND ".$filtre; $sql .= " ORDER BY libelle ASC"; dol_syslog(get_class($this)."::selectShippingMode", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { $num = $this->db->num_rows($result); $i = 0; if ($num) { print '"; if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); } else { print $langs->trans("NoShippingMethodDefined"); } } else { dol_print_error($this->db); } } /** * Display form to select shipping mode * * @param string $page Page * @param int $selected Id of shipping mode * @param string $htmlname Name of select html field * @param int $addempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. * @return void */ public function formSelectShippingMethod($page, $selected = '', $htmlname = 'shipping_method_id', $addempty = 0) { global $langs, $db; $langs->load("deliveries"); if ($htmlname != "none") { print '
'; print ''; print ''; $this->selectShippingMethod($selected, $htmlname, '', $addempty); print ''; print '
'; } else { if ($selected) { $code = $langs->getLabelFromKey($db, $selected, 'c_shipment_mode', 'rowid', 'code'); print $langs->trans("SendingMethod".strtoupper($code)); } else { print " "; } } } /** * Creates HTML last in cycle situation invoices selector * * @param string $selected Preselected ID * @param int $socid Company ID * * @return string HTML select */ public function selectSituationInvoices($selected = '', $socid = 0) { global $langs; $langs->load('bills'); $opt = ''; $sql = 'SELECT rowid, ref, situation_cycle_ref, situation_counter, situation_final, fk_soc'; $sql .= ' FROM '.MAIN_DB_PREFIX.'facture'; $sql .= ' WHERE entity IN ('.getEntity('invoice').')'; $sql .= ' AND situation_counter >= 1'; $sql .= ' AND fk_soc = '.(int) $socid; $sql .= ' AND type <> 2'; $sql .= ' ORDER by situation_cycle_ref, situation_counter desc'; $resql = $this->db->query($sql); if ($resql && $this->db->num_rows($resql) > 0) { // Last seen cycle $ref = 0; while ($obj = $this->db->fetch_object($resql)) { //Same cycle ? if ($obj->situation_cycle_ref != $ref) { // Just seen this cycle $ref = $obj->situation_cycle_ref; //not final ? if ($obj->situation_final != 1) { //Not prov? if (substr($obj->ref, 1, 4) != 'PROV') { if ($selected == $obj->rowid) { $opt .= ''; } else { $opt .= ''; } } } } } } else { dol_syslog("Error sql=".$sql.", error=".$this->error, LOG_ERR); } if ($opt == '') { $opt = ''; } return $opt; } /** * Creates HTML units selector (code => label) * * @param string $selected Preselected Unit ID * @param string $htmlname Select name * @param int $showempty Add a nempty line * @return string HTML select */ public function selectUnits($selected = '', $htmlname = 'units', $showempty = 0) { global $langs; $langs->load('products'); $return = ''; } return $return; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return a HTML select list of bank accounts * * @param string $selected Id account pre-selected * @param string $htmlname Name of select zone * @param int $status Status of searched accounts (0=open, 1=closed, 2=both) * @param string $filtre To filter list * @param int $useempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. * @param string $moreattrib To add more attribute on select * @param int $showcurrency Show currency in label * @param string $morecss More CSS * @return int <0 if error, Num of bank account found if OK (0, 1, 2, ...) */ public function select_comptes($selected = '', $htmlname = 'accountid', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '', $showcurrency = 0, $morecss = '') { // phpcs:enable global $langs, $conf; $langs->load("admin"); $num = 0; $sql = "SELECT rowid, label, bank, clos as status, currency_code"; $sql .= " FROM ".MAIN_DB_PREFIX."bank_account"; $sql .= " WHERE entity IN (".getEntity('bank_account').")"; if ($status != 2) $sql .= " AND clos = ".(int) $status; if ($filtre) $sql .= " AND ".$filtre; $sql .= " ORDER BY label"; dol_syslog(get_class($this)."::select_comptes", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { $num = $this->db->num_rows($result); $i = 0; if ($num) { print '"; } else { if ($status == 0) print ''.$langs->trans("NoActiveBankAccountDefined").''; else print ''.$langs->trans("NoBankAccountFound").''; } } else { dol_print_error($this->db); } return $num; } /** * Return a HTML select list of establishment * * @param string $selected Id establishment pre-selected * @param string $htmlname Name of select zone * @param int $status Status of searched establishment (0=open, 1=closed, 2=both) * @param string $filtre To filter list * @param int $useempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. * @param string $moreattrib To add more attribute on select * @return int <0 if error, Num of establishment found if OK (0, 1, 2, ...) */ public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '') { // phpcs:enable global $langs, $conf; $langs->load("admin"); $num = 0; $sql = "SELECT rowid, name, fk_country, status, entity"; $sql .= " FROM ".MAIN_DB_PREFIX."establishment"; $sql .= " WHERE 1=1"; if ($status != 2) $sql .= " AND status = ".(int) $status; if ($filtre) $sql .= " AND ".$filtre; $sql .= " ORDER BY name"; dol_syslog(get_class($this)."::select_establishment", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { $num = $this->db->num_rows($result); $i = 0; if ($num) { print '"; } else { if ($status == 0) print ''.$langs->trans("NoActiveEstablishmentDefined").''; else print ''.$langs->trans("NoEstablishmentFound").''; } } else { dol_print_error($this->db); } } /** * Display form to select bank account * * @param string $page Page * @param int $selected Id of bank account * @param string $htmlname Name of select html field * @param int $addempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. * @return void */ public function formSelectAccount($page, $selected = '', $htmlname = 'fk_account', $addempty = 0) { global $langs; if ($htmlname != "none") { print '
'; print ''; print ''; $nbaccountfound = $this->select_comptes($selected, $htmlname, 0, '', $addempty); if ($nbaccountfound > 0) print ''; print '
'; } else { $langs->load('banks'); if ($selected) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $bankstatic = new Account($this->db); $result = $bankstatic->fetch($selected); if ($result) print $bankstatic->getNomUrl(1); } else { print " "; } } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of categories having choosed type * * @param string|int $type Type of category ('customer', 'supplier', 'contact', 'product', 'member'). Old mode (0, 1, 2, ...) is deprecated. * @param string $selected Id of category preselected or 'auto' (autoselect category if there is only one element). Not used if $outputmode = 1. * @param string $htmlname HTML field name * @param int $maxlength Maximum length for labels * @param int|string|array $markafterid Keep only or removed all categories including the leaf $markafterid in category tree (exclude) or Keep only of category is inside the leaf starting with this id. * $markafterid can be an : * - int (id of category) * - string (categories ids seprated by comma) * - array (list of categories ids) * @param int $outputmode 0=HTML select string, 1=Array * @param int $include [=0] Removed or 1=Keep only * @param string $morecss More CSS * @return string * @see select_categories() */ public function select_all_categories($type, $selected = '', $htmlname = "parent", $maxlength = 64, $markafterid = 0, $outputmode = 0, $include = 0, $morecss = '') { // phpcs:enable global $conf, $langs; $langs->load("categories"); include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; // For backward compatibility if (is_numeric($type)) { dol_syslog(__METHOD__.': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING); } if ($type === Categorie::TYPE_BANK_LINE) { // TODO Move this into common category feature $cate_arbo = array(); $sql = "SELECT c.label, c.rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."bank_categ as c"; $sql .= " WHERE entity = ".$conf->entity; $sql .= " ORDER BY c.label"; $result = $this->db->query($sql); if ($result) { $num = $this->db->num_rows($result); $i = 0; while ($i < $num) { $objp = $this->db->fetch_object($result); if ($objp) $cate_arbo[$objp->rowid] = array('id'=>$objp->rowid, 'fulllabel'=>$objp->label); $i++; } $this->db->free($result); } else dol_print_error($this->db); } else { $cat = new Categorie($this->db); $cate_arbo = $cat->get_full_arbo($type, $markafterid, $include); } $output = ''; $output .= "\n"; if ($outputmode) return $outarray; return $output; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show a confirmation HTML form or AJAX popup * * @param string $page Url of page to call if confirmation is OK * @param string $title Title * @param string $question Question * @param string $action Action * @param array $formquestion An array with forms complementary inputs * @param string $selectedchoice "" or "no" or "yes" * @param int $useajax 0=No, 1=Yes, 2=Yes but submit page with &confirm=no if choice is No, 'xxx'=preoutput confirm box with div id=dialog-confirm-xxx * @param int $height Force height of box * @param int $width Force width of box * @return void * @deprecated * @see formconfirm() */ public function form_confirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = "", $useajax = 0, $height = 170, $width = 500) { // phpcs:enable dol_syslog(__METHOD__.': using form_confirm is deprecated. Use formconfim instead.', LOG_WARNING); print $this->formconfirm($page, $title, $question, $action, $formquestion, $selectedchoice, $useajax, $height, $width); } /** * Show a confirmation HTML form or AJAX popup. * Easiest way to use this is with useajax=1. * If you use useajax='xxx', you must also add jquery code to trigger opening of box (with correct parameters) * just after calling this method. For example: * print ''."\n"; * * @param string $page Url of page to call if confirmation is OK. Can contains parameters (param 'action' and 'confirm' will be reformated) * @param string $title Title * @param string $question Question * @param string $action Action * @param array|string $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , )) * type can be 'hidden', 'text', 'password', 'checkbox', 'radio', 'date', 'morecss', ... * @param string $selectedchoice '' or 'no', or 'yes' or '1' or '0' * @param int|string $useajax 0=No, 1=Yes, 2=Yes but submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx * @param int|string $height Force height of box (0 = auto) * @param int $width Force width of box ('999' or '90%'). Ignored and forced to 90% on smartphones. * @param int $disableformtag 1=Disable form tag. Can be used if we are already inside a
section. * @return string HTML ajax code if a confirm ajax popup is required, Pure HTML code if it's an html form */ public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0) { global $langs, $conf; $more = ''; $formconfirm = ''; $inputok = array(); $inputko = array(); // Clean parameters $newselectedchoice = empty($selectedchoice) ? "no" : $selectedchoice; if ($conf->browser->layout == 'phone') $width = '95%'; // Set height automatically if not defined if (empty($height)) { $height = 220; if (is_array($formquestion) && count($formquestion) > 2) { $height += ((count($formquestion) - 2) * 24); } } if (is_array($formquestion) && !empty($formquestion)) { // First add hidden fields and value foreach ($formquestion as $key => $input) { if (is_array($input) && !empty($input)) { if ($input['type'] == 'hidden') { $more .= ''."\n"; } } } // Now add questions $moreonecolumn = ''; $more .= '
'."\n"; foreach ($formquestion as $key => $input) { if (is_array($input) && !empty($input)) { $size = (!empty($input['size']) ? ' size="'.$input['size'].'"' : ''); $moreattr = (!empty($input['moreattr']) ? ' '.$input['moreattr'] : ''); $morecss = (!empty($input['morecss']) ? ' '.$input['morecss'] : ''); if ($input['type'] == 'text') { $more .= '
'.$input['label'].'
'."\n"; } elseif ($input['type'] == 'password') { $more .= '
'.$input['label'].'
'."\n"; } elseif ($input['type'] == 'select') { $more .= '
'; if (!empty($input['label'])) $more .= $input['label'].'
'; $more .= $this->selectarray($input['name'], $input['values'], $input['default'], 1, 0, 0, $moreattr, 0, 0, 0, '', $morecss); $more .= '
'."\n"; } elseif ($input['type'] == 'checkbox') { $more .= '
'; $more .= '
'.$input['label'].'
'; $more .= ' $selval) { $more .= '
'; if ($i == 0) $more .= '
'.$input['label'].'
'; else $more .= '
 
'; $more .= '
'.$input['label'].'
'; $more .= '
'; $more .= $this->selectDate($input['value'], $input['name'], 0, 0, 0, '', 1, 0); $more .= '
'."\n"; $formquestion[] = array('name'=>$input['name'].'day'); $formquestion[] = array('name'=>$input['name'].'month'); $formquestion[] = array('name'=>$input['name'].'year'); $formquestion[] = array('name'=>$input['name'].'hour'); $formquestion[] = array('name'=>$input['name'].'min'); } elseif ($input['type'] == 'other') { $more .= '
'; if (!empty($input['label'])) $more .= $input['label'].'
'; $more .= $input['value']; $more .= '
'."\n"; } elseif ($input['type'] == 'onecolumn') { $moreonecolumn .= '
'; $moreonecolumn .= $input['value']; $moreonecolumn .= '
'."\n"; } } } $more .= '
'."\n"; $more .= $moreonecolumn; } // JQUI method dialog is broken with jmobile, we use standard HTML. // 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 // See page product/card.php for example if (!empty($conf->dol_use_jmobile)) $useajax = 0; if (empty($conf->use_javascript_ajax)) $useajax = 0; if ($useajax) { $autoOpen = true; $dialogconfirm = 'dialog-confirm'; $button = ''; if (!is_numeric($useajax)) { $button = $useajax; $useajax = 1; $autoOpen = false; $dialogconfirm .= '-'.$button; } $pageyes = $page.(preg_match('/\?/', $page) ? '&' : '?').'action='.$action.'&confirm=yes'; $pageno = ($useajax == 2 ? $page.(preg_match('/\?/', $page) ? '&' : '?').'confirm=no' : ''); // Add input fields into list of fields to read during submit (inputok and inputko) if (is_array($formquestion)) { foreach ($formquestion as $key => $input) { //print "xx ".$key." rr ".is_array($input)."
\n"; if (is_array($input) && isset($input['name'])) array_push($inputok, $input['name']); if (isset($input['inputko']) && $input['inputko'] == 1) array_push($inputko, $input['name']); } } // Show JQuery confirm box. $formconfirm .= ''."\n"; $formconfirm .= "\n\n"; $formconfirm .= ''; $formconfirm .= "\n"; } else { $formconfirm .= "\n\n"; if (empty($disableformtag)) $formconfirm .= ''."\n"; $formconfirm .= ''."\n"; $formconfirm .= ''."\n"; $formconfirm .= ''."\n"; // Line title $formconfirm .= ''."\n"; // Line text if (is_array($formquestion) && !empty($formquestion['text'])) { $formconfirm .= ''."\n"; } // Line form fields if ($more) { $formconfirm .= ''."\n"; } // Line with question $formconfirm .= ''; $formconfirm .= ''; $formconfirm .= ''; $formconfirm .= ''; $formconfirm .= ''."\n"; $formconfirm .= '
'.img_picto('', 'recent').' '.$title.'
'.$formquestion['text'].'
'."\n"; $formconfirm .= $more; $formconfirm .= '
'.$question.''; $formconfirm .= $this->selectyesno("confirm", $newselectedchoice); $formconfirm .= '
'."\n"; if (empty($disableformtag)) $formconfirm .= "\n"; $formconfirm .= '
'; $formconfirm .= "\n"; } return $formconfirm; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show a form to select a project * * @param int $page Page * @param int $socid Id third party (-1=all, 0=only projects not linked to a third party, id=projects not linked or linked to third party id) * @param int $selected Id pre-selected project * @param string $htmlname Name of select field * @param int $discard_closed Discard closed projects (0=Keep,1=hide completely except $selected,2=Disable) * @param int $maxlength Max length * @param int $forcefocus Force focus on field (works with javascript only) * @param int $nooutput No print is done. String is returned. * @return string Return html content */ public function form_project($page, $socid, $selected = '', $htmlname = 'projectid', $discard_closed = 0, $maxlength = 20, $forcefocus = 0, $nooutput = 0) { // phpcs:enable global $langs; require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; $out = ''; $formproject = new FormProjets($this->db); $langs->load("project"); if ($htmlname != "none") { $out .= "\n"; $out .= '
'; $out .= ''; $out .= ''; $out .= $formproject->select_projects($socid, $selected, $htmlname, $maxlength, 0, 1, $discard_closed, $forcefocus, 0, 0, '', 1); $out .= ''; $out .= '
'; } else { if ($selected) { $projet = new Project($this->db); $projet->fetch($selected); //print ''.$projet->title.''; $out .= $projet->getNomUrl(0, '', 1); } else { $out .= " "; } } if (empty($nooutput)) { print $out; return ''; } return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show a form to select payment conditions * * @param int $page Page * @param string $selected Id condition pre-selectionne * @param string $htmlname Name of select html field * @param int $addempty Add empty entry * @return void */ public function form_conditions_reglement($page, $selected = '', $htmlname = 'cond_reglement_id', $addempty = 0) { // phpcs:enable global $langs; if ($htmlname != "none") { print '
'; print ''; print ''; $this->select_conditions_paiements($selected, $htmlname, -1, $addempty); print ''; print '
'; } else { if ($selected) { $this->load_cache_conditions_paiements(); print $this->cache_conditions_paiements[$selected]['label']; } else { print " "; } } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show a form to select a delivery delay * * @param int $page Page * @param string $selected Id condition pre-selectionne * @param string $htmlname Name of select html field * @param int $addempty Ajoute entree vide * @return void */ public function form_availability($page, $selected = '', $htmlname = 'availability', $addempty = 0) { // phpcs:enable global $langs; if ($htmlname != "none") { print '
'; print ''; print ''; $this->selectAvailabilityDelay($selected, $htmlname, -1, $addempty); print ''; print '
'; } else { if ($selected) { $this->load_cache_availability(); print $this->cache_availability[$selected]['label']; } else { print " "; } } } /** * Output HTML form to select list of input reason (events that triggered an object creation, like after sending an emailing, making an advert, ...) * List found into table c_input_reason loaded by loadCacheInputReason * * @param string $page Page * @param string $selected Id condition pre-selectionne * @param string $htmlname Name of select html field * @param int $addempty Add empty entry * @return void */ public function formInputReason($page, $selected = '', $htmlname = 'demandreason', $addempty = 0) { global $langs; if ($htmlname != "none") { print '
'; print ''; print ''; $this->selectInputReason($selected, $htmlname, -1, $addempty); print ''; print '
'; } else { if ($selected) { $this->loadCacheInputReason(); foreach ($this->cache_demand_reason as $key => $val) { if ($val['id'] == $selected) { print $val['label']; break; } } } else { print " "; } } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show a form + html select a date * * @param string $page Page * @param string $selected Date preselected * @param string $htmlname Html name of date input fields or 'none' * @param int $displayhour Display hour selector * @param int $displaymin Display minutes selector * @param int $nooutput 1=No print output, return string * @return string * @see selectDate() */ public function form_date($page, $selected, $htmlname, $displayhour = 0, $displaymin = 0, $nooutput = 0) { // phpcs:enable global $langs; $ret = ''; if ($htmlname != "none") { $ret .= '
'; $ret .= ''; $ret .= ''; $ret .= ''; $ret .= ''; $ret .= ''; $ret .= '
'; $ret .= $this->selectDate($selected, $htmlname, $displayhour, $displaymin, 1, 'form'.$htmlname, 1, 0); $ret .= '
'; } else { if ($displayhour) $ret .= dol_print_date($selected, 'dayhour'); else $ret .= dol_print_date($selected, 'day'); } if (empty($nooutput)) print $ret; return $ret; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show a select form to choose a user * * @param string $page Page * @param string $selected Id of user preselected * @param string $htmlname Name of input html field. If 'none', we just output the user link. * @param array $exclude List of users id to exclude * @param array $include List of users id to include * @return void */ public function form_users($page, $selected = '', $htmlname = 'userid', $exclude = '', $include = '') { // phpcs:enable global $langs; if ($htmlname != "none") { print '
'; print ''; print ''; print $this->select_dolusers($selected, $htmlname, 1, $exclude, 0, $include); print ''; print '
'; } else { if ($selected) { require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; $theuser = new User($this->db); $theuser->fetch($selected); print $theuser->getNomUrl(1); } else { print " "; } } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show form with payment mode * * @param string $page Page * @param int $selected Id mode pre-selectionne * @param string $htmlname Name of select html field * @param string $filtertype To filter on field type in llx_c_paiement (array('code'=>xx,'label'=>zz)) * @param int $active Active or not, -1 = all * @param int $addempty 1=Add empty entry * @return void */ public function form_modes_reglement($page, $selected = '', $htmlname = 'mode_reglement_id', $filtertype = '', $active = 1, $addempty = 0) { // phpcs:enable global $langs; if ($htmlname != "none") { print '
'; print ''; print ''; $this->select_types_paiements($selected, $htmlname, $filtertype, 0, $addempty, 0, 0, $active); print ''; print '
'; } else { if ($selected) { $this->load_cache_types_paiements(); print $this->cache_types_paiements[$selected]['label']; } else { print " "; } } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show form with multicurrency code * * @param string $page Page * @param string $selected code pre-selectionne * @param string $htmlname Name of select html field * @return void */ public function form_multicurrency_code($page, $selected = '', $htmlname = 'multicurrency_code') { // phpcs:enable global $langs; if ($htmlname != "none") { print '
'; print ''; print ''; print $this->selectMultiCurrency($selected, $htmlname, 0); print ''; print '
'; } else { dol_include_once('/core/lib/company.lib.php'); print !empty($selected) ? currency_name($selected, 1) : ' '; } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show form with multicurrency rate * * @param string $page Page * @param double $rate Current rate * @param string $htmlname Name of select html field * @param string $currency Currency code to explain the rate * @return void */ public function form_multicurrency_rate($page, $rate = '', $htmlname = 'multicurrency_tx', $currency = '') { // phpcs:enable global $langs, $mysoc, $conf; if ($htmlname != "none") { print '
'; print ''; print ''; print ' '; print ' '; print ''; print '
'; } else { if (!empty($rate)) { print price($rate, 1, $langs, 1, 0); if ($currency && $rate != 1) print '   ('.price($rate, 1, $langs, 1, 0).' '.$currency.' = 1 '.$conf->currency.')'; } else { print 1; } } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show a select box with available absolute discounts * * @param string $page Page URL where form is shown * @param int $selected Value pre-selected * @param string $htmlname Name of SELECT component. If 'none', not changeable. Example 'remise_id'. * @param int $socid Third party id * @param float $amount Total amount available * @param string $filter SQL filter on discounts * @param int $maxvalue Max value for lines that can be selected * @param string $more More string to add * @param int $hidelist 1=Hide list * @param int $discount_type 0 => customer discount, 1 => supplier discount * @return void */ public function form_remise_dispo($page, $selected, $htmlname, $socid, $amount, $filter = '', $maxvalue = 0, $more = '', $hidelist = 0, $discount_type = 0) { // phpcs:enable global $conf, $langs; if ($htmlname != "none") { print '
'; print ''; print ''; print '
'; if (!empty($discount_type)) { if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { if (!$filter || $filter == "fk_invoice_supplier_source IS NULL") $translationKey = 'HasAbsoluteDiscountFromSupplier'; // If we want deposit to be substracted to payments only and not to total of final invoice else $translationKey = 'HasCreditNoteFromSupplier'; } else { if (!$filter || $filter == "fk_invoice_supplier_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS PAID)%')") $translationKey = 'HasAbsoluteDiscountFromSupplier'; else $translationKey = 'HasCreditNoteFromSupplier'; } } else { if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { if (!$filter || $filter == "fk_facture_source IS NULL") $translationKey = 'CompanyHasAbsoluteDiscount'; // If we want deposit to be substracted to payments only and not to total of final invoice else $translationKey = 'CompanyHasCreditNote'; } else { if (!$filter || $filter == "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')") $translationKey = 'CompanyHasAbsoluteDiscount'; else $translationKey = 'CompanyHasCreditNote'; } } print $langs->trans($translationKey, price($amount, 0, $langs, 0, 0, -1, $conf->currency)); if (empty($hidelist)) print ': '; print '
'; if (empty($hidelist)) { print '
'; $newfilter = 'discount_type='.intval($discount_type); if (!empty($discount_type)) { $newfilter .= ' AND fk_invoice_supplier IS NULL AND fk_invoice_supplier_line IS NULL'; // Supplier discounts available } else { $newfilter .= ' AND fk_facture IS NULL AND fk_facture_line IS NULL'; // Customer discounts available } if ($filter) $newfilter .= ' AND ('.$filter.')'; $nbqualifiedlines = $this->select_remises($selected, $htmlname, $newfilter, $socid, $maxvalue); if ($nbqualifiedlines > 0) { print '   '; } print '
'; } if ($more) { print '
'; print $more; print '
'; } print '
'; } else { if ($selected) { print $selected; } else { print "0"; } } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show forms to select a contact * * @param string $page Page * @param Societe $societe Filter on third party * @param int $selected Id contact pre-selectionne * @param string $htmlname Name of HTML select. If 'none', we just show contact link. * @return void */ public function form_contacts($page, $societe, $selected = '', $htmlname = 'contactid') { // phpcs:enable global $langs, $conf; if ($htmlname != "none") { print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; $num = $this->select_contacts($societe->id, $selected, $htmlname); if ($num == 0) { $addcontact = (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT) ? $langs->trans("AddContact") : $langs->trans("AddContactAddress")); print ''.$addcontact.''; } print '
'; } else { if ($selected) { require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; $contact = new Contact($this->db); $contact->fetch($selected); print $contact->getFullName($langs); } else { print " "; } } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Output html select to select thirdparty * * @param string $page Page * @param string $selected Id preselected * @param string $htmlname Name of HTML select * @param string $filter optional filters criteras * @param int $showempty Add an empty field * @param int $showtype Show third party type in combolist (customer, prospect or supplier) * @param int $forcecombo Force to use combo box * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) * @param int $nooutput No print output. Return it only. * @return void|string */ public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0) { // phpcs:enable global $langs; $out = ''; if ($htmlname != "none") { $out .= '
'; $out .= ''; $out .= ''; $out .= $this->select_company($selected, $htmlname, $filter, $showempty, $showtype, $forcecombo, $events); $out .= ''; $out .= '
'; } else { if ($selected) { require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; $soc = new Societe($this->db); $soc->fetch($selected); $out .= $soc->getNomUrl($langs); } else { $out .= " "; } } if ($nooutput) return $out; else print $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Retourne la liste des devises, dans la langue de l'utilisateur * * @param string $selected preselected currency code * @param string $htmlname name of HTML select list * @deprecated * @return void */ public function select_currency($selected = '', $htmlname = 'currency_id') { // phpcs:enable print $this->selectCurrency($selected, $htmlname); } /** * Retourne la liste des devises, dans la langue de l'utilisateur * * @param string $selected preselected currency code * @param string $htmlname name of HTML select list * @param string $mode 0 = Add currency symbol into label, 1 = Add 3 letter iso code * @return string */ public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0) { global $conf, $langs, $user; $langs->loadCacheCurrencies(''); $out = ''; if ($selected == 'euro' || $selected == 'euros') $selected = 'EUR'; // Pour compatibilite $out .= ''; if ($user->admin) $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); // Make select dynamic include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname); return $out; } /** * Return array of currencies in user language * * @param string $selected preselected currency code * @param string $htmlname name of HTML select list * @param integer $useempty 1=Add empty line * @return string */ public function selectMultiCurrency($selected = '', $htmlname = 'multicurrency_code', $useempty = 0) { global $db, $conf, $langs, $user; $langs->loadCacheCurrencies(''); // Load ->cache_currencies $TCurrency = array(); $sql = 'SELECT code FROM '.MAIN_DB_PREFIX.'multicurrency'; $sql .= " WHERE entity IN ('".getEntity('mutlicurrency')."')"; $resql = $this->db->query($sql); if ($resql) { while ($obj = $this->db->fetch_object($resql)) $TCurrency[$obj->code] = $obj->code; } $out = ''; $out .= ''; // Make select dynamic include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname); return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Load into the cache vat rates of a country * * @param string $country_code Country code with quotes ("'CA'", or "'CA,IN,...'") * @return int Nb of loaded lines, 0 if already loaded, <0 if KO */ public function load_cache_vatrates($country_code) { // phpcs:enable global $langs; $num = count($this->cache_vatrates); if ($num > 0) return $num; // Cache already loaded dol_syslog(__METHOD__, LOG_DEBUG); $sql = "SELECT DISTINCT t.rowid, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid"; $sql .= " AND t.active > 0"; $sql .= " AND c.code IN (".$country_code.")"; $sql .= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC"; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); if ($num) { for ($i = 0; $i < $num; $i++) { $obj = $this->db->fetch_object($resql); $this->cache_vatrates[$i]['rowid'] = $obj->rowid; $this->cache_vatrates[$i]['code'] = $obj->code; $this->cache_vatrates[$i]['txtva'] = $obj->taux; $this->cache_vatrates[$i]['nprtva'] = $obj->recuperableonly; $this->cache_vatrates[$i]['localtax1'] = $obj->localtax1; $this->cache_vatrates[$i]['localtax1_type'] = $obj->localtax1_type; $this->cache_vatrates[$i]['localtax2'] = $obj->localtax2; $this->cache_vatrates[$i]['localtax2_type'] = $obj->localtax1_type; $this->cache_vatrates[$i]['label'] = $obj->taux.'%'.($obj->code ? ' ('.$obj->code.')' : ''); // Label must contains only 0-9 , . % or * $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 $positiverates = ''; if ($obj->taux) $positiverates .= ($positiverates ? '/' : '').$obj->taux; if ($obj->localtax1) $positiverates .= ($positiverates ? '/' : '').$obj->localtax1; if ($obj->localtax2) $positiverates .= ($positiverates ? '/' : '').$obj->localtax2; if (empty($positiverates)) $positiverates = '0'; $this->cache_vatrates[$i]['labelpositiverates'] = $positiverates.($obj->code ? ' ('.$obj->code.')' : ''); // Must never be used as key, only label } return $num; } else { $this->error = ''.$langs->trans("ErrorNoVATRateDefinedForSellerCountry", $country_code).''; return -1; } } else { $this->error = ''.$this->db->error().''; return -2; } } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Output an HTML select vat rate. * The name of this function should be selectVat. We keep bad name for compatibility purpose. * * @param string $htmlname Name of HTML select field * @param float|string $selectedrate Force preselected vat rate. Can be '8.5' or '8.5 (NOO)' for example. Use '' for no forcing. * @param Societe $societe_vendeuse Thirdparty seller * @param Societe $societe_acheteuse Thirdparty buyer * @param int $idprod Id product. O if unknown of NA. * @param int $info_bits Miscellaneous information on line (1 for NPR) * @param int|string $type ''=Unknown, 0=Product, 1=Service (Used if idprod not defined) * Si vendeur non assujeti a TVA, TVA par defaut=0. Fin de regle. * Si le (pays vendeur = pays acheteur) alors la TVA par defaut=TVA du produit vendu. Fin de regle. * Si (vendeur et acheteur dans Communaute europeenne) et bien vendu = moyen de transports neuf (auto, bateau, avion), TVA par defaut=0 (La TVA doit etre paye par l'acheteur au centre d'impots de son pays et non au vendeur). Fin de regle. * Si vendeur et acheteur dans Communauté européenne et acheteur= particulier alors TVA par défaut=TVA du produit vendu. Fin de règle. * Si vendeur et acheteur dans Communauté européenne et acheteur= entreprise alors TVA par défaut=0. Fin de règle. * Sinon la TVA proposee par defaut=0. Fin de regle. * @param bool $options_only Return HTML options lines only (for ajax treatment) * @param int $mode 0=Use vat rate as key in combo list, 1=Add VAT code after vat rate into key, -1=Use id of vat line as key * @return string */ public function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = '', $societe_acheteuse = '', $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0) { // phpcs:enable global $langs, $conf, $mysoc; $langs->load('errors'); $return = ''; // Define defaultnpr, defaultttx and defaultcode $defaultnpr = ($info_bits & 0x01); $defaultnpr = (preg_match('/\*/', $selectedrate) ? 1 : $defaultnpr); $defaulttx = str_replace('*', '', $selectedrate); $defaultcode = ''; if (preg_match('/\((.*)\)/', $defaulttx, $reg)) { $defaultcode = $reg[1]; $defaulttx = preg_replace('/\s*\(.*\)/', '', $defaulttx); } //var_dump($selectedrate.'-'.$defaulttx.'-'.$defaultnpr.'-'.$defaultcode); // Check parameters if (is_object($societe_vendeuse) && !$societe_vendeuse->country_code) { if ($societe_vendeuse->id == $mysoc->id) { $return .= ''.$langs->trans("ErrorYourCountryIsNotDefined").''; } else { $return .= ''.$langs->trans("ErrorSupplierCountryIsNotDefined").''; } return $return; } //var_dump($societe_acheteuse); //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"; //exit; // Define list of countries to use to search VAT rates to show // First we defined code_country to use to find list if (is_object($societe_vendeuse)) { $code_country = "'".$societe_vendeuse->country_code."'"; } else { $code_country = "'".$mysoc->country_code."'"; // Pour compatibilite ascendente } if (!empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC)) // If option to have vat for end customer for services is on { require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; if (!isInEEC($societe_vendeuse) && (!is_object($societe_acheteuse) || (isInEEC($societe_acheteuse) && !$societe_acheteuse->isACompany()))) { // We also add the buyer if (is_numeric($type)) { if ($type == 1) // We know product is a service { $code_country .= ",'".$societe_acheteuse->country_code."'"; } } elseif (!$idprod) // We don't know type of product { $code_country .= ",'".$societe_acheteuse->country_code."'"; } else { $prodstatic = new Product($this->db); $prodstatic->fetch($idprod); if ($prodstatic->type == Product::TYPE_SERVICE) // We know product is a service { $code_country .= ",'".$societe_acheteuse->country_code."'"; } } } } // Now we get list $num = $this->load_cache_vatrates($code_country); // If no vat defined, return -1 with message into this->error if ($num > 0) { // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '') if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) { $tmpthirdparty = new Societe($this->db); $defaulttx = get_default_tva($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod); $defaultnpr = get_default_npr($societe_vendeuse, (is_object($societe_acheteuse) ? $societe_acheteuse : $tmpthirdparty), $idprod); if (preg_match('/\((.*)\)/', $defaulttx, $reg)) { $defaultcode = $reg[1]; $defaulttx = preg_replace('/\s*\(.*\)/', '', $defaulttx); } if (empty($defaulttx)) $defaultnpr = 0; } // Si taux par defaut n'a pu etre determine, on prend dernier de la liste. // Comme ils sont tries par ordre croissant, dernier = plus eleve = taux courant if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) { if (empty($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS)) $defaulttx = $this->cache_vatrates[$num - 1]['txtva']; else $defaulttx = ($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS == 'none' ? '' : $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS); } // Disabled if seller is not subject to VAT $disabled = false; $title = ''; if (is_object($societe_vendeuse) && $societe_vendeuse->id == $mysoc->id && $societe_vendeuse->tva_assuj == "0") { // Override/enable VAT for expense report regardless of global setting - needed if expense report used for business expenses instead // of using supplier invoices (this is a very bad idea !) if (empty($conf->global->EXPENSEREPORT_OVERRIDE_VAT)) { $title = ' title="'.$langs->trans('VATIsNotUsed').'"'; $disabled = true; } } if (!$options_only) $return .= ''; } else { $return .= $this->error; } $this->num = $num; return $return; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Show a HTML widget to input a date or combo list for day, month, years and optionaly hours and minutes. * Fields are preselected with : * - set_time date (must be a local PHP server timestamp or string date with format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM') * - local date in user area, if set_time is '' (so if set_time is '', output may differs when done from two different location) * - Empty (fields empty), if set_time is -1 (in this case, parameter empty must also have value 1) * * @param integer $set_time Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). * @param string $prefix Prefix for fields name * @param int $h 1 or 2=Show also hours (2=hours on a new line), -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show hour always empty * @param int $m 1=Show also minutes, -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show minutes always empty * @param int $empty 0=Fields required, 1=Empty inputs are allowed, 2=Empty inputs are allowed for hours only * @param string $form_name Not used * @param int $d 1=Show days, month, years * @param int $addnowlink Add a link "Now" * @param int $nooutput Do not output html string but return it * @param int $disabled Disable input fields * @param int $fullday When a checkbox with this html name is on, hour and day are set with 00:00 or 23:59 * @param string $addplusone Add a link "+1 hour". Value must be name of another select_date field. * @param datetime $adddateof Add a link "Date of invoice" using the following date. * @return string|void Nothing or string if nooutput is 1 * @deprecated * @see selectDate(), form_date(), select_month(), select_year(), select_dayofweek() */ public function select_date($set_time = '', $prefix = 're', $h = 0, $m = 0, $empty = 0, $form_name = "", $d = 1, $addnowlink = 0, $nooutput = 0, $disabled = 0, $fullday = '', $addplusone = '', $adddateof = '') { // phpcs:enable $retstring = $this->selectDate($set_time, $prefix, $h, $m, $empty, $form_name, $d, $addnowlink, $disabled, $fullday, $addplusone, $adddateof); if (!empty($nooutput)) { return $retstring; } print $retstring; return; } /** * Show 2 HTML widget to input a date or combo list for day, month, years and optionaly hours and minutes. * Fields are preselected with : * - set_time date (must be a local PHP server timestamp or string date with format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM') * - local date in user area, if set_time is '' (so if set_time is '', output may differs when done from two different location) * - Empty (fields empty), if set_time is -1 (in this case, parameter empty must also have value 1) * * @param integer $set_time Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). * @param integer $set_time_end Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). * @param string $prefix Prefix for fields name * @param string $empty 0=Fields required, 1=Empty inputs are allowed, 2=Empty inputs are allowed for hours only * @return string Html for selectDate * @see form_date(), select_month(), select_year(), select_dayofweek() */ public function selectDateToDate($set_time = '', $set_time_end = '', $prefix = 're', $empty = 0) { $ret = $this->selectDate($set_time, $prefix.'_start', 0, 0, $empty); $ret .= '
'; $ret .= $this->selectDate($set_time_end, $prefix.'_end', 0, 0, $empty); return $ret; } /** * Show a HTML widget to input a date or combo list for day, month, years and optionaly hours and minutes. * Fields are preselected with : * - set_time date (must be a local PHP server timestamp or string date with format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM') * - local date in user area, if set_time is '' (so if set_time is '', output may differs when done from two different location) * - Empty (fields empty), if set_time is -1 (in this case, parameter empty must also have value 1) * * @param integer $set_time Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). * @param string $prefix Prefix for fields name * @param int $h 1 or 2=Show also hours (2=hours on a new line), -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show hour always empty * @param int $m 1=Show also minutes, -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show minutes always empty * @param int $empty 0=Fields required, 1=Empty inputs are allowed, 2=Empty inputs are allowed for hours only * @param string $form_name Not used * @param int $d 1=Show days, month, years * @param int $addnowlink Add a link "Now", 1 with server time, 2 with local computer time * @param int $disabled Disable input fields * @param int $fullday When a checkbox with id #fullday is checked, hours are set with 00:00 (if value if 'fulldaystart') or 23:59 (if value is 'fulldayend') * @param string $addplusone Add a link "+1 hour". Value must be name of another selectDate field. * @param datetime $adddateof Add a link "Date of ..." using the following date. See also $labeladddateof for the label used. * @param string $openinghours Specify hour start and hour end for the select ex 8,20 * @param int $stepminutes Specify step for minutes between 1 and 30 * @param string $labeladddateof Label to use for the $adddateof parameter. * @param string $placeholder Placeholder * @return string Html for selectDate * @see form_date(), select_month(), select_year(), select_dayofweek() */ public function selectDate($set_time = '', $prefix = 're', $h = 0, $m = 0, $empty = 0, $form_name = "", $d = 1, $addnowlink = 0, $disabled = 0, $fullday = '', $addplusone = '', $adddateof = '', $openinghours = '', $stepminutes = 1, $labeladddateof = '', $placeholder = '') { global $conf, $langs; $retstring = ''; if ($prefix == '') $prefix = 're'; if ($h == '') $h = 0; if ($m == '') $m = 0; $emptydate = 0; $emptyhours = 0; if ($stepminutes <= 0 || $stepminutes > 30) $stepminutes = 1; if ($empty == 1) { $emptydate = 1; $emptyhours = 1; } if ($empty == 2) { $emptydate = 0; $emptyhours = 1; } $orig_set_time = $set_time; if ($set_time === '' && $emptydate == 0) { include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; $set_time = dol_now('tzuser') - (getServerTimeZoneInt('now') * 3600); // set_time must be relative to PHP server timezone } // Analysis of the pre-selection date if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', $set_time, $reg)) // deprecated usage { // Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' $syear = (!empty($reg[1]) ? $reg[1] : ''); $smonth = (!empty($reg[2]) ? $reg[2] : ''); $sday = (!empty($reg[3]) ? $reg[3] : ''); $shour = (!empty($reg[4]) ? $reg[4] : ''); $smin = (!empty($reg[5]) ? $reg[5] : ''); } elseif (strval($set_time) != '' && $set_time != -1) { // set_time est un timestamps (0 possible) $syear = dol_print_date($set_time, "%Y"); $smonth = dol_print_date($set_time, "%m"); $sday = dol_print_date($set_time, "%d"); if ($orig_set_time != '') { $shour = dol_print_date($set_time, "%H"); $smin = dol_print_date($set_time, "%M"); $ssec = dol_print_date($set_time, "%S"); } else { $shour = ''; $smin = ''; $ssec = ''; } } else { // Date est '' ou vaut -1 $syear = ''; $smonth = ''; $sday = ''; $shour = !isset($conf->global->MAIN_DEFAULT_DATE_HOUR) ? ($h == -1 ? '23' : '') : $conf->global->MAIN_DEFAULT_DATE_HOUR; $smin = !isset($conf->global->MAIN_DEFAULT_DATE_MIN) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_MIN; $ssec = !isset($conf->global->MAIN_DEFAULT_DATE_SEC) ? ($h == -1 ? '59' : '') : $conf->global->MAIN_DEFAULT_DATE_SEC; } if ($h == 3) $shour = ''; if ($m == 3) $smin = ''; // You can set MAIN_POPUP_CALENDAR to 'eldy' or 'jquery' $usecalendar = 'combo'; if (!empty($conf->use_javascript_ajax) && (empty($conf->global->MAIN_POPUP_CALENDAR) || $conf->global->MAIN_POPUP_CALENDAR != "none")) { $usecalendar = ((empty($conf->global->MAIN_POPUP_CALENDAR) || $conf->global->MAIN_POPUP_CALENDAR == 'eldy') ? 'jquery' : $conf->global->MAIN_POPUP_CALENDAR); } if ($d) { // Show date with popup if ($usecalendar != 'combo') { $formated_date = ''; //print "e".$set_time." t ".$conf->format_date_short; if (strval($set_time) != '' && $set_time != -1) { //$formated_date=dol_print_date($set_time,$conf->format_date_short); $formated_date = dol_print_date($set_time, $langs->trans("FormatDateShortInput")); // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript } // Calendrier popup version eldy if ($usecalendar == "eldy") { // Zone de saisie manuelle de la date $retstring .= 'trans("FormatDateShortJavaInput").'\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript $retstring .= '>'; // Icone calendrier if (!$disabled) { $retstring .= ''; } else $retstring .= ''; $retstring .= ''."\n"; $retstring .= ''."\n"; $retstring .= ''."\n"; } elseif ($usecalendar == 'jquery') { if (!$disabled) { // Output javascript for datepicker $retstring .= ""; } // Zone de saisie manuelle de la date $retstring .= '
'; $retstring .= 'trans("FormatDateShortJavaInput").'\'); "'; // FormatDateShortInput for dol_print_date / FormatDateShortJavaInput that is same for javascript $retstring .= '>'; // Icone calendrier if (!$disabled) { /* Not required. Managed by option buttonImage of jquery $retstring.=img_object($langs->trans("SelectDate"),'calendarday','id="'.$prefix.'id" class="datecallink"'); $retstring.="";*/ } else { $retstring .= ''; } $retstring .= '
'; $retstring .= ''."\n"; $retstring .= ''."\n"; $retstring .= ''."\n"; } else { $retstring .= "Bad value of MAIN_POPUP_CALENDAR"; } } // Show date with combo selects else { //$retstring.='
'; // Day $retstring .= ''; if ($emptydate || $set_time == -1) { $retstring .= ''; } for ($day = 1; $day <= 31; $day++) { $retstring .= ''; } $retstring .= ""; $retstring .= ''; if ($emptydate || $set_time == -1) { $retstring .= ''; } // Month for ($month = 1; $month <= 12; $month++) { $retstring .= '"; } $retstring .= ""; // Year if ($emptydate || $set_time == -1) { $retstring .= ''; } else { $retstring .= ''; for ($year = $syear - 10; $year < $syear + 10; $year++) { $retstring .= ''; } $retstring .= "\n"; } //$retstring.='
'; } } if ($d && $h) $retstring .= ($h == 2 ? '
' : ' '); if ($h) { $hourstart = 0; $hourend = 24; if ($openinghours != '') { $openinghours = explode(',', $openinghours); $hourstart = $openinghours[0]; $hourend = $openinghours[1]; if ($hourend < $hourstart) $hourend = $hourstart; } // Show hour $retstring .= ''; if ($emptyhours) $retstring .= ''; for ($hour = $hourstart; $hour < $hourend; $hour++) { if (strlen($hour) < 2) $hour = "0".$hour; $retstring .= ''; } $retstring .= ''; if ($m && empty($conf->dol_optimize_smallscreen)) $retstring .= ":"; } if ($m) { // Show minutes $retstring .= ''; if ($emptyhours) $retstring .= ''; for ($min = 0; $min < 60; $min += $stepminutes) { if (strlen($min) < 2) $min = "0".$min; $retstring .= ''; } $retstring .= ''; $retstring .= ''; } // Add a "Now" link if ($conf->use_javascript_ajax && $addnowlink) { // Script which will be inserted in the onClick of the "Now" link $reset_scripts = ""; if ($addnowlink == 2) // local computer time { // pad add leading 0 on numbers $reset_scripts .= "Number.prototype.pad = function(size) { var s = String(this); while (s.length < (size || 2)) {s = '0' + s;} return s; }; var d = new Date();"; } // Generate the date part, depending on the use or not of the javascript calendar if ($addnowlink == 1) // server time expressed in user time setup { $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date(dol_now(), 'day', 'tzuser').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.dol_print_date(dol_now(), '%d', 'tzuser').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.dol_print_date(dol_now(), '%m', 'tzuser').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.dol_print_date(dol_now(), '%Y', 'tzuser').'\');'; } elseif ($addnowlink == 2) { /* Disabled because the output does not use the string format defined by FormatDateShort key to forge the value into #prefix. * This break application for foreign languages. $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(d.toLocaleDateString(\''.str_replace('_', '-', $langs->defaultlang).'\'));'; $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(d.getDate().pad());'; $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(parseInt(d.getMonth().pad()) + 1);'; $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(d.getFullYear());'; */ $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date(dol_now(), 'day', 'tzuser').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.dol_print_date(dol_now(), '%d', 'tzuser').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.dol_print_date(dol_now(), '%m', 'tzuser').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.dol_print_date(dol_now(), '%Y', 'tzuser').'\');'; } /*if ($usecalendar == "eldy") { $base=DOL_URL_ROOT.'/core/'; $reset_scripts .= 'resetDP(\''.$base.'\',\''.$prefix.'\',\''.$langs->trans("FormatDateShortJavaInput").'\',\''.$langs->defaultlang.'\');'; } else { $reset_scripts .= 'this.form.elements[\''.$prefix.'day\'].value=formatDate(new Date(), \'d\'); '; $reset_scripts .= 'this.form.elements[\''.$prefix.'month\'].value=formatDate(new Date(), \'M\'); '; $reset_scripts .= 'this.form.elements[\''.$prefix.'year\'].value=formatDate(new Date(), \'yyyy\'); '; }*/ // Update the hour part if ($h) { if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {"; //$reset_scripts .= 'this.form.elements[\''.$prefix.'hour\'].value=formatDate(new Date(), \'HH\'); '; if ($addnowlink == 1) { $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(), '%H', 'tzuser').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').change();'; } elseif ($addnowlink == 2) { $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(d.getHours().pad());'; $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').change();'; } if ($fullday) $reset_scripts .= ' } '; } // Update the minute part if ($m) { if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {"; //$reset_scripts .= 'this.form.elements[\''.$prefix.'min\'].value=formatDate(new Date(), \'mm\'); '; if ($addnowlink == 1) { $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(), '%M', 'tzuser').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').change();'; } elseif ($addnowlink == 2) { $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(d.getMinutes().pad());'; $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').change();'; } if ($fullday) $reset_scripts .= ' } '; } // If reset_scripts is not empty, print the link with the reset_scripts in the onClick if ($reset_scripts && empty($conf->dol_optimize_smallscreen)) { $retstring .= ' '; } } // Add a "Plus one hour" link if ($conf->use_javascript_ajax && $addplusone) { // Script which will be inserted in the onClick of the "Add plusone" link $reset_scripts = ""; // Generate the date part, depending on the use or not of the javascript calendar $reset_scripts .= 'jQuery(\'#'.$prefix.'\').val(\''.dol_print_date(dol_now(), 'day').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'day\').val(\''.dol_print_date(dol_now(), '%d').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'month\').val(\''.dol_print_date(dol_now(), '%m').'\');'; $reset_scripts .= 'jQuery(\'#'.$prefix.'year\').val(\''.dol_print_date(dol_now(), '%Y').'\');'; // Update the hour part if ($h) { if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {"; $reset_scripts .= 'jQuery(\'#'.$prefix.'hour\').val(\''.dol_print_date(dol_now(), '%H').'\');'; if ($fullday) $reset_scripts .= ' } '; } // Update the minute part if ($m) { if ($fullday) $reset_scripts .= " if (jQuery('#fullday:checked').val() == null) {"; $reset_scripts .= 'jQuery(\'#'.$prefix.'min\').val(\''.dol_print_date(dol_now(), '%M').'\');'; if ($fullday) $reset_scripts .= ' } '; } // If reset_scripts is not empty, print the link with the reset_scripts in the onClick if ($reset_scripts && empty($conf->dol_optimize_smallscreen)) { $retstring .= ' '; } } // Add a "Plus one hour" link if ($conf->use_javascript_ajax && $adddateof) { $tmparray = dol_getdate($adddateof); if (empty($labeladddateof)) $labeladddateof = $langs->trans("DateInvoice"); $retstring .= ' - '; $out .= ''; $out .= '
'; return $out; } /** * Return HTML to show the search and clear search button * * @param string $cssclass CSS class * @param int $calljsfunction 0=default. 1=call function initCheckForSelect() after changing status of checkboxes * @param string $massactionname Mass action button name that will launch an action on the selected items * @return string */ public function showCheckAddButtons($cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction") { global $conf, $langs; $out = ''; if (!empty($conf->use_javascript_ajax)) $out .= '
'; $out .= ''; return $out; } /** * Return HTML to show the search and clear seach button * * @param int $addcheckuncheckall Add the check all/uncheck all checkbox (use javascript) and code to manage this * @param string $cssclass CSS class * @param int $calljsfunction 0=default. 1=call function initCheckForSelect() after changing status of checkboxes * @param string $massactionname Mass action name * @return string */ public function showFilterAndCheckAddButtons($addcheckuncheckall = 0, $cssclass = 'checkforaction', $calljsfunction = 0, $massactionname = "massaction") { $out = $this->showFilterButtons(); if ($addcheckuncheckall) { $out .= $this->showCheckAddButtons($cssclass, $calljsfunction, $massactionname); } return $out; } /** * Return HTML to show the select of expense categories * * @param string $selected preselected category * @param string $htmlname name of HTML select list * @param integer $useempty 1=Add empty line * @param array $excludeid id to exclude * @param string $target htmlname of target select to bind event * @param int $default_selected default category to select if fk_c_type_fees change = EX_KME * @param array $params param to give * @param int $info_admin Show the tooltip help picto to setup list * @return string */ public function selectExpenseCategories($selected = '', $htmlname = 'fk_c_exp_tax_cat', $useempty = 0, $excludeid = array(), $target = '', $default_selected = 0, $params = array(), $info_admin = 1) { global $db, $langs, $user; $out = ''; $sql = 'SELECT rowid, label FROM '.MAIN_DB_PREFIX.'c_exp_tax_cat WHERE active = 1'; $sql .= ' AND entity IN (0,'.getEntity('exp_tax_cat').')'; if (!empty($excludeid)) $sql .= ' AND rowid NOT IN ('.implode(',', $excludeid).')'; $sql .= ' ORDER BY label'; $resql = $db->query($sql); if ($resql) { $out = ''; $out .= ajax_combobox('select_'.$htmlname); if (!empty($htmlname) && $user->admin && $info_admin) $out .= ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); if (!empty($target)) { $sql = "SELECT c.id FROM ".MAIN_DB_PREFIX."c_type_fees as c WHERE c.code = 'EX_KME' AND c.active = 1"; $resql = $db->query($sql); if ($resql) { if ($db->num_rows($resql) > 0) { $obj = $db->fetch_object($resql); $out .= ''; } } } } else { dol_print_error($db); } return $out; } /** * Return HTML to show the select ranges of expense range * * @param string $selected preselected category * @param string $htmlname name of HTML select list * @param integer $useempty 1=Add empty line * @return string */ public function selectExpenseRanges($selected = '', $htmlname = 'fk_range', $useempty = 0) { global $db, $conf, $langs; $out = ''; $sql = 'SELECT rowid, range_ik FROM '.MAIN_DB_PREFIX.'c_exp_tax_range'; $sql .= ' WHERE entity = '.$conf->entity.' AND active = 1'; $resql = $db->query($sql); if ($resql) { $out = ''; } else { dol_print_error($db); } return $out; } /** * Return HTML to show a select of expense * * @param string $selected preselected category * @param string $htmlname name of HTML select list * @param integer $useempty 1=Add empty choice * @param integer $allchoice 1=Add all choice * @param integer $useid 0=use 'code' as key, 1=use 'id' as key * @return string */ public function selectExpense($selected = '', $htmlname = 'fk_c_type_fees', $useempty = 0, $allchoice = 1, $useid = 0) { global $db, $langs; $out = ''; $sql = 'SELECT id, code, label FROM '.MAIN_DB_PREFIX.'c_type_fees'; $sql .= ' WHERE active = 1'; $resql = $db->query($sql); if ($resql) { $out = ''; } else { dol_print_error($db); } return $out; } /** * Output a combo list with invoices qualified for a third party * * @param int $socid Id third party (-1=all, 0=only projects not linked to a third party, id=projects not linked or linked to third party id) * @param int $selected Id invoice preselected * @param string $htmlname Name of HTML select * @param int $maxlength Maximum length of label * @param int $option_only Return only html options lines without the select tag * @param string $show_empty Add an empty line ('1' or string to show for empty line) * @param int $discard_closed Discard closed projects (0=Keep,1=hide completely,2=Disable) * @param int $forcefocus Force focus on field (works with javascript only) * @param int $disabled Disabled * @param string $morecss More css added to the select component * @param string $projectsListId ''=Automatic filter on project allowed. List of id=Filter on project ids. * @param string $showproject 'all' = Show project info, ''=Hide project info * @param User $usertofilter User object to use for filtering * @return int Nbr of project if OK, <0 if KO */ public function selectInvoice($socid = -1, $selected = '', $htmlname = 'invoiceid', $maxlength = 24, $option_only = 0, $show_empty = '1', $discard_closed = 0, $forcefocus = 0, $disabled = 0, $morecss = 'maxwidth500', $projectsListId = '', $showproject = 'all', $usertofilter = null) { global $user, $conf, $langs; require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; if (is_null($usertofilter)) { $usertofilter = $user; } $out = ''; $hideunselectables = false; if (!empty($conf->global->PROJECT_HIDE_UNSELECTABLES)) $hideunselectables = true; if (empty($projectsListId)) { if (empty($usertofilter->rights->projet->all->lire)) { $projectstatic = new Project($this->db); $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertofilter, 0, 1); } } // Search all projects $sql = 'SELECT f.rowid, f.ref as fref, "nolabel" as flabel, p.rowid as pid, f.ref, p.title, p.fk_soc, p.fk_statut, p.public,'; $sql .= ' s.nom as name'; $sql .= ' FROM '.MAIN_DB_PREFIX.'projet as p'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON s.rowid = p.fk_soc,'; $sql .= ' '.MAIN_DB_PREFIX.'facture as f'; $sql .= " WHERE p.entity IN (".getEntity('project').")"; $sql .= " AND f.fk_projet = p.rowid AND f.fk_statut=0"; //Brouillons seulement //if ($projectsListId) $sql.= " AND p.rowid IN (".$projectsListId.")"; //if ($socid == 0) $sql.= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)"; //if ($socid > 0) $sql.= " AND (p.fk_soc=".$socid." OR p.fk_soc IS NULL)"; $sql .= " GROUP BY f.ref ORDER BY p.ref, f.ref ASC"; $resql = $this->db->query($sql); if ($resql) { // Use select2 selector if (!empty($conf->use_javascript_ajax)) { include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus); $out .= $comboenhancement; $morecss = 'minwidth200imp maxwidth500'; } if (empty($option_only)) { $out .= ''; } print $out; $this->db->free($resql); return $num; } else { dol_print_error($this->db); return -1; } } /** * Output the component to make advanced search criteries * * @param array $arrayofcriterias Array of available search criterias. Example: array($object->element => $object->fields, 'otherfamily' => otherarrayoffields, ...) * @param array $search_component_params Array of selected search criterias * @param array $arrayofinputfieldsalreadyoutput Array of input fields already inform. The component will not generate a hidden input field if it is in this list. * @return string HTML component for advanced search */ public function searchComponent($arrayofcriterias, $search_component_params, $arrayofinputfieldsalreadyoutput = array()) { global $langs; $ret = ''; $ret .= '
'; //$ret .= ''; $ret .= ''; $ret .= ''; $ret .= $langs->trans("Filters"); $ret .= ''; //$ret .= ''; $ret .= '
'; $texttoshow = '
'.$langs->trans("Search").'
'; $ret .= '
'.$texttoshow.'
'; $ret .= '
'; $ret .= ''; // For compatibility with forms that show themself the search criteria in addition of this component, we output the fields foreach ($arrayofcriterias as $criterias) { foreach ($criterias as $criteriafamilykey => $criteriafamilyval) { if (in_array('search_'.$criteriafamilykey, $arrayofinputfieldsalreadyoutput)) continue; if (in_array($criteriafamilykey, array('rowid', 'ref_ext', 'entity', 'extraparams'))) continue; if (in_array($criteriafamilyval['type'], array('date', 'datetime', 'timestamp'))) { $ret .= ''; $ret .= ''; $ret .= ''; $ret .= ''; $ret .= ''; $ret .= ''; $ret .= ''; $ret .= ''; } else { $ret .= ''; } } } $ret .= '
'; return $ret; } /** * selectModelMail * * @param string $prefix Prefix * @param string $modelType Model type * @param int $default 1=Show also Default mail template * @return string HTML select string */ public function selectModelMail($prefix, $modelType = '', $default = 0) { global $langs, $db, $user; $retstring = ''; $TModels = array(); include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; $formmail = new FormMail($db); $result = $formmail->fetchAllEMailTemplate($modelType, $user, $langs); if ($default) $TModels[0] = $langs->trans('DefaultMailModel'); if ($result > 0) { foreach ($formmail->lines_model as $model) { $TModels[$model->id] = $model->label; } } $retstring .= '"; return $retstring; } }