diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index 265628eb35a..ca64bb83324 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -140,9 +140,9 @@ if ($result) { $compta_fees = $obj->compte; $vatdata = getTaxesFromId($obj->tva_tx.($obj->vat_src_code?' ('.$obj->vat_src_code.')':''), $mysoc, $mysoc, 0); - $compta_tva = (! empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $account_vat); - $compta_localtax1 = (! empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva); - $compta_localtax2 = (! empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva); + $compta_tva = (! empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $account_vat); + $compta_localtax1 = (! empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $cpttva); + $compta_localtax2 = (! empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $cpttva); // Define array to display all VAT rates that use this accounting account $compta_tva if (price2num($obj->tva_tx) || ! empty($obj->vat_src_code)) diff --git a/htdocs/adherents/admin/adherent_emails.php b/htdocs/adherents/admin/adherent_emails.php index 2dedd8fd265..292b9c77339 100644 --- a/htdocs/adherents/admin/adherent_emails.php +++ b/htdocs/adherents/admin/adherent_emails.php @@ -157,6 +157,7 @@ print ''; * Editing global variables not related to a specific theme */ $constantes=array( + 'ADHERENT_MAIL_FROM', 'ADHERENT_AUTOREGISTER_NOTIF_MAIL_SUBJECT', 'ADHERENT_AUTOREGISTER_NOTIF_MAIL', 'ADHERENT_AUTOREGISTER_MAIL_SUBJECT', @@ -167,7 +168,6 @@ $constantes=array( 'ADHERENT_MAIL_COTIS', 'ADHERENT_MAIL_RESIL_SUBJECT', 'ADHERENT_MAIL_RESIL', - 'ADHERENT_MAIL_FROM', ); $helptext='*'.$langs->trans("FollowingConstantsWillBeSubstituted").'
'; diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index cf120f3871f..a22a2d57c0d 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -2492,4 +2492,133 @@ class Adherent extends CommonObject return $this->datefin < ($now - $conf->adherent->subscription->warning_delay); } + + + + /** + * Send reminders by emails before subscription end + * CAN BE A CRON TASK + * + * @param int $daysbeforeend Nb of days before end of subscription (negative number = after subscription) + * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + */ + public function sendReminderForExpiredSubscription($daysbeforeend=10) + { + global $conf, $langs, $mysoc, $user; + + $this->output = ''; + $this->error=''; + + $blockingerrormsg = ''; + + /*if (empty($conf->global->MEMBER_REMINDER_EMAIL)) + { + $langs->load("agenda"); + $this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Adherent")); + return 0; + }*/ + + $now = dol_now(); + + dol_syslog(__METHOD__, LOG_DEBUG); + + $tmp=dol_getdate($now); + $datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year']), -1 * $daysbeforeend, 'd'); + + $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent'; + $sql.= " WHERE datefin = '".$this->db->idate($datetosearchfor)."'"; + + $resql = $this->db->query($sql); + if ($resql) + { + $num_rows = $this->db->num_rows($resql); + + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; + $adherent = new Adherent($this->db); + $formmail=new FormMail($db); + + $i=0; + $nbok = 0; + $nbko = 0; + while ($i < $num_rows) + { + $obj = $this->db->fetch_object($resql); + + $adherent->fetch($obj->rowid); + + if (empty($adherent->email)) + { + $nbko++; + } + else + { + $adherent->fetch_thirdparty(); + + // Send reminder email + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; + include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; + + $outputlangs = new Translate('', $conf); + $outputlangs->setDefaultLang(empty($adherent->thirdparty->default_lang) ? $mysoc->default_lang : $adherent->thirdparty->default_lang); + $outputlangs->loadLangs(array("main", "members")); + + $arraydefaultmessage=$formmail->getEMailTemplate($this->db, 'member', $user, $outputlangs, 0, 1, '(SendReminderForExpiredSubscriptionTitle)'); + + if (is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) + { + $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $adherent); + //if (is_array($adherent->thirdparty)) $substitutionarraycomp = ... + complete_substitutions_array($substitutionarray, $outputlangs, $adherent); + + $subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs); + $msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs); + $from = $conf->global->ADHERENT_MAIL_FROM; + $to = $adherent->email; + + $cmail = new CMailFile($subject, $to, $from, $msg, array(), array(), array(), '', '', 0, 1); + $result = $cmail->sendfile(); + if (! $result) + { + $error++; + $this->error = $cmail->error; + $this->errors += $cmail->errors; + $nbko++; + } + else + { + $nbok++; + } + } + else + { + $blockingerrormsg="Can't find email template '(SendReminderForExpiredSubscriptionTitle)'"; + $nbko++; + break; + } + } + + $i++; + } + } + else + { + $this->error = $this->db->lasterror(); + return 1; + } + + if ($blockingerrormsg) + { + $this->error = $blockingerrormsg; + return 1; + } + else + { + $this->output = 'Found '.($nbok + $nbko).' members to send reminder to.'; + $this->output.= ' Send email successfuly to '.$nbok.' members'; + if ($nbko) $this->output.= ' - Canceled for '.$nbko.' member (no email or email sending error)'; + } + + return 0; + } + } diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index 77f969181f4..21d3cb2eae5 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -646,7 +646,7 @@ if ($resql) elseif ($value == 'lang') { print ''; - print $formadmin->select_language($search_lang, 'search_lang', 0, null, 1); + print $formadmin->select_language($search_lang, 'search_lang', 0, null, 1, 0, 0, 'maxwidth150'); print ''; } elseif ($value == 'fk_user') @@ -661,7 +661,7 @@ if ($resql) elseif ($value == 'topic') print ''; elseif ($value == 'type_template') { - print ''.$form->selectarray('search_type_template', $elementList, $search_type_template, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100onsmartphone').''; + print ''.$form->selectarray('search_type_template', $elementList, $search_type_template, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth200 maxwidth100onsmartphone').''; } elseif (! in_array($value, array('content', 'content_lines'))) print ''; } @@ -867,7 +867,7 @@ if ($resql) print ""; // Modify link / Delete link - print ''; + print ''; if ($canbemodified) print ''.img_edit().''; if ($iserasable) { @@ -1016,7 +1016,7 @@ function fieldList($fieldlist, $obj='', $tabname='', $context='') } else { - print $form->selectarray('type_template', $elementList, (! empty($obj->{$fieldlist[$field]})?$obj->{$fieldlist[$field]}:''), 1); + print $form->selectarray('type_template', $elementList, (! empty($obj->{$fieldlist[$field]})?$obj->{$fieldlist[$field]}:''), 1, 0, 0, '', 0, 0, 0, '', 'maxwidth200'); } print ''; } diff --git a/htdocs/core/class/commonorder.class.php b/htdocs/core/class/commonorder.class.php index 8cacf7065b1..b3e5033330d 100644 --- a/htdocs/core/class/commonorder.class.php +++ b/htdocs/core/class/commonorder.class.php @@ -73,7 +73,7 @@ abstract class CommonOrderLine extends CommonObjectLine /** * Quantity - * @var int + * @var float */ public $qty; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 4cd3a9f0a72..9da4043fe3f 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5630,6 +5630,123 @@ class Form return $out; } + /** + * Return a HTML select string, built from an array of key+value but content returned into select come from an Ajax call of an URL. + * Note: Do not apply langs->trans function on returned content of Ajax service, content may be entity encoded twice. + * + * @param string $htmlname Name of html select area + * @param string $array Array (key=>array('text'=>'A text', 'url'=>'An url'), ...) + * @param string $id Preselected key + * @param string $moreparam Add more parameters onto the select tag + * @param int $disableFiltering If set to 1, results are not filtered with searched string + * @param int $disabled Html select box is disabled + * @param int $minimumInputLength Minimum Input Length + * @param string $morecss Add more class to css styles + * @param int $callurlonselect If set to 1, some code is added so an url return by the ajax is called when value is selected. + * @param string $placeholder String to use as placeholder + * @param integer $acceptdelayedhtml 1 if caller request to have html js content not returned but saved into global $delayedhtmlcontent (so caller can show it at end of page to avoid flash FOUC effect) + * @return string HTML select string + * @see ajax_combobox in ajax.lib.php + */ + static function selectArrayFilter($htmlname, $array, $id='', $moreparam='', $disableFiltering=0, $disabled=0, $minimumInputLength=1, $morecss='', $callurlonselect=0, $placeholder='', $acceptdelayedhtml=0) + { + global $conf, $langs; + global $delayedhtmlcontent; + + // TODO Use an internal dolibarr component instead of select2 + if (empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && ! defined('REQUIRE_JQUERY_MULTISELECT')) return ''; + + $out=''; + + $formattedarrayresult = array(); + + foreach($array as $key => $value) { + $o = new stdClass(); + $o->id = $key; + $o->text = $value['text']; + $o->url = $value['url']; + $formattedarrayresult[] = $o; + } + + $tmpplugin='select2'; + $outdelayed="\n".' + '; + + if ($acceptdelayedhtml) + { + $delayedhtmlcontent.=$outdelayed; + } + else + { + $out.=$outdelayed; + } + return $out; + } + /** * Show a multiselect form from an array. * diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 2b1c94889e3..0e5483396a0 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -912,7 +912,7 @@ class FormMail extends Form } } - // Complete substitution array + // Complete substitution array with the url to make online payment $paymenturl=''; if (empty($this->substit['__REF__'])) { @@ -930,7 +930,6 @@ class FormMail extends Form $url=getOnlinePaymentUrl(0, $typeforonlinepayment, $this->substit['__REF__']); $paymenturl=$url; } - $this->substit['__ONLINE_PAYMENT_URL__']=$paymenturl; //Add lines substitution key from each line @@ -1041,9 +1040,9 @@ class FormMail extends Form * * @param DoliDB $db Database handler * @param string $type_template Get message for type=$type_template, type='all' also included. - * @param string $user Use template public or limited to this user + * @param string $user Get template public or limited to this user * @param Translate $outputlangs Output lang object - * @param int $id Id of template to find, or -1 for first found with position 0, or 0 for first found whatever is position or -2 for exact match with label (no aswer if not found) + * @param int $id Id of template to find, or -1 for first found with position 0, or 0 for first found whatever is position (priority order depends on lang provided or not) or -2 for exact match with label (no answer if not found) * @param int $active 1=Only active template, 0=Only disabled, -1=All * @param string $label Label of template * @return ModelMail @@ -1058,7 +1057,7 @@ class FormMail extends Form return -1; } - $sql = "SELECT label, topic, joinfiles, content, content_lines, lang"; + $sql = "SELECT rowid, label, topic, joinfiles, content, content_lines, lang"; $sql.= " FROM ".MAIN_DB_PREFIX.'c_email_templates'; $sql.= " WHERE (type_template='".$db->escape($type_template)."' OR type_template='all')"; $sql.= " AND entity IN (".getEntity('c_email_templates').")"; @@ -1080,6 +1079,7 @@ class FormMail extends Form $obj = $db->fetch_object($resql); if ($obj) { + $ret->id = $obj->rowid; $ret->label = $obj->label; $ret->lang = $obj->lang; $ret->topic = $obj->topic; diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 3d92d5f9019..8fcdf53b4a6 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -177,20 +177,10 @@ class Ldap if ($connected) break; if (empty($host)) continue; - if (preg_match('/^ldap/',$host)) - { - if ($this->serverPing($host) === true) { - $this->connection = ldap_connect($host); - } - else continue; - } - else - { - if ($this->serverPing($host, $this->serverPort) === true) { - $this->connection = ldap_connect($host,$this->serverPort); - } - else continue; + if ($this->serverPing($host, $this->serverPort) === true) { + $this->connection = ldap_connect($host, $this->serverPort); } + else continue; if (is_resource($this->connection)) { @@ -742,6 +732,10 @@ class Ldap if (preg_match('/^ldaps:\/\/([^\/]+)\/?$/',$host, $regs)) { $host = 'ssl://'.$regs[1]; } + // Remove ldap:// + if (preg_match('/^ldap:\/\/([^\/]+)\/?$/',$host, $regs)) { + $host = $regs[1]; + } $op = @fsockopen($host, $port, $errno, $errstr, $timeout); if (!$op) return false; //DC is N/A else { diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php index e60070f1179..3314830b68a 100644 --- a/htdocs/core/class/utils.class.php +++ b/htdocs/core/class/utils.class.php @@ -47,7 +47,7 @@ class Utils * Purge files into directory of data files. * CAN BE A CRON TASK * - * @param string $choice Choice of purge mode ('tempfiles', 'tempfilesold' to purge temp older than 24h, 'allfiles', 'logfile') + * @param string $choice Choice of purge mode ('tempfiles', '' or 'tempfilesold' to purge temp older than 24h, 'allfiles', 'logfile') * @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK) */ function purgeFiles($choice='tempfilesold') @@ -129,7 +129,7 @@ class Utils } elseif ($filesarray[$key]['type'] == 'file') { - // If (file that is not logfile) or (if logfile with option logfile) + // If (file that is not logfile) or (if mode is logfile) if ($filesarray[$key]['fullname'] != $filelog || $choice=='logfile') { $result=dol_delete_file($filesarray[$key]['fullname'], 1, 1); @@ -138,7 +138,10 @@ class Utils $count++; $countdeleted++; } - else $counterror++; + else + { + $counterror++; + } } } } @@ -672,8 +675,8 @@ class Utils /** * This saves syslog files and compresses older ones * Used from cronjob - * - * @return int 0 if OK, < 0 if KO + * + * @return int 0 if OK, < 0 if KO */ function compressSyslogs() { global $conf; @@ -683,6 +686,7 @@ class Utils } if(! function_exists('gzopen')) { + $this->error = 'Support for gzopen not available in this PHP'; return -1; } @@ -690,7 +694,7 @@ class Utils $nbSaves = ! empty($conf->global->SYSLOG_FILE_SAVES) ? intval($conf->global->SYSLOG_FILE_SAVES) : 14; - if(empty($conf->global->SYSLOG_FILE)) { + if (empty($conf->global->SYSLOG_FILE)) { $mainlogdir = DOL_DATA_ROOT; $mainlog = 'dolibarr.log'; } else { @@ -707,7 +711,7 @@ class Utils $logname = $file['name']; $logpath = $file['path']; - // Handle already compressed files + // Handle already compressed files to rename them and add +1 $filter = '^'.preg_quote($logname, '/').'\.([0-9]+)\.gz$'; @@ -726,7 +730,7 @@ class Utils krsort($gzfiles, SORT_NUMERIC); foreach($gzfiles as $numsave => $dummy) { - if(dol_is_file($logpath.'/'.$logname.'.'.($numsave+1).'.gz')) { + if (dol_is_file($logpath.'/'.$logname.'.'.($numsave+1).'.gz')) { return -2; } @@ -738,18 +742,19 @@ class Utils } // Compress last save - - if(dol_is_file($logpath.'/'.$logname.'.1')) { + if (dol_is_file($logpath.'/'.$logname.'.1')) { if($nbSaves > 1) { $gzfilehandle = gzopen($logpath.'/'.$logname.'.2.gz', 'wb9'); - if(empty($gzfilehandle)) { + if (empty($gzfilehandle)) { + $this->error = 'Failted to open file '.$logpath.'/'.$logname.'.2.gz'; return -3; } $sourcehandle = fopen($logpath.'/'.$logname.'.1', 'r'); - if(empty($sourcehandle)) { + if (empty($sourcehandle)) { + $this->error = 'Failed to open file '.$logpath.'/'.$logname.'.1'; return -4; } @@ -766,14 +771,16 @@ class Utils // Compress current file et recreate it - if(dol_is_file($logpath.'/'.$logname)) { - if(dol_move($logpath.'/'.$logname, $logpath.'/'.$logname.'.1', 0, 1, 0, 0)) { + if (dol_is_file($logpath.'/'.$logname)) { + if (dol_move($logpath.'/'.$logname, $logpath.'/'.$logname.'.1', 0, 1, 0, 0)) + { $newlog = fopen($logpath.'/'.$logname, 'a+'); fclose($newlog); } } } + $this->output = 'Archive log files (keeping last SYSLOG_FILE_SAVES='.$nbSaves.' files) done.'; return 0; } } \ No newline at end of file diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index ea5a7bd9b85..6ea633f1f1d 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1278,6 +1278,7 @@ function dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$ $result=dol_delete_file("$dir/$item", 1, $nophperrors); $count++; if ($result) $countdeleted++; + //else print 'Error on '.$item."\n"; } } } @@ -1288,6 +1289,7 @@ function dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$ $result=dol_delete_dir($dir, $nophperrors); $count++; if ($result) $countdeleted++; + //else print 'Error on '.$dir."\n"; } } } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 2177559c0ab..746f6c55f13 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3082,7 +3082,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ $pictowithoutext = preg_replace('/(\.png|\.gif|\.svg)$/', '', $picto); //if (in_array($picto, array('switch_off', 'switch_on', 'off', 'on'))) - if (in_array($pictowithoutext, array('delete', 'edit', 'off', 'on', 'printer', 'resize', 'switch_off', 'switch_on', 'unlink', 'uparrow'))) + if (in_array($pictowithoutext, array('delete', 'edit', 'off', 'on', 'play', 'playdisabled', 'printer', 'resize', 'switch_off', 'switch_on', 'unlink', 'uparrow'))) { $fakey = $pictowithoutext; $facolor=''; $fasize=''; if ($pictowithoutext == 'switch_off') { $fakey = 'fa-toggle-off'; $facolor='#999'; $fasize='2em'; } @@ -3095,7 +3095,8 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ elseif ($pictowithoutext == 'resize') { $fakey = 'fa-crop'; $facolor='#444'; } elseif ($pictowithoutext == 'uparrow') { $fakey = 'fa-mail-forward'; $facolor='#555'; } elseif ($pictowithoutext == 'unlink') { $fakey = 'fa-chain-broken'; $facolor='#555'; } - else { $fakey = 'fa-'.$pictowithoutext; $facolor='#999'; } + elseif ($pictowithoutext == 'playdisabled') { $fakey = 'fa-play'; $facolor='#ccc'; } + else { $fakey = 'fa-'.$pictowithoutext; $facolor='#444'; } if (preg_match('/class="([^"]+)"/', $moreatt, $reg)) { $morecss.=($morecss?' ':'').$reg[1]; } $enabledisablehtml =''; @@ -5728,11 +5729,31 @@ function getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $ob $substitutionarray=array(); - if (empty($exclude) || ! in_array('system', $exclude)) + if (empty($exclude) || ! in_array('user', $exclude)) { - $substitutionarray['__(AnyTranslationKey)__']=$outputlangs->trans('TranslationOfKey'); - $substitutionarray['__[AnyConstantKey]__']=$outputlangs->trans('ValueOfConstant'); - $substitutionarray['__DOL_MAIN_URL_ROOT__']=DOL_MAIN_URL_ROOT; + // Add SIGNATURE into substitutionarray first, so, when we will make the substitution, + // this will include signature content first and then replace var found into content of signature + $signature = $user->signature; + $substitutionarray=array_merge($substitutionarray, array( + '__USER_SIGNATURE__' => (string) (($signature && empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? ($onlykey == 2 ? dol_trunc(dol_string_nohtmltag($signature), 30) : $signature) : '') + ) + ); + // For backward compatibility + if ($onlykey != 2) + { + $substitutionarray['__SIGNATURE__'] = (string) (($signature && empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? ($onlykey == 2 ? dol_trunc(dol_string_nohtmltag($signature), 30) : $signature) : ''); + } + + $substitutionarray=array_merge($substitutionarray, array( + '__USER_ID__' => (string) $user->id, + '__USER_LOGIN__' => (string) $user->login, + '__USER_LASTNAME__' => (string) $user->lastname, + '__USER_FIRSTNAME__' => (string) $user->firstname, + '__USER_FULLNAME__' => (string) $user->getFullName($outputlangs), + '__USER_SUPERVISOR_ID__' => (string) ($user->fk_user ? $user->fk_user : '0'), + '__USER_REMOTE_IP__' => (string) $_SERVER['REMOTE_ADDR'] + ) + ); } if ((empty($exclude) || ! in_array('mycompany', $exclude)) && is_object($mysoc)) { @@ -5803,7 +5824,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $ob $substitutionarray['__REFCLIENT__'] = (isset($object->ref_client) ? $object->ref_client : (isset($object->ref_customer) ? $object->ref_customer : '')); $substitutionarray['__REFSUPPLIER__'] = (isset($object->ref_supplier) ? $object->ref_supplier : ''); - // TODO USe this ? + // TODO Use this ? $msgishtml = 0; $birthday = dol_print_date($object->birth,'day'); @@ -5880,7 +5901,26 @@ function getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $ob } } - $substitutionarray['__ONLINE_PAYMENT_URL__'] = 'TODO'; + // Complete substitution array with the url to make online payment + $paymenturl=''; + if (empty($substitutionarray['__REF__'])) + { + $paymenturl=''; + } + else + { + // Set the online payment url link into __ONLINE_PAYMENT_URL__ key + require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; + $outputlangs->load('paypal'); + $typeforonlinepayment='free'; + if (is_object($object) && $object->element == 'commande') $typeforonlinepayment='order'; + if (is_object($object) && $object->element == 'facture') $typeforonlinepayment='invoice'; + if (is_object($object) && $object->element == 'member') $typeforonlinepayment='member'; + $url=getOnlinePaymentUrl(0, $typeforonlinepayment, $substitutionarray['__REF__']); + $paymenturl=$url; + } + + $substitutionarray['__ONLINE_PAYMENT_URL__']=$paymenturl; } } if (empty($exclude) || ! in_array('objectamount', $exclude)) @@ -5930,31 +5970,11 @@ function getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $ob )); } - if (empty($exclude) || ! in_array('user', $exclude)) + if (empty($exclude) || ! in_array('system', $exclude)) { - // Add SIGNATURE into substitutionarray first, so, when we will make the substitution, - // this will also replace var found into content of signature - $signature = $user->signature; - $substitutionarray=array_merge($substitutionarray, array( - '__USER_SIGNATURE__' => (string) (($signature && empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? ($onlykey == 2 ? dol_trunc(dol_string_nohtmltag($signature), 30) : $signature) : '') - ) - ); - // For backward compatibility - if ($onlykey != 2) - { - $substitutionarray['__SIGNATURE__'] = (string) (($signature && empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? ($onlykey == 2 ? dol_trunc(dol_string_nohtmltag($signature), 30) : $signature) : ''); - } - - $substitutionarray=array_merge($substitutionarray, array( - '__USER_ID__' => (string) $user->id, - '__USER_LOGIN__' => (string) $user->login, - '__USER_LASTNAME__' => (string) $user->lastname, - '__USER_FIRSTNAME__' => (string) $user->firstname, - '__USER_FULLNAME__' => (string) $user->getFullName($outputlangs), - '__USER_SUPERVISOR_ID__' => (string) ($user->fk_user ? $user->fk_user : '0'), - '__USER_REMOTE_IP__' => (string) $_SERVER['REMOTE_ADDR'] - ) - ); + $substitutionarray['__(AnyTranslationKey)__']=$outputlangs->trans('TranslationOfKey'); + $substitutionarray['__[AnyConstantKey]__']=$outputlangs->trans('ValueOfConstant'); + $substitutionarray['__DOL_MAIN_URL_ROOT__']=DOL_MAIN_URL_ROOT; } if (! empty($conf->multicompany->enabled)) { diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index e3a20533de0..dc223f58ec3 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -802,15 +802,15 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m } // Personalized field {XXX-1} à {XXX-9} - /*$maskperso=array(); + $maskperso=array(); $maskpersonew=array(); $tmpmask=$mask; - while (preg_match('/\{([A-Z]+)\-([1-9])\}/i',$tmpmask,$regKey)) + while (preg_match('/\{([A-Z]+)\-([1-9])\}/',$tmpmask,$regKey)) { - $maskperso[$regKey[1]]='\{'.$regKey[1]+'\-'.$regKey[2].'\}'; - $maskpersonew[$regKey[1]]=str_pad('', '_', $regKey[2], STR_PAD_RIGHT); - $tmpmask=preg_replace('/\{'.$regKey[1].'\-'.$regKey[2].'\}/i', $maskpersonew, $tmpmask); - }*/ + $maskperso[$regKey[1]]='{'.$regKey[1].'-'.$regKey[2].'}'; + $maskpersonew[$regKey[1]]=str_pad('', $regKey[2], '_', STR_PAD_RIGHT); + $tmpmask=preg_replace('/\{'.$regKey[1].'\-'.$regKey[2].'\}/i', $maskpersonew[$regKey[1]], $tmpmask); + } if (strstr($mask,'user_extra_')) { @@ -827,10 +827,10 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m $maskwithonlyymcode=preg_replace('/\{(c+)(0*)\}/i',$maskrefclient,$maskwithonlyymcode); $maskwithonlyymcode=preg_replace('/\{(t+)\}/i',$masktype_value,$maskwithonlyymcode); $maskwithonlyymcode=preg_replace('/\{(u+)\}/i',$maskuser_value,$maskwithonlyymcode); - /*foreach($maskperso as $key => $val) + foreach($maskperso as $key => $val) { - $maskwithonlyymcode=preg_replace('/'.$val.'/i', $maskpersonew[$key], $maskwithonlyymcode); - }*/ + $maskwithonlyymcode=preg_replace('/'.preg_quote($val,'/').'/i', $maskpersonew[$key], $maskwithonlyymcode); + } $maskwithnocode=$maskwithonlyymcode; $maskwithnocode=preg_replace('/\{yyyy\}/i','yyyy',$maskwithnocode); $maskwithnocode=preg_replace('/\{yy\}/i','yy',$maskwithnocode); @@ -974,6 +974,10 @@ function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$m if ($maskrefclient) $maskLike = str_replace(dol_string_nospecial('{'.$maskrefclient.'}'),str_pad("",dol_strlen($maskrefclient),"_"),$maskLike); if ($masktype) $maskLike = str_replace(dol_string_nospecial('{'.$masktype.'}'),$masktype_value,$maskLike); if ($maskuser) $maskLike = str_replace(dol_string_nospecial('{'.$maskuser.'}'),$maskuser_value,$maskLike); + foreach($maskperso as $key => $val) + { + $maskLike = str_replace(dol_string_nospecial($maskperso[$key]),$maskpersonew[$key],$maskLike); + } // Get counter in database $counter=0; diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 73f8e507caf..dbcce928ccf 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -190,7 +190,7 @@ function getOnlinePaymentUrl($mode, $type, $ref='', $amount='9.99', $freetag='yo } } } - if ($type == 'membersubscription') + if ($type == 'member' || $type == 'membersubscription') { $out=DOL_MAIN_URL_ROOT.'/public/payment/newpayment.php?source=membersubscription&ref='.($mode?'':''); if ($mode == 1) $out.='member_ref'; diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index c565f55c934..738a49fe81e 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -1209,12 +1209,10 @@ class pdf_einstein extends ModelePDFCommandes function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey="PdfOrderTitle") { global $conf,$langs,$hookmanager; + + // Translations + $outputlangs->loadLangs(array("main", "bills", "propal", "orders", "companies")); - $outputlangs->load("main"); - $outputlangs->load("bills"); - $outputlangs->load("propal"); - $outputlangs->load("companies"); - $outputlangs->load("orders"); $default_font_size = pdf_getPDFFontSize($outputlangs); pdf_pagehead($pdf,$outputlangs,$this->page_hauteur); diff --git a/htdocs/core/modules/contract/doc/pdf_strato.modules.php b/htdocs/core/modules/contract/doc/pdf_strato.modules.php index a42ac2c7e8d..62501d4881e 100644 --- a/htdocs/core/modules/contract/doc/pdf_strato.modules.php +++ b/htdocs/core/modules/contract/doc/pdf_strato.modules.php @@ -493,12 +493,11 @@ class pdf_strato extends ModelePDFContract function _pagehead(&$pdf, $object, $showaddress, $outputlangs) { global $conf,$langs; + $default_font_size = pdf_getPDFFontSize($outputlangs); - - $outputlangs->load("main"); - $outputlangs->load("dict"); - $outputlangs->load("companies"); - $outputlangs->load("contract"); + + // Translations + $outputlangs->loadLangs(array("main", "dict", "contract", "companies")); pdf_pagehead($pdf,$outputlangs,$this->page_hauteur); diff --git a/htdocs/core/modules/expedition/doc/pdf_merou.modules.php b/htdocs/core/modules/expedition/doc/pdf_merou.modules.php index c535d231a67..1609ef8283f 100644 --- a/htdocs/core/modules/expedition/doc/pdf_merou.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_merou.modules.php @@ -385,9 +385,9 @@ class pdf_merou extends ModelePdfExpedition { global $langs; $default_font_size = pdf_getPDFFontSize($outputlangs); - - $langs->load("main"); - $langs->load("bills"); + + // Translations + $langs->loadLangs(array("main", "bills")); if (empty($hidetop)) { diff --git a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php index 75db209b6d3..32fe36044b3 100644 --- a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php @@ -38,10 +38,25 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; */ class pdf_standard extends ModeleExpenseReport { - var $db; - var $name; - var $description; - var $type; + /** + * @var DoliDb Database handler + */ + public $db; + + /** + * @var string model name + */ + public $name; + + /** + * @var string model description (short text) + */ + public $description; + + /** + * @var string document type + */ + public $type; var $phpmin = array(4,3,0); // Minimum version of PHP required by module var $version = 'dolibarr'; @@ -512,10 +527,10 @@ class pdf_standard extends ModeleExpenseReport function _pagehead(&$pdf, $object, $showaddress, $outputlangs) { global $conf,$langs,$hookmanager; + + // Translations + $outputlangs->loadLangs(array("main", "trips", "companies")); - $outputlangs->load("main"); - $outputlangs->load("trips"); - $outputlangs->load("companies"); $default_font_size = pdf_getPDFFontSize($outputlangs); /* diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index e537331625e..17b652ed2db 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -42,24 +42,52 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; */ class pdf_crabe extends ModelePDFFactures { - var $db; - var $name; - var $description; - var $update_main_doc_field; // Save the name of generated file as the main doc when generating a doc with this template - var $type; + /** + * @var DoliDb Database handler + */ + public $db; - var $phpmin = array(4,3,0); // Minimum version of PHP required by module - var $version = 'dolibarr'; + /** + * @var string model name + */ + public $name; - var $page_largeur; - var $page_hauteur; - var $format; - var $marge_gauche; - var $marge_droite; - var $marge_haute; - var $marge_basse; + /** + * @var string model description (short text) + */ + public $description; - var $emetteur; // Objet societe qui emet + /** + * @var int Save the name of generated file as the main doc when generating a doc with this template + */ + public $update_main_doc_field; + + /** + * @var string document type + */ + public $type; + + /** + * @var array() Minimum version of PHP required by module. + * e.g.: PHP ≥ 5.3 = array(5, 3) + */ + public $phpmin = array(5, 2); + + /** + * Dolibarr version of the loaded document + * @public string + */ + public $version = 'dolibarr'; + + public $page_largeur; + public $page_hauteur; + public $format; + public $marge_gauche; + public $marge_droite; + public $marge_haute; + public $marge_basse; + + public $emetteur; // Objet societe qui emet /** * @var bool Situation invoice type @@ -1514,12 +1542,10 @@ class pdf_crabe extends ModelePDFFactures */ function _pagehead(&$pdf, $object, $showaddress, $outputlangs) { - global $conf,$langs; - - $outputlangs->load("main"); - $outputlangs->load("bills"); - $outputlangs->load("propal"); - $outputlangs->load("companies"); + global $conf, $langs; + + // Translations + $outputlangs->loadLangs(array("main", "bills", "propal", "companies")); $default_font_size = pdf_getPDFFontSize($outputlangs); diff --git a/htdocs/core/modules/modAdherent.class.php b/htdocs/core/modules/modAdherent.class.php index d26836fa646..f3369d58582 100644 --- a/htdocs/core/modules/modAdherent.class.php +++ b/htdocs/core/modules/modAdherent.class.php @@ -324,6 +324,12 @@ class modAdherent extends DolibarrModules $this->import_fieldshidden_array[$r]=array('extra.fk_object'=>'lastrowid-'.MAIN_DB_PREFIX.'adherent'); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent) $this->import_regex_array[$r]=array('a.civility'=>'code@'.MAIN_DB_PREFIX.'c_civility','a.fk_adherent_type'=>'rowid@'.MAIN_DB_PREFIX.'adherent_type','a.morphy'=>'(phy|mor)','a.statut'=>'^[0|1]','a.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$','a.datefin'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$'); $this->import_examplevalues_array[$r]=array('a.civility'=>"MR",'a.lastname'=>'Smith','a.firstname'=>'John','a.login'=>'jsmith','a.pass'=>'passofjsmith','a.fk_adherent_type'=>'1','a.morphy'=>'"mor" or "phy"','a.societe'=>'JS company','a.address'=>'21 jump street','a.zip'=>'55000','a.town'=>'New York','a.country'=>'1','a.email'=>'jsmith@example.com','a.birth'=>'1972-10-10','a.statut'=>"0 or 1",'a.note_public'=>"This is a public comment on member",'a.note_private'=>"This is private comment on member",'a.datec'=>dol_print_date($now,'%Y-%m__%d'),'a.datefin'=>dol_print_date(dol_time_plus_duree($now, 1, 'y'),'%Y-%m-%d')); + + // Cronjobs + $this->cronjobs = array( + 0=>array('label'=>'SendReminderForExpiredSubscription', 'jobtype'=>'method', 'class'=>'adherents/class/adherent.class.php', 'objectname'=>'Adherent', 'method'=>'sendReminderForExpiredSubscription', 'parameters'=>'10', 'comment'=>'sendReminderForExpiredSubscription', 'frequency'=>1, 'unitfrequency'=> 3600 * 24, 'priority'=>50, 'status'=>0, 'test'=>true), + ); + } diff --git a/htdocs/core/modules/modSyslog.class.php b/htdocs/core/modules/modSyslog.class.php index 39a4c93951b..fca192f5ec0 100644 --- a/htdocs/core/modules/modSyslog.class.php +++ b/htdocs/core/modules/modSyslog.class.php @@ -82,7 +82,7 @@ class modSyslog extends DolibarrModules // Cronjobs $this->cronjobs = array( - 0=>array('label'=>'CompressSyslogs', 'jobtype'=>'method', 'class'=>'core/class/utils.class.php', 'objectname'=>'Utils', 'method'=>'compressSyslogs', 'parameters'=>'', 'comment'=>'PurgeDeleteTemporaryFiles', 'frequency'=>1, 'unitfrequency'=> 3600 * 24, 'priority'=>50, 'status'=>0, 'test'=>true), + 0=>array('label'=>'CompressSyslogs', 'jobtype'=>'method', 'class'=>'core/class/utils.class.php', 'objectname'=>'Utils', 'method'=>'compressSyslogs', 'parameters'=>'', 'comment'=>'Compress and archive log files', 'frequency'=>1, 'unitfrequency'=> 3600 * 24, 'priority'=>50, 'status'=>0, 'test'=>true), ); } } diff --git a/htdocs/cron/list.php b/htdocs/cron/list.php index f6a695d4a39..1bb68fe5cd9 100644 --- a/htdocs/cron/list.php +++ b/htdocs/cron/list.php @@ -311,8 +311,8 @@ if ($action == 'execute') $arrayofmassactions = array( //'presend'=>$langs->trans("SendByMail"), //'builddoc'=>$langs->trans("PDFMerge"), - 'enable'=>$langs->trans("Enable"), - 'disable'=>$langs->trans("Disable"), + 'enable'=>$langs->trans("CronStatusActiveBtn"), + 'disable'=>$langs->trans("CronStatusInactiveBtn"), ); if ($user->rights->mymodule->delete) $arrayofmassactions['predelete']=$langs->trans("Delete"); if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array(); @@ -527,16 +527,16 @@ if ($num > 0) } if ($user->rights->cron->execute) { - if (!empty($obj->status)) print "rowid."&action=execute".(empty($conf->global->CRON_KEY)?'':'&securitykey='.$conf->global->CRON_KEY).($sortfield?'&sortfield='.$sortfield:'').($sortorder?'&sortorder='.$sortorder:'').$param."\" title=\"".dol_escape_htmltag($langs->trans('CronExecute'))."\">".img_picto($langs->trans('CronExecute'),"play").""; - else print "trans('JobDisabled'))."\">".img_picto($langs->trans('JobDisabled'),"playdisabled").""; + if (!empty($obj->status)) print 'global->CRON_KEY)?'':'&securitykey='.$conf->global->CRON_KEY).($sortfield?'&sortfield='.$sortfield:'').($sortorder?'&sortorder='.$sortorder:'').$param."\" title=\"".dol_escape_htmltag($langs->trans('CronExecute'))."\">".img_picto($langs->trans('CronExecute'),"play").''; + else print ''.img_picto($langs->trans('JobDisabled'),"playdisabled").''; } else { - print "trans('NotEnoughPermissions'))."\">".img_picto($langs->trans('NotEnoughPermissions'),"playdisabled").""; + print ''.img_picto($langs->trans('NotEnoughPermissions'),"playdisabled").''; } if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined { $selected=0; if (in_array($obj->rowid, $arrayofselected)) $selected=1; - print '   '; + print '   '; } print ''; diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index 23744912c9b..c653c756bba 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -261,21 +261,28 @@ if ($action == 'update') // Update $verif = $object->update($user); - if ($verif > 0) - { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; - } - else - { - // Otherwise we display the request form with the SQL error message - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&error=SQL_Create&msg='.$object->error); - exit; - } + + if ($verif <= 0) + { + setEventMessages($object->error, $object->errors, 'warnings'); + $action='edit'; + } + else + { + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + exit; + } } - } else { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; + else + { + setEventMessages($langs->trans("NotEnoughPermissions"), null, 'errors'); + $action=''; + } + } + else + { + setEventMessages($langs->trans("ErrorBadStatus"), null, 'errors'); + $action=''; } } @@ -299,7 +306,9 @@ if ($action == 'confirm_delete' && GETPOST('confirm') == 'yes' && $user->rights- } else { - $error = $langs->trans('ErrorCantDeleteCP'); + $error++; + setEventMessages($langs->trans('ErrorCantDeleteCP'), null, 'errors'); + $action=''; } } @@ -393,24 +402,26 @@ if ($action == 'confirm_send') $trackid='leav'.$object->id; - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, null, null, null, '', '', 0, 0, '', '', $trackid); + $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 0, '', '', $trackid); // Envoi du mail $result=$mail->sendfile(); if (!$result) { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&error=mail&error_content='.$mail->error); - exit; + setEventMessages($mail->error, $mail->errors, 'warnings'); + $action=''; + } + else + { + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + exit; } - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; } else { - // Sinon on affiche le formulaire de demande avec le message d'erreur SQL - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&error=SQL_Create&msg='.$object->error); - exit; + setEventMessages($object->error, $object->errors, 'errors'); + $action=''; } } } @@ -481,31 +492,33 @@ if ($action == 'confirm_valid') $trackid='leav'.$object->id; - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, null, null, null, '', '', 0, 0, '', '', $trackid); + $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 0, '', '', $trackid); // Envoi du mail $result=$mail->sendfile(); - if (!$result) { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&error=mail&error_content='.$mail->error); - exit; + if (!$result) + { + setEventMessages($mail->error, $mail->errors, 'warnings'); + $action=''; + } + else + { + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + exit; } - - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; - } else { - // Sinon on affiche le formulaire de demande avec le message d'erreur SQL - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&error=SQL_Create&msg='.$object->error); - exit; } - + else + { + setEventMessages($object->error, $object->errors, 'errors'); + $action=''; + } } - } -if ($action == 'confirm_refuse') +if ($action == 'confirm_refuse' && GETPOST('confirm','alpha') == 'yes') { - if (! empty($_POST['detail_refuse'])) + if (! empty($_POST['detail_refuse'])) { $object = new Holiday($db); $object->fetch($id); @@ -513,10 +526,10 @@ if ($action == 'confirm_refuse') // Si statut en attente de validation et valideur = utilisateur if ($object->statut == 2 && $user->id == $object->fk_validator) { - $object->date_refuse = date('Y-m-d H:i:s', time()); + $object->date_refuse = dol_print_date('dayhour', dol_now()); $object->fk_user_refuse = $user->id; $object->statut = 5; - $object->detail_refuse = $_POST['detail_refuse']; + $object->detail_refuse = GETPOST('detail_refuse','alphanohtml'); $verif = $object->update($user); @@ -558,29 +571,31 @@ if ($action == 'confirm_refuse') $trackid='leav'.$object->id; - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, null, null, null, '', '', 0, 0, '', '', $trackid); + $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 0, '', '', $trackid); // Envoi du mail $result=$mail->sendfile(); - if(!$result) { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&error=mail&error_content='.$mail->error); - exit; + if (!$result) + { + setEventMessages($mail->error, $mail->errors, 'warnings'); + $action=''; + } + else + { + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + exit; } - - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; - } else { - // Sinon on affiche le formulaire de demande avec le message d'erreur SQL - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&error=SQL_Create&msg='.$object->error); - exit; } - + else + { + setEventMessages($object->error, $object->errors, 'errors'); + $action=''; + } } - } else { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&error=NoMotifRefuse'); - exit; + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DetailRefusCP")), null, 'errors'); + $action='refuse'; } } @@ -588,6 +603,8 @@ if ($action == 'confirm_refuse') // Si Validation de la demande if ($action == 'confirm_draft' && GETPOST('confirm') == 'yes') { + $error = 0; + $object = new Holiday($db); $object->fetch($id); @@ -597,7 +614,8 @@ if ($action == 'confirm_draft' && GETPOST('confirm') == 'yes') $result = $object->update($user); if ($result < 0) { - $error = $langs->trans('ErrorBackToDraft'); + $error++; + setEventMessages($langs->trans('ErrorBackToDraft').' '.$object->error, $object->errors, 'errors'); } if (! $error) @@ -616,6 +634,8 @@ if ($action == 'confirm_draft' && GETPOST('confirm') == 'yes') // Si Validation de la demande if ($action == 'confirm_cancel' && GETPOST('confirm') == 'yes') { + $error = 0; + $object = new Holiday($db); $object->fetch($id); @@ -647,7 +667,8 @@ if ($action == 'confirm_cancel' && GETPOST('confirm') == 'yes') if ($result1 < 0 || $result2 < 0) { - $error = $langs->trans('ErrorCantDeleteCP'); + $error++; + setEventMessages($langs->trans('ErrorCantDeleteCP').' '.$object->error, $object->errors, 'errors'); } } @@ -697,27 +718,22 @@ if ($action == 'confirm_cancel' && GETPOST('confirm') == 'yes') $trackid='leav'.$object->id; - $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, null, null, null, '', '', 0, 0, '', '', $trackid); + $mail = new CMailFile($subject, $emailTo, $emailFrom, $message, array(), array(), array(), '', '', 0, 0, '', '', $trackid); // Envoi du mail $result=$mail->sendfile(); - if(!$result) + if (!$result) { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&error=mail&error_content='.$mail->error); - exit; + setEventMessages($mail->error, $mail->errors, 'warnings'); + $action=''; + } + else + { + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + exit; } - - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; } - else - { - // Sinon on affiche le formulaire de demande avec le message d'erreur SQL - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.'&error=SQL_Create&msg='.$object->error); - exit; - } - } } @@ -1010,48 +1026,8 @@ else // On vérifie si l'utilisateur à le droit de lire cette demande if ($cancreate) { - if ($action == 'delete') - { - if ($user->rights->holiday->delete) - { - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleDeleteCP"),$langs->trans("ConfirmDeleteCP"),"confirm_delete", '', 0, 1); - } - } - - // Si envoi en validation - if ($action == 'sendToValidate' && $object->statut == 1) - { - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleToValidCP"),$langs->trans("ConfirmToValidCP"),"confirm_send", '', 1, 1); - } - - // Si validation de la demande - if ($action == 'valid') - { - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleValidCP"),$langs->trans("ConfirmValidCP"),"confirm_valid", '', 1, 1); - } - - // Si refus de la demande - if ($action == 'refuse') - { - $array_input = array(array('type'=>"text",'label'=> $langs->trans('DetailRefusCP'),'name'=>"detail_refuse",'size'=>"50",'value'=>"")); - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id."&action=confirm_refuse", $langs->trans("TitleRefuseCP"), $langs->trans('ConfirmRefuseCP'), "confirm_refuse", $array_input, 1, 0); - } - - // Si annulation de la demande - if ($action == 'cancel') - { - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleCancelCP"),$langs->trans("ConfirmCancelCP"),"confirm_cancel", '', 1, 1); - } - - // Si back to draft - if ($action == 'backtodraft') - { - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleSetToDraft"),$langs->trans("ConfirmSetToDraft"),"confirm_draft", '', 1, 1); - } - $head=holiday_prepare_head($object); - if ($action == 'edit' && $object->statut == 1) { $edit = true; @@ -1244,6 +1220,47 @@ else dol_fiche_end(); + // Confirmation messages + if ($action == 'delete') + { + if ($user->rights->holiday->delete) + { + print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleDeleteCP"),$langs->trans("ConfirmDeleteCP"),"confirm_delete", '', 0, 1); + } + } + + // Si envoi en validation + if ($action == 'sendToValidate' && $object->statut == 1) + { + print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleToValidCP"),$langs->trans("ConfirmToValidCP"),"confirm_send", '', 1, 1); + } + + // Si validation de la demande + if ($action == 'valid') + { + print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleValidCP"),$langs->trans("ConfirmValidCP"),"confirm_valid", '', 1, 1); + } + + // Si refus de la demande + if ($action == 'refuse') + { + $array_input = array(array('type'=>"text",'label'=> $langs->trans('DetailRefusCP'),'name'=>"detail_refuse",'size'=>"50",'value'=>"")); + print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id."&action=confirm_refuse", $langs->trans("TitleRefuseCP"), $langs->trans('ConfirmRefuseCP'), "confirm_refuse", $array_input, 1, 0); + } + + // Si annulation de la demande + if ($action == 'cancel') + { + print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleCancelCP"),$langs->trans("ConfirmCancelCP"),"confirm_cancel", '', 1, 1); + } + + // Si back to draft + if ($action == 'backtodraft') + { + print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id,$langs->trans("TitleSetToDraft"),$langs->trans("ConfirmSetToDraft"),"confirm_draft", '', 1, 1); + } + + if ($action == 'edit' && $object->statut == 1) { print '
'; diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index 67ef15c74ef..1e12f9f87eb 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -276,12 +276,12 @@ class Holiday extends CommonObject } /** - * List holidays for a particular user + * List holidays for a particular user or list of users * - * @param int $user_id ID of user to list - * @param string $order Sort order - * @param string $filter SQL Filter - * @return int -1 if KO, 1 if OK, 2 if no result + * @param int|string $user_id ID of user to list, or comma separated list of IDs of users to list + * @param string $order Sort order + * @param string $filter SQL Filter + * @return int -1 if KO, 1 if OK, 2 if no result */ function fetchByUser($user_id, $order='', $filter='') { @@ -321,8 +321,8 @@ class Holiday extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."holiday as cp, ".MAIN_DB_PREFIX."user as uu, ".MAIN_DB_PREFIX."user as ua"; $sql.= " WHERE cp.entity IN (".getEntity('holiday').")"; - $sql.= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid "; // Hack pour la recherche sur le tableau - $sql.= " AND cp.fk_user = ".$user_id; + $sql.= " AND cp.fk_user = uu.rowid AND cp.fk_validator = ua.rowid"; // Hack pour la recherche sur le tableau + $sql.= " AND cp.fk_user IN (".$user_id.")"; // Filtre de séléction if(!empty($filter)) { diff --git a/htdocs/install/mysql/data/llx_c_email_templates.sql b/htdocs/install/mysql/data/llx_c_email_templates.sql index 3a99e44cd8b..ad8d8ffd199 100644 --- a/htdocs/install/mysql/data/llx_c_email_templates.sql +++ b/htdocs/install/mysql/data/llx_c_email_templates.sql @@ -20,7 +20,9 @@ -- de l'install et tous les sigles '--' sont supprimés. -- -INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,enabled,active,topic,content,content_lines) VALUES (0,'adherent','member','',0,null,null,'(SendAnEMailToMember)',1,1,1,'__(CardContent)__','__(Hello)__,

\n\n__(ThisIsContentOfYourCard)__
\n__(ID)__ : __ID__
\n__(Civiliyty)__ : __MEMBER_CIVILITY__
\n__(Firstname)__ : __MEMBER_FIRSTNAME__
\n__(Lastname)__ : __MEMBER_LASTNAME__
\n__(Fullname)__ : __MEMBER_FULLNAME__
\n__(Company)__ : __MEMBER_COMPANY__
\n__(Address)__ : __MEMBER_ADDRESS__
\n__(Zip)__ : __MEMBER_ZIP__
\n__(Town)__ : __MEMBER_TOWN__
\n__(Country)__ : __MEMBER_COUNTRY__
\n__(Email)__ : __MEMBER_EMAIL__
\n__(Birthday)__ : __MEMBER_BIRTH__
\n__(Photo)__ : __MEMBER_PHOTO__
\n__(Login)__ : __MEMBER_LOGIN__
\n__(Password)__ : __MEMBER_PASSWORD__
\n__(Phone)__ : __MEMBER_PHONE__
\n__(PhonePerso)__ : __MEMBER_PHONEPRO__
\n__(PhoneMobile)__ : __MEMBER_PHONEMOBILE__

\n__(Sincerely)__
__USER_SIGNATURE__',null); +INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,enabled,active,topic,content,content_lines) VALUES (0,'adherent','member','',0,null,null,'(SendAnEMailToMember)',1,1,1,'[__[MAIN_INFO_SOCIETE_NOM]__] __(CardContent)__','__(Hello)__,

\n\n__(ThisIsContentOfYourCard)__
\n__(ID)__ : __ID__
\n__(Civiliyty)__ : __MEMBER_CIVILITY__
\n__(Firstname)__ : __MEMBER_FIRSTNAME__
\n__(Lastname)__ : __MEMBER_LASTNAME__
\n__(Fullname)__ : __MEMBER_FULLNAME__
\n__(Company)__ : __MEMBER_COMPANY__
\n__(Address)__ : __MEMBER_ADDRESS__
\n__(Zip)__ : __MEMBER_ZIP__
\n__(Town)__ : __MEMBER_TOWN__
\n__(Country)__ : __MEMBER_COUNTRY__
\n__(Email)__ : __MEMBER_EMAIL__
\n__(Birthday)__ : __MEMBER_BIRTH__
\n__(Photo)__ : __MEMBER_PHOTO__
\n__(Login)__ : __MEMBER_LOGIN__
\n__(Password)__ : __MEMBER_PASSWORD__
\n__(Phone)__ : __MEMBER_PHONE__
\n__(PhonePerso)__ : __MEMBER_PHONEPRO__
\n__(PhoneMobile)__ : __MEMBER_PHONEMOBILE__

\n__(Sincerely)__
__USER_SIGNATURE__',null); +INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,enabled,active,topic,content,content_lines) VALUES (0,'adherent','member','',0,null,null,'(SendReminderForExpiredSubscriptionTitle)',1,1,1,'[__[MAIN_INFO_SOCIETE_NOM]__] __(YourSubscriptionHasExpired)__','__(Hello)__ __MEMBER_FULLNAME__,

\n\n__(ThisIsContentOfSubscriptionReminderEmail)__
\n
__ONLINE_PAYMENT_URL__
\n

\n__(Sincerely)__
__USER_SIGNATURE__',null); + INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,enabled,active,topic,content,content_lines) VALUES (0,'banque','thirdparty','',0,null,null,'(YourSEPAMandate)',1,1,0,'__(YourSEPAMandate)__','__(Hello)__,

\n\n__(FindYourSEPAMandate)__ :
\n__MYCOMPANY_NAME__
\n__MYCOMPANY_FULLADDRESS__

\n__(Sincerely)__
\n__USER_SIGNATURE__',null); diff --git a/htdocs/install/mysql/migration/7.0.0-8.0.0.sql b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql index 35813d8b635..c1d7e59cbed 100644 --- a/htdocs/install/mysql/migration/7.0.0-8.0.0.sql +++ b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql @@ -304,3 +304,9 @@ ALTER TABLE llx_societe_account ADD CONSTRAINT llx_societe_account_fk_societe FO ALTER TABLE llx_societe_rib MODIFY COLUMN max_total_amount_of_all_payments double(24,8); ALTER TABLE llx_societe_rib MODIFY COLUMN total_amount_of_all_payments double(24,8); + + +INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,enabled,active,topic,content,content_lines) VALUES (0,'adherent','member','',0,null,null,'(SendAnEMailToMember)',1,1,1,'[__[MAIN_INFO_SOCIETE_NOM]__] __(CardContent)__','__(Hello)__,

\n\n__(ThisIsContentOfYourCard)__
\n__(ID)__ : __ID__
\n__(Civiliyty)__ : __MEMBER_CIVILITY__
\n__(Firstname)__ : __MEMBER_FIRSTNAME__
\n__(Lastname)__ : __MEMBER_LASTNAME__
\n__(Fullname)__ : __MEMBER_FULLNAME__
\n__(Company)__ : __MEMBER_COMPANY__
\n__(Address)__ : __MEMBER_ADDRESS__
\n__(Zip)__ : __MEMBER_ZIP__
\n__(Town)__ : __MEMBER_TOWN__
\n__(Country)__ : __MEMBER_COUNTRY__
\n__(Email)__ : __MEMBER_EMAIL__
\n__(Birthday)__ : __MEMBER_BIRTH__
\n__(Photo)__ : __MEMBER_PHOTO__
\n__(Login)__ : __MEMBER_LOGIN__
\n__(Password)__ : __MEMBER_PASSWORD__
\n__(Phone)__ : __MEMBER_PHONE__
\n__(PhonePerso)__ : __MEMBER_PHONEPRO__
\n__(PhoneMobile)__ : __MEMBER_PHONEMOBILE__

\n__(Sincerely)__
__USER_SIGNATURE__',null); +INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,enabled,active,topic,content,content_lines) VALUES (0,'adherent','member','',0,null,null,'(SendReminderForExpiredSubscriptionTitle)',1,1,1,'[__[MAIN_INFO_SOCIETE_NOM]__] __(YourSubscriptionHasExpired)__','__(Hello)__ __MEMBER_FULLNAME__,

\n\n__(ThisIsContentOfSubscriptionReminderEmail)__
\n
__ONLINE_PAYMENT_URL__
\n

\n__(Sincerely)__
__USER_SIGNATURE__',null); + + diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index bfa338605f2..befb763d60c 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -179,4 +179,8 @@ ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS=Product used for subscription line into in NameOrCompany=Name or company SubscriptionRecorded=Subscription recorded NoEmailSentToMember=No email sent to member -EmailSentToMember=Email sent to member at %s \ No newline at end of file +EmailSentToMember=Email sent to member at %s +SendReminderForExpiredSubscriptionTitle=Send reminder by email for expired subscription +SendReminderForExpiredSubscription=Send reminder by email to members when subscription is about to expire (parameter is number of days before end of subscription to send the remind) +YourSubscriptionHasExpired=Your subscription has expired +ThisIsContentOfSubscriptionReminderEmail=This is an email to remind you that your subscription is about to expire. diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 115155e629a..c3bd5c184c0 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1619,19 +1619,19 @@ function left_menu($menu_array_before, $helppagename='', $notused='', $menu_arra if ($conf->browser->layout == 'phone') $conf->global->MAIN_USE_OLD_SEARCH_FORM=1; // Select into select2 is awfull on smartphone. TODO Is this still true with select2 v4 ? print "\n"; + + if (! is_object($form)) $form=new Form($db); + $selected=-1; + $usedbyinclude=1; + include_once DOL_DOCUMENT_ROOT.'/core/ajax/selectsearchbox.php'; // This set $arrayresult + if ($conf->use_javascript_ajax && empty($conf->global->MAIN_USE_OLD_SEARCH_FORM)) { - if (! is_object($form)) $form=new Form($db); - $selected=-1; - $searchform.=$form->selectArrayAjax('searchselectcombo', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, '', '', 0, 1, 'vmenusearchselectcombo', 1, $langs->trans("Search"), 1); + //$searchform.=$form->selectArrayAjax('searchselectcombo', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, '', '', 0, 1, 'vmenusearchselectcombo', 1, $langs->trans("Search"), 1); + $searchform.=$form->selectArrayFilter('searchselectcombo', $arrayresult, $selected, '', 1, 0, 1, 'vmenusearchselectcombo', 1, $langs->trans("Search"), 1); } else { - if (! is_object($form)) $form=new Form($db); - $selected=-1; - $usedbyinclude=1; - include_once DOL_DOCUMENT_ROOT.'/core/ajax/selectsearchbox.php'; - foreach($arrayresult as $key => $val) { //$searchform.=printSearchForm($val['url'], $val['url'], $val['label'], 'maxwidth100', 'sall', $val['shortcut'], 'searchleft', img_picto('',$val['img'])); diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 96baf02c7d8..1a7b336b4bc 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -46,7 +46,7 @@ require_once DOL_DOCUMENT_ROOT.'/societe/class/societeaccount.class.php'; // Security check // No check on module enabled. Done later according to $validpaymentmethod -$langs->loadLangs(array("main","other","dict","bills","companies","errors","paybox")); // File with generic data +$langs->loadLangs(array("main","other","dict","bills","companies","errors","paybox","paypal")); // File with generic data $action=GETPOST('action','aZ09'); @@ -157,8 +157,6 @@ $urlko=preg_replace('/&$/','',$urlko); // Remove last & if (! empty($conf->paypal->enabled)) { - $langs->load("paypal"); - require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php'; require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php'; @@ -867,7 +865,7 @@ if ($source == 'order') { print ''."\n"; } - print ''."\n"; + if (is_object($order->thirdparty)) print ''."\n"; print ''."\n"; print ''."\n"; $labeldesc=$langs->trans("Order").' '.$order->ref; @@ -1002,7 +1000,7 @@ if ($source == 'invoice') { print ''."\n"; } - print ''."\n"; + if (is_object($invoice->thirdparty)) print ''."\n"; print ''."\n"; print ''."\n"; $labeldesc=$langs->trans("Invoice").' '.$invoice->ref; @@ -1210,7 +1208,7 @@ if ($source == 'contractline') { print ''."\n"; } - print ''."\n"; + if (is_object($contract->thirdparty)) print ''."\n"; print ''."\n"; print ''."\n"; $labeldesc=$langs->trans("Contract").' '.$contract->ref; @@ -1236,8 +1234,8 @@ if ($source == 'membersubscription') } else { + $member->fetch_thirdparty(); $object = $member; - $subscription=new Subscription($db); } @@ -1374,6 +1372,7 @@ if ($source == 'membersubscription') { print ''."\n"; } + if (is_object($member->thirdparty)) print ''."\n"; print ''."\n"; $labeldesc = $langs->trans("PaymentSubscription"); if (GETPOST('desc','alpha')) $labeldesc=GETPOST('desc','alpha'); diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index d046c325eca..d56e5b1e22a 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -399,6 +399,7 @@ $sql.= " s.email, s.phone, s.url, s.siren as idprof1, s.siret as idprof2, s.ape $sql.= " s.tms as date_update, s.datec as date_creation,"; $sql.= " s.code_compta,s.code_compta_fournisseur,"; $sql.= " typent.code as typent_code,"; +$sql.= " country.code as country_code,"; $sql.= " state.code_departement as state_code, state.nom as state_name,"; $sql.= " region.code_region as region_code, region.nom as region_name"; // We'll need these fields in order to filter by sale (including the case where the user can only see his prospects) @@ -1091,7 +1092,7 @@ while ($i < min($num, $limit)) } if (! empty($arrayfields['s.phone']['checked'])) { - print "".$obj->phone."\n"; + print "".dol_print_phone($obj->phone, $obj->country_code, 0, $obj->rowid)."\n"; if (! $i) $totalarray['nbfield']++; } if (! empty($arrayfields['s.url']['checked'])) diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index d266094b53b..1eeec0c189f 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -627,6 +627,9 @@ textarea.centpercent { .paddingright2 { padding-: 2px; } +.cursordefault { + cursor: default; +} .cursorpointer { cursor: pointer; } @@ -996,9 +999,14 @@ select.selectarrowonleft option { width: 95%; } + select { + padding-top: 4px; + padding-bottom: 5px; + } input, input[type=text], input[type=password], select, textarea { min-width: 20px; - min-height: 1.4em; + font-size: px; + /* min-height: 1.4em; */ /* line-height: 1.4em; */ /* padding: .4em .1em; */ /* border-bottom: 1px solid #BBB; */ diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 88ef5d5caaa..a9ff6ebd09b 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -628,6 +628,9 @@ textarea.centpercent { .paddingright2 { padding-: 2px; } +.cursordefault { + cursor: default; +} .cursorpointer { cursor: pointer; } @@ -985,10 +988,15 @@ select.selectarrowonleft option { width: 95%; } + select { + padding-top: 4px; + padding-bottom: 5px; + } input, input[type=text], input[type=password], select, textarea { min-width: 20px; min-height: 1.4em; line-height: 1.4em; + font-size: px; /* padding: .4em .1em; */ /* border-bottom: 1px solid #BBB; */ /* max-width: inherit; why this */