diff --git a/.github/workflows/exakat.yml b/.github/workflows/exakat.yml index 3cfc4f8ba23..c2f8cc12765 100644 --- a/.github/workflows/exakat.yml +++ b/.github/workflows/exakat.yml @@ -13,5 +13,5 @@ jobs: - name: Exakat uses: docker://exakat/exakat-ga with: - ignore_rules: 'Classes/UseInstanceof,Performances/PrePostIncrement,Functions/UndefinedFunctions,Functions/WrongNumberOfArguments,Functions/WrongTypeWithCall,Variables/UndefinedVariable,Classes/DontUnsetProperties,Classes/NonPpp,Classes/StaticMethodsCalledFromObject,Classes/UseClassOperator,Functions/UsesDefaultArguments,Php/NoClassInGlobal,Php/ShouldUseCoalesce,Php/WrongTypeForNativeFunction,Structures/MergeIfThen,Structures/ElseIfElseif,Structures/RepeatedPrint,Structures/SameConditions,Structures/SwitchWithoutDefault,Structures/ShouldMakeTernary,Structures/UselessParenthesis,Structures/UseConstant' + ignore_rules: 'Classes/UseInstanceof,Performances/PrePostIncrement,Functions/UndefinedFunctions,Functions/WrongNumberOfArguments,Functions/WrongTypeWithCall,Variables/UndefinedVariable,Classes/DontUnsetProperties,Classes/NonPpp,Classes/StaticMethodsCalledFromObject,Classes/UseClassOperator,Functions/UsesDefaultArguments,Php/NoClassInGlobal,Php/ShouldUseCoalesce,Php/WrongTypeForNativeFunction,Structures/AddZero,Structures/DropElseAfterReturn,Structures/IfWithSameConditions,Structures/MergeIfThen,Structures/ElseIfElseif,Structures/ExitUsage,Structures/RepeatedPrint,Structures/RepeatedRegex,Structures/SameConditions,Structures/SwitchWithoutDefault,Structures/ShouldMakeTernary,Structures/UselessParenthesis,Structures/UseConstant' ignore_dirs: '/htdocs/includes,/build,/dev,/doc,/scripts,/test' \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 639183de6ff..3ae9f554f26 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,6 @@ os: linux dist: xenial #dist: bionic -# Deprecated: The key sudo has no effect anymore. -#sudo: required language: php @@ -33,49 +31,25 @@ addons: # We need pgloader for import mysql database into pgsql - pgloader -php: -- '5.6' -- '7.4' -- nightly - env: global: # Set to true for very verbose output - DEBUG=false - jobs: - # MariaDB overrides MySQL installation so it's not possible to test both yet - #- DB=mariadb - - DB=mysql - - DB=postgresql - # See https://docs.travis-ci.com/user/languages/php/#Apache-%2B-PHP - #- WS=apache - # See https://github.com/DracoBlue/travis-ci-nginx-php-fpm-test - #- WS=nginx jobs: fast_finish: true allow_failures: - php: nightly - # We exclude some combinations not usefull to save Travis CPU - exclude: - - php: '7.0' - env: DB=mysql - - php: '7.1' - env: DB=mysql - - php: '7.2' - env: DB=mysql - - php: '7.3' - env: DB=mysql - - php: '7.0' - env: DB=postgresql - - php: '7.1' - env: DB=postgresql - - php: '7.2' - env: DB=postgresql - - php: '7.3' - env: DB=postgresql - - php: nightly - env: DB=postgresql + include: + - if: type = push + php: '5.6' + env: DB=postgresql + - if: type = pull_request OR type = push + php: '7.4' + env: DB=mysql + - if: type = push AND branch = develop + php: nightly + env: DB=mysql notifications: email: @@ -146,7 +120,7 @@ install: - | echo "Adding path of binaries tools installed by composer to the PATH" - export PATH="$TRAVIS_BUILD_DIR/htdocs/includes/bin:$TRAVIS_BUILD_DIR/vendor/bin:$TRAVIS_BUILD_DIR/htdocs/includes:$PATH" + export PATH="$TRAVIS_BUILD_DIR/htdocs/includes/bin:$PATH" echo $PATH ls $TRAVIS_BUILD_DIR/vendor ls $TRAVIS_BUILD_DIR/htdocs/includes/bin @@ -426,7 +400,7 @@ script: php step5.php 12.0.0 13.0.0 > $TRAVIS_BUILD_DIR/upgrade12001300-3.log # Enable modules not enabled into original dump - php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_API,MAIN_MODULE_SUPPLIERPROPOSAL,MAIN_MODULE_WEBSITE,MAIN_MODULE_TICKET,MAIN_MODULE_ACCOUNTING,MAIN_MODULE_MRP > $TRAVIS_BUILD_DIR/enablemodule.log + php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_API,MAIN_MODULE_SUPPLIERPROPOSAL,MAIN_MODULE_WEBSITE,MAIN_MODULE_TICKET,MAIN_MODULE_ACCOUNTING,MAIN_MODULE_MRP,MAIN_MODULE_RECRUITMENT > $TRAVIS_BUILD_DIR/enablemodule.log echo $? cd - set +e diff --git a/build/generate_filelist_xml.php b/build/generate_filelist_xml.php index 581353b758b..41c20740d78 100755 --- a/build/generate_filelist_xml.php +++ b/build/generate_filelist_xml.php @@ -125,6 +125,11 @@ $checksumconcat=array(); $outputfile=$outputdir.'/filelist-'.$release.'.xml'; $fp = fopen($outputfile, 'w'); +if (empty($fp)) { + print 'Failed to open file '.$outputfile."\n"; + exit(-1); +} + fputs($fp, ''."\n"); fputs($fp, ''."\n"); diff --git a/htdocs/accountancy/bookkeeping/balance.php b/htdocs/accountancy/bookkeeping/balance.php index a930ed12852..232444b7d97 100644 --- a/htdocs/accountancy/bookkeeping/balance.php +++ b/htdocs/accountancy/bookkeeping/balance.php @@ -227,8 +227,8 @@ if ($action != 'export_csv') $moreforfilter .= $form->selectDate($search_date_end ? $search_date_end : -1, 'date_end', 0, 0, 1, '', 1, 0); $moreforfilter .= ' - '; - $moreforfilter .= $langs->trans('ShowSubtotalByGroup').': '; - $moreforfilter .= ''; + $moreforfilter .= ': '; + $moreforfilter .= ''; $moreforfilter .= ''; @@ -272,6 +272,8 @@ if ($action != 'export_csv') $total_credit = 0; $sous_total_debit = 0; $sous_total_credit = 0; + $total_opening_balance = 0; + $sous_total_opening_balance = 0; $displayed_account = ""; $accountingaccountstatic = new AccountingAccount($db); @@ -302,7 +304,13 @@ if ($action != 'export_csv') $link = ''; $total_debit += $line->debit; $total_credit += $line->credit; - $root_account_description = $object->get_compte_racine($line->numero_compte); + $opening_balance = isset($opening_balances["'".$line->numero_compte."'"]) ? $opening_balances["'".$line->numero_compte."'"] : 0; + $total_opening_balance += $opening_balance; + + $tmparrayforrootaccount = $object->getRootAccount($line->numero_compte); + $root_account_description = $tmparrayforrootaccount['label']; + $root_account_number = $tmparrayforrootaccount['account_number']; + if (empty($accountingaccountstatic->account_number)) { $link = ''.img_edit_add().''; } @@ -311,14 +319,14 @@ if ($action != 'export_csv') if (!empty($show_subgroup)) { // Show accounting account - if (empty($displayed_account) || $root_account_description != $displayed_account) { + if (empty($displayed_account) || $root_account_number != $displayed_account) { // Show subtotal per accounting account if ($displayed_account != "") { print ''; print ''.$langs->trans("SubTotal").':'; print ''.price($sous_total_debit).''; print ''.price($sous_total_credit).''; - print ''.price(price2num($sous_total_credit - $sous_total_debit)).''; + print ''.price(price2num($sous_total_opening_balance + $sous_total_credit - $sous_total_debit)).''; print "\n"; print ''; } @@ -328,18 +336,18 @@ if ($action != 'export_csv') print ''.$line->numero_compte.($root_account_description ? ' - '.$root_account_description : '').''; print ''; - $displayed_account = $root_account_description; + $displayed_account = $root_account_number; $sous_total_debit = 0; $sous_total_credit = 0; + $sous_total_opening_balance = 0; } } - // $object->get_compte_racine($line->numero_compte); print ''.$accounting_account.''; - print ''.price($opening_balances["'".$line->numero_compte."'"]).''; + print ''.price($opening_balance).''; print ''.price($line->debit).''; print ''.price($line->credit).''; - print ''.price(price2num($line->debit - $line->credit, 'MT')).''; + print ''.price(price2num($opening_balance + $line->debit - $line->credit, 'MT')).''; print ''.$link; print ''; print "\n"; @@ -347,16 +355,17 @@ if ($action != 'export_csv') // Records the sub-total $sous_total_debit += $line->debit; $sous_total_credit += $line->credit; + $sous_total_opening_balance += $opening_balance; } if (!empty($show_subgroup)) { - print ''.$langs->trans("SubTotal").':'.price($sous_total_debit).''.price($sous_total_credit).''.price(price2num($sous_total_debit - $sous_total_credit)).''; + print ''.$langs->trans("SubTotal").':'.price($sous_total_debit).''.price($sous_total_credit).''.price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit, 'MT')).''; print "\n"; print ''; } - print ''.$langs->trans("AccountBalance").':'.price($total_debit).''.price($total_credit).''.price(price2num($total_debit - $total_credit)).''; + print ''.$langs->trans("AccountBalance").':'.price($total_debit).''.price($total_credit).''.price(price2num($total_opening_balance + $total_debit - $total_credit, 'MT')).''; print "\n"; print ''; diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 299a9700364..097eb38b47f 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -630,7 +630,7 @@ else $buttonLabel = $langs->trans("ExportList"); $parameters = array(); $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { -// Button re-export + // Button re-export if (!empty($conf->global->ACCOUNTING_REEXPORT)) { $newcardbutton = '' . img_picto($langs->trans("Activated"), 'switch_on') . ' '; } else { diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 505c51d27fe..8312b155b8b 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1898,23 +1898,22 @@ class BookKeeping extends CommonObject return $out; } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Description of a root accounting account + * Return id and description of a root accounting account. + * This function takes the parent of parent to get the root account ! * * @param string $account Accounting account * @return string Root account */ - public function get_compte_racine($account = null) + public function getRootAccount($account = null) { - // phpcs:enable global $conf; $pcgver = $conf->global->CHARTOFACCOUNTS; - $sql = "SELECT root.account_number, root.label as label"; + $sql = "SELECT root.rowid, root.account_number, root.label as label"; $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as aa"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; - $sql .= " AND asy.rowid = ".$pcgver; + $sql .= " AND asy.rowid = ".((int) $pcgver); $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as parent ON aa.account_parent = parent.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as root ON parent.account_parent = root.rowid"; $sql .= " WHERE aa.account_number = '".$this->db->escape($account)."'"; @@ -1930,7 +1929,7 @@ class BookKeeping extends CommonObject $obj = $this->db->fetch_object($resql); } - return $obj->label; + return array('id'=>$obj->rowid, 'account_number'=>$obj->account_number, 'label'=>$obj->label); } else { $this->error = "Error ".$this->db->lasterror(); dol_syslog(__METHOD__." ".$this->error, LOG_ERR); diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 9bedb1a39ca..15494596e0f 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1988,11 +1988,11 @@ class Adherent extends CommonObject * @param int $withpictoimg 0=No picto, 1=Include picto into link, 2=Only picto, -1=Include photo into link, -2=Only picto photo, -3=Only photo very small) * @param int $maxlen length max label * @param string $option Page for link ('card', 'category', 'subscription', ...) - * @param string $mode ''=Show firstname+lastname as label (using default order), 'firstname'=Show only firstname, 'login'=Show login, 'ref'=Show ref + * @param string $mode ''=Show firstname+lastname as label (using default order), 'firstname'=Show only firstname, 'lastname'=Show only lastname, 'login'=Show login, 'ref'=Show ref * @param string $morecss Add more css on link * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking * @param int $notooltip 1=Disable tooltip - * @param int $addlinktonotes 1=Add link to notes + * @param int $addlinktonotes 1=Add link to notes * @return string Chaine avec URL */ public function getNomUrl($withpictoimg = 0, $maxlen = 0, $option = 'card', $mode = '', $morecss = '', $save_lastsearch_value = -1, $notooltip = 0, $addlinktonotes = 0) @@ -2072,7 +2072,7 @@ class Adherent extends CommonObject } elseif ($mode == 'ref') { $result .= $this->id; } else { - $result .= $this->getFullName($langs, '', ($mode == 'firstname' ? 2 : -1), $maxlen); + $result .= $this->getFullName($langs, '', ($mode == 'firstname' ? 2 : ($mode == 'lastname' ? 4 : -1)), $maxlen); } if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result .= ''; } diff --git a/htdocs/adherents/class/subscription.class.php b/htdocs/adherents/class/subscription.class.php index aebd48963d2..713812b639b 100644 --- a/htdocs/adherents/class/subscription.class.php +++ b/htdocs/adherents/class/subscription.class.php @@ -250,11 +250,16 @@ class Subscription extends CommonObject $this->db->begin(); + if (!is_numeric($this->amount)) { + $this->error = 'BadValueForParameterAmount'; + return -1; + } + $sql = "UPDATE ".MAIN_DB_PREFIX."subscription SET "; $sql .= " fk_type = ".$this->fk_type.","; $sql .= " fk_adherent = ".$this->fk_adherent.","; $sql .= " note=".($this->note ? "'".$this->db->escape($this->note)."'" : 'null').","; - $sql .= " subscription = '".price2num($this->amount)."',"; + $sql .= " subscription = ".price2num($this->amount).","; $sql .= " dateadh='".$this->db->idate($this->dateh)."',"; $sql .= " datef='".$this->db->idate($this->datef)."',"; $sql .= " datec='".$this->db->idate($this->datec)."',"; diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 611542b8ebc..1c4e42da1fe 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -333,7 +333,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! $listofpaths = array(); $listofnames = array(); $listofmimes = array(); - if (is_object($object->invoice)) { + if (is_object($object->invoice) && (!is_object($arraydefaultmessage) || intval($arraydefaultmessage->joinfiles))) { $invoicediroutput = $conf->facture->dir_output; $fileparams = dol_most_recent_file($invoicediroutput.'/'.$object->invoice->ref, preg_quote($object->invoice->ref, '/').'[^\-]+'); $file = $fileparams['fullname']; diff --git a/htdocs/adherents/subscription/list.php b/htdocs/adherents/subscription/list.php index b8cfb64a39f..05a0567a8d9 100644 --- a/htdocs/adherents/subscription/list.php +++ b/htdocs/adherents/subscription/list.php @@ -433,9 +433,7 @@ while ($i < min($num, $limit)) { // Lastname if (!empty($arrayfields['d.lastname']['checked'])) { - $adherent->firstname = ''; - print ''.$adherent->getNomUrl(-1).''; - $adherent->firstname = $obj->firstname; + print ''.$adherent->getNomUrl(-1, 0, 'card', 'lastname').''; if (!$i) $totalarray['nbfield']++; } // Firstname diff --git a/htdocs/admin/bom.php b/htdocs/admin/bom.php index db3bc348716..19ca39c21f3 100644 --- a/htdocs/admin/bom.php +++ b/htdocs/admin/bom.php @@ -232,8 +232,10 @@ foreach ($dirmodels as $reldir) // Show example of numbering model print ''; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; - elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/chequereceipts.php b/htdocs/admin/chequereceipts.php index 4fee30d274e..8c2acb5dc8b 100644 --- a/htdocs/admin/chequereceipts.php +++ b/htdocs/admin/chequereceipts.php @@ -168,8 +168,10 @@ foreach ($dirmodels as $reldir) // Show example of numbering module print ''; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; - elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/commande.php b/htdocs/admin/commande.php index 594052500ca..daf015f68eb 100644 --- a/htdocs/admin/commande.php +++ b/htdocs/admin/commande.php @@ -297,8 +297,10 @@ foreach ($dirmodels as $reldir) // Show example of numbering model print ''; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; - elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index 8b900f552c8..75dcb9b179f 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -406,11 +406,12 @@ print ''; print ''."\n"; +// Zip print ''; -print ''."\n"; +print ''."\n"; print ''; -print ''."\n"; +print ''."\n"; // Country print ''; diff --git a/htdocs/admin/contract.php b/htdocs/admin/contract.php index bfdff79cc1f..517a547cea6 100644 --- a/htdocs/admin/contract.php +++ b/htdocs/admin/contract.php @@ -229,7 +229,11 @@ foreach ($dirmodels as $reldir) // Show example of numbering model print ''; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) { $langs->load("errors"); print '
'.$langs->trans($tmp).'
'; } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } + elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/delivery.php b/htdocs/admin/delivery.php index d9c1b2ebe17..3707c395437 100644 --- a/htdocs/admin/delivery.php +++ b/htdocs/admin/delivery.php @@ -229,7 +229,8 @@ foreach ($dirmodels as $reldir) print ''; $tmp = $module->getExample(); if (preg_match('/^Error/', $tmp)) { - $langs->load("errors"); print '
'.$langs->trans($tmp).'
'; + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/expedition.php b/htdocs/admin/expedition.php index b446851b539..9e65af2d06c 100644 --- a/htdocs/admin/expedition.php +++ b/htdocs/admin/expedition.php @@ -234,7 +234,8 @@ foreach ($dirmodels as $reldir) print ''; $tmp = $module->getExample(); if (preg_match('/^Error/', $tmp)) { - $langs->load("errors"); print '
'.$langs->trans($tmp).'
'; + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/expensereport.php b/htdocs/admin/expensereport.php index f572226c379..8ffd4ab58c0 100644 --- a/htdocs/admin/expensereport.php +++ b/htdocs/admin/expensereport.php @@ -238,8 +238,10 @@ foreach ($dirmodels as $reldir) // Show example of numbering model print ''; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; - elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php index 35dd1002b12..7da8044ee07 100644 --- a/htdocs/admin/facture.php +++ b/htdocs/admin/facture.php @@ -313,8 +313,10 @@ foreach ($dirmodels as $reldir) // Show example of numbering module print ''; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; - elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/fichinter.php b/htdocs/admin/fichinter.php index 64660b67365..3d9e23cf61c 100644 --- a/htdocs/admin/fichinter.php +++ b/htdocs/admin/fichinter.php @@ -291,8 +291,10 @@ foreach ($dirmodels as $reldir) // Show example of numbering model print ''; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; - elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/holiday.php b/htdocs/admin/holiday.php index be09a062703..9a3845ace5b 100644 --- a/htdocs/admin/holiday.php +++ b/htdocs/admin/holiday.php @@ -229,7 +229,10 @@ foreach ($dirmodels as $reldir) // Show example of numbering model print ''; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) { $langs->load("errors"); print '
'.$langs->trans($tmp).'
'; } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print ''."\n"; diff --git a/htdocs/admin/ihm.php b/htdocs/admin/ihm.php index ec6ab640125..ad2cd408471 100644 --- a/htdocs/admin/ihm.php +++ b/htdocs/admin/ihm.php @@ -241,8 +241,8 @@ print ''; clearstatcache(); print '
'; -print ''; -print ''; +print '
'.$langs->trans("Language").'
'; +print ''; print ''; // Default language diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index 448d2bb4bfb..872c0d414eb 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -268,6 +268,7 @@ if (empty($reshook)) { if ($value == 'content') continue; if ($value == 'content_lines') continue; + // Rename some POST variables into a generic name if (GETPOST('actionmodify', 'alpha') && $value == 'topic') $_POST['topic'] = $_POST['topic-'.$rowid]; if ((!isset($_POST[$value]) || $_POST[$value] == '' || $_POST[$value] == '-1') && $value != 'lang' && $value != 'fk_user' && $value != 'position') @@ -306,6 +307,7 @@ if (empty($reshook)) { if ($value == 'lang') $keycode = 'langcode'; if (empty($keycode)) $keycode = $value; + // Clean input variables if ($value == 'entity') $_POST[$keycode] = $conf->entity; if ($value == 'fk_user' && !($_POST[$keycode] > 0)) $_POST[$keycode] = ''; if ($value == 'private' && !is_numeric($_POST[$keycode])) $_POST[$keycode] = '0'; @@ -319,11 +321,11 @@ if (empty($reshook)) { if (!$user->admin) { // A non admin user can only edit its own template $sql .= " ".((int) $user->id); } else { - $sql .= " ".((int) GETPOST($keycode, 'fk_user')); + $sql .= " ".((int) GETPOST($keycode, 'int')); } } elseif ($keycode == 'content') { $sql .= "'".$db->escape(GETPOST($keycode, 'restricthtml'))."'"; - } elseif (in_array($keycode, array('joinfile', 'private', 'position'))) { + } elseif (in_array($keycode, array('joinfiles', 'private', 'position'))) { $sql .= (int) GETPOST($keycode, 'int'); } else { $sql .= "'".$db->escape(GETPOST($keycode, 'nohtml'))."'"; @@ -362,6 +364,7 @@ if (empty($reshook)) { if ($field == 'lang') $keycode = 'langcode'; if (empty($keycode)) $keycode = $field; + // Rename some POST variables into a generic name if ($field == 'fk_user' && !($_POST['fk_user'] > 0)) $_POST['fk_user'] = ''; if ($field == 'topic') $_POST['topic'] = $_POST['topic-'.$rowid]; if ($field == 'joinfiles') $_POST['joinfiles'] = $_POST['joinfiles-'.$rowid]; @@ -378,11 +381,11 @@ if (empty($reshook)) { if (!$user->admin) { // A non admin user can only edit its own template $sql .= " ".((int) $user->id); } else { - $sql .= " ".((int) GETPOST($keycode, 'fk_user')); + $sql .= " ".((int) GETPOST($keycode, 'int')); } } elseif ($keycode == 'content') { $sql .= "'".$db->escape(GETPOST($keycode, 'restricthtml'))."'"; - } elseif (in_array($keycode, array('joinfile', 'private', 'position'))) { + } elseif (in_array($keycode, array('joinfiles', 'private', 'position'))) { $sql .= (int) GETPOST($keycode, 'int'); } else { $sql .= "'".$db->escape(GETPOST($keycode, 'nohtml'))."'"; @@ -393,7 +396,7 @@ if (empty($reshook)) { $sql .= " WHERE ".$rowidcol." = ".((int) $rowid); if (!$user->admin) { // A non admin user can only edit its own template - $sql .= " AND fk_user = ".$user->id; + $sql .= " AND fk_user = ".((int) $user->id); } //print $sql;exit; dol_syslog("actionmodify", LOG_DEBUG); @@ -414,7 +417,7 @@ if (empty($reshook)) { $sql = "DELETE from ".$tabname[$id]." WHERE ".$rowidcol."=".((int) $rowid); if (!$user->admin) { // A non admin user can only edit its own template - $sql .= " AND fk_user = ".$user->id; + $sql .= " AND fk_user = ".((int) $user->id); } dol_syslog("delete", LOG_DEBUG); $result = $db->query($sql); diff --git a/htdocs/admin/menus/edit.php b/htdocs/admin/menus/edit.php index 6181754e979..f182fb39cbd 100644 --- a/htdocs/admin/menus/edit.php +++ b/htdocs/admin/menus/edit.php @@ -34,13 +34,14 @@ $langs->loadLangs(array("other", "admin")); $cancel = GETPOST('cancel', 'alphanohtml'); // We click on a Cancel button $confirm = GETPOST('confirm'); -if (!$user->admin) accessforbidden(); +if (!$user->admin) { + accessforbidden(); +} $dirstandard = array(); $dirsmartphone = array(); $dirmenus = array_merge(array("/core/menus/"), (array) $conf->modules_parts['menus']); -foreach ($dirmenus as $dirmenu) -{ +foreach ($dirmenus as $dirmenu) { $dirstandard[] = $dirmenu.'standard'; $dirsmartphone[] = $dirmenu.'smartphone'; } @@ -56,8 +57,12 @@ $menu_handler_smartphone = preg_replace('/_frontoffice.php/i', '', $menu_handler $menu_handler = $menu_handler_top; -if (GETPOST("handler_origine")) $menu_handler = GETPOST("handler_origine"); -if (GETPOST("menu_handler")) $menu_handler = GETPOST("menu_handler"); +if (GETPOST("handler_origine")) { + $menu_handler = GETPOST("handler_origine"); +} +if (GETPOST("menu_handler")) { + $menu_handler = GETPOST("menu_handler"); +} @@ -65,22 +70,16 @@ if (GETPOST("menu_handler")) $menu_handler = GETPOST("menu_handler"); * Actions */ -if ($action == 'update') -{ - if (!$cancel) - { +if ($action == 'update') { + if (!$cancel) { $leftmenu = ''; $mainmenu = ''; - if (GETPOST('menuIdParent', 'alphanohtml') && !is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) - { + if (GETPOST('menuIdParent', 'alphanohtml') && !is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) { $tmp = explode('&', GETPOST('menuIdParent', 'alphanohtml')); - foreach ($tmp as $s) - { - if (preg_match('/fk_mainmenu=/', $s)) - { + foreach ($tmp as $s) { + if (preg_match('/fk_mainmenu=/', $s)) { $mainmenu = preg_replace('/fk_mainmenu=/', '', $s); } - if (preg_match('/fk_leftmenu=/', $s)) - { + if (preg_match('/fk_leftmenu=/', $s)) { $leftmenu = preg_replace('/fk_leftmenu=/', '', $s); } } @@ -88,31 +87,31 @@ if ($action == 'update') $menu = new Menubase($db); $result = $menu->fetch(GETPOST('menuId', 'int')); - if ($result > 0) - { - $menu->title = GETPOST('titre', 'alphanohtml'); - $menu->leftmenu = GETPOST('leftmenu', 'aZ09'); - $menu->url = GETPOST('url', 'alphanohtml'); - $menu->langs = GETPOST('langs', 'alphanohtml'); - $menu->position = GETPOST('position', 'int'); - $menu->enabled = GETPOST('enabled', 'alphanohtml'); - $menu->perms = GETPOST('perms', 'alphanohtml'); - $menu->target = GETPOST('target', 'alphanohtml'); - $menu->user = GETPOST('user', 'alphanohtml'); - $menu->mainmenu = GETPOST('propertymainmenu', 'alphanohtml'); - if (is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) - { - $menu->fk_menu = GETPOST('menuIdParent', 'alphanohtml'); + if ($result > 0) { + $menu->title = (string) GETPOST('titre', 'alphanohtml'); + $menu->leftmenu = (string) GETPOST('leftmenu', 'aZ09'); + $menu->url = (string) GETPOST('url', 'alphanohtml'); + $menu->langs = (string) GETPOST('langs', 'alphanohtml'); + $menu->position = (int) GETPOST('position', 'int'); + $menu->enabled = (string) GETPOST('enabled', 'alphanohtml'); + $menu->perms = (string) GETPOST('perms', 'alphanohtml'); + $menu->target = (string) GETPOST('target', 'alphanohtml'); + $menu->user = (string) GETPOST('user', 'alphanohtml'); + $menu->mainmenu = (string) GETPOST('propertymainmenu', 'alphanohtml'); + if (is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) { + $menu->fk_menu = (int) GETPOST('menuIdParent', 'alphanohtml'); } else { - if (GETPOST('type', 'alphanohtml') == 'top') $menu->fk_menu = 0; - else $menu->fk_menu = -1; + if (GETPOST('type', 'alphanohtml') == 'top') { + $menu->fk_menu = 0; + } else { + $menu->fk_menu = -1; + } $menu->fk_mainmenu = $mainmenu; $menu->fk_leftmenu = $leftmenu; } $result = $menu->update($user); - if ($result > 0) - { + if ($result > 0) { setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs'); } else { setEventMessages($menu->error, $menu->errors, 'errors'); @@ -130,26 +129,21 @@ if ($action == 'update') } } -if ($action == 'add') -{ - if ($cancel) - { +if ($action == 'add') { + if ($cancel) { header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler); exit; } - $leftmenu = ''; $mainmenu = ''; - if (GETPOST('menuId', 'alphanohtml', 3) && !is_numeric(GETPOST('menuId', 'alphanohtml', 3))) - { + $leftmenu = ''; + $mainmenu = ''; + if (GETPOST('menuId', 'alphanohtml', 3) && !is_numeric(GETPOST('menuId', 'alphanohtml', 3))) { $tmp = explode('&', GETPOST('menuId', 'alphanohtml', 3)); - foreach ($tmp as $s) - { - if (preg_match('/fk_mainmenu=/', $s)) - { + foreach ($tmp as $s) { + if (preg_match('/fk_mainmenu=/', $s)) { $mainmenu = preg_replace('/fk_mainmenu=/', '', $s); } - if (preg_match('/fk_leftmenu=/', $s)) - { + if (preg_match('/fk_leftmenu=/', $s)) { $leftmenu = preg_replace('/fk_leftmenu=/', '', $s); } } @@ -158,70 +152,64 @@ if ($action == 'add') $langs->load("errors"); $error = 0; - if (!$error && !$_POST['menu_handler']) - { + if (!$error && !$_POST['menu_handler']) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("MenuHandler")), null, 'errors'); $action = 'create'; $error++; } - if (!$error && !$_POST['type']) - { + if (!$error && !$_POST['type']) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors'); $action = 'create'; $error++; } - if (!$error && !$_POST['url']) - { + if (!$error && !$_POST['url']) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("URL")), null, 'errors'); $action = 'create'; $error++; } - if (!$error && !$_POST['titre']) - { + if (!$error && !$_POST['titre']) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Title")), null, 'errors'); $action = 'create'; $error++; } - if (!$error && $_POST['menuId'] && $_POST['type'] == 'top') - { + if (!$error && $_POST['menuId'] && $_POST['type'] == 'top') { setEventMessages($langs->trans("ErrorTopMenuMustHaveAParentWithId0"), null, 'errors'); $action = 'create'; $error++; } - if (!$error && !$_POST['menuId'] && $_POST['type'] == 'left') - { + if (!$error && !$_POST['menuId'] && $_POST['type'] == 'left') { setEventMessages($langs->trans("ErrorLeftMenuMustHaveAParentId"), null, 'errors'); $action = 'create'; $error++; } - if (!$error) - { + if (!$error) { $menu = new Menubase($db); $menu->menu_handler = preg_replace('/_menu$/', '', GETPOST('menu_handler', 'aZ09')); - $menu->type = GETPOST('type', 'alphanohtml'); - $menu->title = GETPOST('titre', 'alphanohtml'); - $menu->url = GETPOST('url', 'alphanohtml'); - $menu->langs = GETPOST('langs', 'alphanohtml'); - $menu->position = GETPOST('position', 'int'); - $menu->enabled = GETPOST('enabled', 'alphanohtml'); - $menu->perms = GETPOST('perms', 'alphanohtml'); - $menu->target = GETPOST('target', 'alphanohtml'); - $menu->user = GETPOST('user', 'alphanohtml'); - $menu->mainmenu = GETPOST('propertymainmenu', 'alphanohtml'); - if (is_numeric(GETPOST('menuId', 'alphanohtml', 3))) - { - $menu->fk_menu = GETPOST('menuId', 'alphanohtml', 3); + $menu->type = (string) GETPOST('type', 'alphanohtml'); + $menu->title = (string) GETPOST('titre', 'alphanohtml'); + $menu->url = (string) GETPOST('url', 'alphanohtml'); + $menu->langs = (string) GETPOST('langs', 'alphanohtml'); + $menu->position = (int) GETPOST('position', 'int'); + $menu->enabled = (string) GETPOST('enabled', 'alphanohtml'); + $menu->perms = (string) GETPOST('perms', 'alphanohtml'); + $menu->target = (string) GETPOST('target', 'alphanohtml'); + $menu->user = (string) GETPOST('user', 'alphanohtml'); + $menu->mainmenu = (string) GETPOST('propertymainmenu', 'alphanohtml'); + if (is_numeric(GETPOST('menuId', 'alphanohtml', 3))) { + $menu->fk_menu = (int) GETPOST('menuId', 'alphanohtml', 3); } else { - if (GETPOST('type', 'alphanohtml') == 'top') $menu->fk_menu = 0; - else $menu->fk_menu = -1; + if (GETPOST('type', 'alphanohtml') == 'top') { + $menu->fk_menu = 0; + } else { + $menu->fk_menu = -1; + } $menu->fk_mainmenu = $mainmenu; $menu->fk_leftmenu = $leftmenu; } $result = $menu->create($user); - if ($result > 0) - { + if ($result > 0) { header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".GETPOST('menu_handler', 'aZ09')); exit; } else { @@ -232,15 +220,13 @@ if ($action == 'add') } // delete -if ($action == 'confirm_delete' && $confirm == 'yes') -{ +if ($action == 'confirm_delete' && $confirm == 'yes') { $db->begin(); $sql = "DELETE FROM ".MAIN_DB_PREFIX."menu WHERE rowid = ".GETPOST('menuId', 'int'); $result = $db->query($sql); - if ($result == 0) - { + if ($result == 0) { $db->commit(); llxHeader(); @@ -268,8 +254,7 @@ $formadmin = new FormAdmin($db); llxHeader('', $langs->trans("Menu")); -if ($action == 'create') -{ +if ($action == 'create') { print ''; } $this->info_box_contents[0][] = array( - 'tr'=>'class="nohover showiffilter'.$this->boxcode.' hideobject"', + 'tr' => 'class="nohover showiffilter'.$this->boxcode.' hideobject"', 'td' => 'class="nohover"', 'textnoformat' => $boxcontent, ); diff --git a/htdocs/core/boxes/intracommreport_box.php b/htdocs/core/boxes/intracommreport_box.php deleted file mode 100644 index d7c383138b6..00000000000 --- a/htdocs/core/boxes/intracommreport_box.php +++ /dev/null @@ -1,88 +0,0 @@ - - * Copyright (C) - * - * 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 core/boxes/mybox.php - * \ingroup intracommreport - * \brief This file is a sample box definition file - * Put some comments here - */ -include_once DOL_DOCUMENT_ROOT."/core/boxes/modules_boxes.php"; - -/** - * Class to manage the box - */ -class intracommreportbox extends ModeleBoxes -{ - - public $boxcode = "mybox"; - public $boximg = "intracommreport"; - public $boxlabel; - public $depends = array("intracommreport"); - public $db; - public $param; - public $info_box_head = array(); - public $info_box_contents = array(); - - /** - * Constructor - */ - public function __construct() - { - global $langs; - $langs->load("boxes"); - - $this->boxlabel = $langs->transnoentitiesnoconv("MyBox"); - } - - /** - * Load data into info_box_contents array to show array later. - * - * @param int $max Maximum number of records to load - * @return void - */ - public function loadBox($max = 5) - { - global $conf, $user, $langs, $db; - - $this->max = $max; - - //include_once DOL_DOCUMENT_ROOT . "/intracommreport/class/intracommreport.class.php"; - - $text = $langs->trans("MyBoxDescription", $max); - $this->info_box_head = array( - 'text' => $text, - 'limit' => dol_strlen($text) - ); - - $this->info_box_contents[0][0] = array('td' => 'align="left"', - 'text' => $langs->trans("MyBoxContent")); - } - - /** - * Method to show box - * - * @param array $head Array with properties of box title - * @param array $contents Array with properties of box lines - * @return void - */ - public function showBox($head = null, $contents = null) - { - parent::showBox($this->info_box_head, $this->info_box_contents); - } -} diff --git a/htdocs/core/boxes/modules_boxes.php b/htdocs/core/boxes/modules_boxes.php index 2ac7ee05c6b..1e32a28f25c 100644 --- a/htdocs/core/boxes/modules_boxes.php +++ b/htdocs/core/boxes/modules_boxes.php @@ -277,7 +277,7 @@ class ModeleBoxes // Can't be abtract as it is instantiated to build "empty" box for ($j = 0; $j < $nbcolthisline; $j++) { // Define tdparam $tdparam = ''; - if (isset($contents[$i][$j]['td'])) $tdparam .= ' '.$contents[$i][$j]['td']; + if (!empty($contents[$i][$j]['td'])) $tdparam .= ' '.$contents[$i][$j]['td']; $text = isset($contents[$i][$j]['text']) ? $contents[$i][$j]['text'] : ''; $textwithnotags = preg_replace('/<([^>]+)>/i', '', $text); diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index c25519e151f..8327a26ae41 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -1389,7 +1389,7 @@ abstract class CommonDocGenerator if ($itemsInRow > 0) { // close table row and empty cols for ($i = $itemsInRow; $i <= $maxItemsInRow; $i++) { - $html .= ""; + $html .= ""; } $html .= ""; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ace39ade0ef..bc1c17d417f 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -578,7 +578,7 @@ abstract class CommonObject * * @param Translate $langs Language object for translation of civility (used only if option is 1) * @param int $option 0=No option, 1=Add civility - * @param int $nameorder -1=Auto, 0=Lastname+Firstname, 1=Firstname+Lastname, 2=Firstname, 3=Firstname if defined else lastname + * @param int $nameorder -1=Auto, 0=Lastname+Firstname, 1=Firstname+Lastname, 2=Firstname, 3=Firstname if defined else lastname, 4=Lastname, 5=Lastname if defined else firstname * @param int $maxlen Maximum length * @return string String with full name */ @@ -6317,8 +6317,18 @@ abstract class CommonObject $param_list_array = explode(':', $param_list[0]); $showempty = (($required && $default != '') ? 0 : 1); - if (!preg_match('/search_/', $keyprefix) && !empty($param_list_array[2])) { // If the entry into $fields is set to add a create button - $morecss .= ' widthcentpercentminusx'; + if (!preg_match('/search_/', $keyprefix)) { + if (!empty($param_list_array[2])) { // If the entry into $fields is set to add a create button + if ($this->fields[$key]['picto']) { + $morecss .= ' widthcentpercentminusxx'; + } else { + $morecss .= ' widthcentpercentminusx'; + } + } else { + if ($this->fields[$key]['picto']) { + $morecss .= ' widthcentpercentminusx'; + } + } } $out = $form->selectForForms($param_list[0], $keyprefix.$key.$keysuffix, $value, $showempty, '', '', $morecss, $moreparam, 0, empty($val['disabled']) ? 0 : 1); @@ -8512,13 +8522,13 @@ abstract class CommonObject } $sql = 'DELETE FROM '.MAIN_DB_PREFIX."ecm_files"; - $sql .= " WHERE src_object_type = '".$this->db->escape($this->table_element.(empty($this->module) ? '' : '@'.$this->module))."' AND src_object_id = ".$this->id; - $resql = $this->db->query($sql); - if (!$resql) { - $this->error = $this->db->lasterror(); - $this->db->rollback(); - return false; - } + $sql .= " WHERE src_object_type = '".$this->db->escape($this->table_element.(empty($this->module) ? '' : '@'.$this->module))."' AND src_object_id = ".$this->id; + $resql = $this->db->query($sql); + if (!$resql) { + $this->error = $this->db->lasterror(); + $this->db->rollback(); + return false; + } } $this->db->commit(); diff --git a/htdocs/core/class/dolreceiptprinter.class.php b/htdocs/core/class/dolreceiptprinter.class.php index ec8d9fa15bd..e075005b437 100644 --- a/htdocs/core/class/dolreceiptprinter.class.php +++ b/htdocs/core/class/dolreceiptprinter.class.php @@ -631,11 +631,18 @@ class dolReceiptPrinter extends Printer break; case 'DOL_PRINT_OBJECT_LINES': foreach ($object->lines as $line) { - //var_dump($line); - $spacestoadd = $nbcharactbyline - strlen($line->ref) - strlen($line->qty) - 10 - 1; - $spaces = str_repeat(' ', $spacestoadd); - $this->printer->text($line->ref.$spaces.$line->qty.' '.str_pad(price($line->total_ttc), 10, ' ', STR_PAD_LEFT)."\n"); - $this->printer->text(strip_tags(htmlspecialchars_decode($line->product_label))."\n"); + if ($line->fk_product) + { + $spacestoadd = $nbcharactbyline - strlen($line->ref) - strlen($line->qty) - 10 - 1; + $spaces = str_repeat(' ', $spacestoadd); + $this->printer->text($line->ref.$spaces.$line->qty.' '.str_pad(price($line->total_ttc), 10, ' ', STR_PAD_LEFT)."\n"); + $this->printer->text(strip_tags(htmlspecialchars_decode($line->product_label))."\n"); + } + else { + $spacestoadd = $nbcharactbyline - strlen($line->description) - strlen($line->qty) - 10 - 1; + $spaces = str_repeat(' ', $spacestoadd); + $this->printer->text($line->description.$spaces.$line->qty.' '.str_pad(price($line->total_ttc), 10, ' ', STR_PAD_LEFT)."\n"); + } } break; case 'DOL_PRINT_OBJECT_TAX': diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 0c7b9d46f3c..a56402fddef 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -266,8 +266,8 @@ class Form elseif (preg_match('/^text/', $typeofdata) || preg_match('/^note/', $typeofdata)) $ret .= dol_htmlentitiesbr($value); elseif (preg_match('/^safehtmlstring/', $typeofdata)) $ret .= dol_string_onlythesehtmltags($value); elseif (preg_match('/^restricthtml/', $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 ($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)); @@ -636,11 +636,11 @@ class Form * 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 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 + * @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') { @@ -780,8 +780,6 @@ class Form $i = 0; if ($num) { - $foundselected = false; - while ($i < $num) { $obj = $this->db->fetch_object($resql); @@ -826,16 +824,22 @@ class Form $atleastonefavorite = 0; $out .= ''; } - if ($selected && $selected != '-1' && ($selected == $row['rowid'] || $selected == $row['code_iso'] || $selected == $row['code_iso3'] || $selected == $row['label'])) - { - $foundselected = true; - $out .= ''; } } @@ -1413,7 +1417,7 @@ class Form * @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) + * @deprecated 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 = '') { @@ -1485,11 +1489,10 @@ class Form $out .= ajax_combobox($htmlid, $events, $conf->global->CONTACT_USE_SEARCH_TO_SELECT); } - if ($htmlname != 'none' && !$options_only) $out .= ''; if (($showempty == 1 || ($showempty == 3 && $num > 1)) && !$multiple) $out .= ''; if ($showempty == 2) $out .= ''; - $num = $this->db->num_rows($resql); $i = 0; if ($num) { @@ -1561,8 +1564,9 @@ class Form $i++; } } else { - $out .= ''; } @@ -2738,12 +2742,13 @@ class Form * @param int $limit Limit of line number * @param int $alsoproductwithnosupplierprice 1=Add also product without supplier prices * @param string $morecss Add more CSS + * @param int $showstockinlist Show stock information (slower). * @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 = '') + public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '', $showstockinlist = 0) { // phpcs:enable - global $langs, $conf, $db; + global $langs, $conf, $db, $user; $out = ''; $outarray = array(); @@ -2756,7 +2761,7 @@ class Form $langs->load('other'); } - $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, p.fk_product_type,"; + $sql = "SELECT p.rowid, p.ref, p.label, p.price, p.duration, p.fk_product_type, p.stock,"; $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"; @@ -2974,6 +2979,45 @@ class Form } } + if (!empty($conf->stock->enabled) && $showstockinlist && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES))) + { + $novirtualstock = ($showstockinlist == 2); + + if (!empty($user->rights->stock->lire)) { + $outvallabel .= ' - '.$langs->trans("Stock").':'.$objp->stock; + + if ($objp->stock > 0) { + $optlabel .= ' - '; + } elseif ($objp->stock <= 0) { + $optlabel .= ' - '; + } + $optlabel .= $langs->transnoentities("Stock").':'.$objp->stock; + $optlabel .= ''; + if (empty($novirtualstock) && !empty($conf->global->STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO)) // Warning, this option may slow down combo list generation + { + $langs->load("stocks"); + + $tmpproduct = new Product($this->db); + $tmpproduct->fetch($objp->rowid, '', '', '', 1, 1, 1); // Load product without lang and prices arrays (we just need to make ->virtual_stock() after) + $tmpproduct->load_virtual_stock(); + $virtualstock = $tmpproduct->stock_theorique; + + $outvallabel .= ' - '.$langs->trans("VirtualStock").':'.$virtualstock; + + $optlabel .= ' - '.$langs->transnoentities("VirtualStock").':'; + if ($virtualstock > 0) { + $optlabel .= ''; + } elseif ($virtualstock <= 0) { + $optlabel .= ''; + } + $optlabel .= $virtualstock; + $optlabel .= ''; + + unset($tmpproduct); + } + } + } + $opt = ''; + $valuetoshow .= ' '.picto_from_langcode($key, 'class="saturatemedium"'); + if ($selected == $keytouse) { + $out .= ''; } else { - $out .= ''; + $out .= ''; } } $out .= ''; diff --git a/htdocs/core/class/html.formorder.class.php b/htdocs/core/class/html.formorder.class.php index dbb97b61656..a0e1da55c7f 100644 --- a/htdocs/core/class/html.formorder.class.php +++ b/htdocs/core/class/html.formorder.class.php @@ -62,8 +62,11 @@ class FormOrder extends Form $options[$value] = $tmpsupplierorder->getLibStatut($short); } - print Form::selectarray($hmlname, $options, $selected, 1, 0, 0, '', 0, 0, 0, '', '', 1); - } + if (is_array($selected)) $selectedarray = $selected; + else $selectedarray = explode(',', $selected); + + print Form::multiselectarray($hmlname, $options, $selectedarray, 0); + } /** * Return list of input method (mode used to receive order, like order received by email, fax, online) diff --git a/htdocs/core/class/interfaces.class.php b/htdocs/core/class/interfaces.class.php index d8c8d36d3a5..19965250727 100644 --- a/htdocs/core/class/interfaces.class.php +++ b/htdocs/core/class/interfaces.class.php @@ -207,7 +207,7 @@ class Interfaces if ($result < 0) { // Action KO - //dol_syslog("Error in trigger ".$action." - Nb of error string returned = ".count($objMod->errors), LOG_ERR); + //dol_syslog("Error in trigger ".$action." - result = ".$result." - Nb of error string returned = ".count($objMod->errors), LOG_ERR); $nbtotal++; $nbko++; if (!empty($objMod->errors)) $this->errors = array_merge($this->errors, $objMod->errors); diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index 3c4c3ea5d36..ab7bf604446 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -589,16 +589,15 @@ class Translate /** * Return text translated of text received as parameter (and encode it into HTML) - * If there is no match for this text, we look in alternative file and if still not found, - * it is returned as it is - * The parameters of this method can contain HTML tags + * If there is no match for this text, we look in alternative file and if still not found, it is returned as it is. + * The parameters of this method should not contain HTML tags. If there is, they will be htmlencoded to have no effect. * * @param string $key Key to translate * @param string $param1 param1 string * @param string $param2 param2 string * @param string $param3 param3 string * @param string $param4 param4 string - * @param int $maxsize Max length of text + * @param int $maxsize Max length of text. Warning: Will not work if paramX has HTML content. deprecated. * @return string Translated string (encoded into HTML entities and UTF8) */ public function trans($key, $param1 = '', $param2 = '', $param3 = '', $param4 = '', $maxsize = 0) @@ -621,25 +620,33 @@ class Translate } } + // We replace some HTML tags by __xx__ to avoid having them encoded by htmlentities because + // we want to keep '"' '' '' '' '' '
' '< ' '' that are reliable HTML tags inside translation strings. + $str = str_replace( + array('"', '', '', '', '', '
', '
', '', '< ', '>'), // We accept '< ' but not '<'. We can accept however '>' + array('__quot__', '__tagbold__', '__tagboldend__', '__tagbold__', '__tagboldend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__lt__', '__gt__'), + $str + ); + if (strpos($key, 'Format') !== 0) { $str = sprintf($str, $param1, $param2, $param3, $param4); // Replace %s and %d except for FormatXXX strings. } + // Crypt string into HTML + $str = htmlentities($str, ENT_COMPAT, $this->charset_output); // Do not convert simple quotes in translation (strings in html are embraced by "). Use dol_escape_htmltag around text in HTML content + + // Restore reliable HTML tags into original translation string + $str = str_replace( + array('__quot__', '__tagbold__', '__tagboldend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__lt__', '__gt__'), + array('"', '', '', '
', '
', '', '< ', '> '), + $str + ); + if ($maxsize) $str = dol_trunc($str, $maxsize); - // We replace some HTML tags by __xx__ to avoid having them encoded by htmlentities - $str = str_replace(array('<', '>', '"',), array('__lt__', '__gt__', '__quot__'), $str); - - // Crypt string into HTML - $str = htmlentities($str, ENT_COMPAT, $this->charset_output); // Do not convert simple quotes in translation (strings in html are enmbraced by "). Use dol_escape_htmltag around text in HTML content - - // Restore HTML tags - $str = str_replace(array('__lt__', '__gt__', '__quot__'), array('<', '>', '"',), $str); - return $str; - } else // Translation is not available - { + } else { // Translation is not available //if ($key[0] == '$') { return dol_eval($key,1); } return $this->getTradFromKey($key); } diff --git a/htdocs/core/class/workboardresponse.class.php b/htdocs/core/class/workboardresponse.class.php index e2d9cc2c0d7..ac1d8fe9676 100644 --- a/htdocs/core/class/workboardresponse.class.php +++ b/htdocs/core/class/workboardresponse.class.php @@ -24,6 +24,11 @@ class WorkboardResponse { + /** + * Unique key of the workboard + * @var string + */ + public $id; /** * Image URL to represent the board item diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index 6cab3638eb5..a697fcdfdc5 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -402,36 +402,36 @@ function run_sql($sqlfile, $silent = 1, $entity = '', $usesavepoint = 1, $handle } } - if ($error == 0) - { - if (!$silent) { - print '
'; - print ''."\n"; + if (!$silent) { + print ''; + print ''."\n"; + } + + if ($error == 0) { $ok = 1; } else { - if (!$silent) { - print ''; - print ''."\n"; - } $ok = 0; } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 3ac22dd7e32..3be5453c406 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1060,7 +1060,7 @@ function dol_escape_json($stringtoescape) * Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields. * * @param string $stringtoescape String to escape - * @param int $keepb 1=Preserve b tags (otherwise, remove them) + * @param int $keepb 1=Keep b tags and escape them, 0=remove them * @param int $keepn 1=Preserve \r\n strings (otherwise, replace them with escaped value). Set to 1 when escaping for a '; + print ''; } else { print ''; } diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php index d64c3c999a7..b52cc3afe84 100644 --- a/htdocs/reception/class/reception.class.php +++ b/htdocs/reception/class/reception.class.php @@ -68,7 +68,6 @@ class Reception extends CommonObject public $brouillon; public $entrepot_id; - public $lines = array(); public $tracking_number; public $tracking_url; public $billed; @@ -106,6 +105,8 @@ class Reception extends CommonObject public $meths; public $listmeths; // List of carriers + public $lines = array(); + const STATUS_DRAFT = 0; const STATUS_VALIDATED = 1; @@ -121,8 +122,6 @@ class Reception extends CommonObject public function __construct($db) { $this->db = $db; - $this->lines = array(); - $this->products = array(); // List of long language codes for status $this->statuts = array(); diff --git a/htdocs/recruitment/admin/setup.php b/htdocs/recruitment/admin/setup.php index 702fa4852f5..fdd4d83e223 100644 --- a/htdocs/recruitment/admin/setup.php +++ b/htdocs/recruitment/admin/setup.php @@ -308,8 +308,10 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { // Show example of numbering model print ''."\n"; diff --git a/htdocs/recruitment/admin/setup_candidatures.php b/htdocs/recruitment/admin/setup_candidatures.php index b829f27eb82..ef4454974e7 100644 --- a/htdocs/recruitment/admin/setup_candidatures.php +++ b/htdocs/recruitment/admin/setup_candidatures.php @@ -308,8 +308,10 @@ foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { // Show example of numbering model print ''."\n"; diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index e67f28c4dab..6a819aa37f8 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -2070,7 +2070,7 @@ class Societe extends CommonObject $discount->amount_tva = $discount->multicurrency_amount_tva = price2num($remise * $vatrate / 100, 'MT'); $discount->amount_ttc = $discount->multicurrency_amount_ttc = price2num($discount->amount_ht + $discount->amount_tva, 'MT'); - $discount->tva_tx = price2num($vatrate, 'MT'); + $discount->tva_tx = price2num($vatrate); $discount->vat_src_code = $vat_src_code; $discount->description = $desc; diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index b891d042e5b..893748deee7 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -272,8 +272,6 @@ if (empty($reshook)) $object->note = GETPOST('note', 'restricthtml'); $object->note_private = GETPOST('note', 'restricthtml'); $object->statut = SupplierProposal::STATUS_DRAFT; - - $id = $object->create_from($user); } else { setEventMessages($langs->trans("ErrorFailedToCopyProposal", GETPOST('copie_supplier_proposal')), null, 'errors'); } diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 914e487b594..9a6ed7e1d38 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -171,9 +171,7 @@ class SupplierProposal extends CommonObject public $remise_percent = 0; public $remise_absolue = 0; - public $products = array(); public $extraparams = array(); - public $lines = array(); public $line; @@ -237,15 +235,12 @@ class SupplierProposal extends CommonObject $this->socid = $socid; $this->id = $supplier_proposalid; - - $this->products = array(); } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Add line into array products - * $this->client doit etre charge + * Add line into array ->lines * * @param int $idproduct Product Id to add * @param int $qty Quantity @@ -253,7 +248,6 @@ class SupplierProposal extends CommonObject * @return int <0 if KO, >0 if OK * * TODO Remplacer les appels a cette fonction par generation objet Ligne - * insere dans tableau $this->products */ public function add_product($idproduct, $qty, $remise_percent = 0) { @@ -1085,23 +1079,6 @@ class SupplierProposal extends CommonObject } } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Insert into DB a supplier_proposal object completely defined by its data members (ex, results from copy). - * - * @param User $user User that create - * @return int Id of the new object if ok, <0 if ko - * @see create() - */ - public function create_from($user) - { - // phpcs:enable - $this->products = $this->lines; - - return $this->create($user); - } - /** * Load an object from its id and create a new one in database * diff --git a/htdocs/takepos/admin/setup.php b/htdocs/takepos/admin/setup.php index fd5f5a1cbc2..88911f10b7d 100644 --- a/htdocs/takepos/admin/setup.php +++ b/htdocs/takepos/admin/setup.php @@ -179,8 +179,10 @@ foreach ($dirmodels as $reldir) // Show example of numbering module print ''."\n"; diff --git a/htdocs/theme/common/flags/unknown.png b/htdocs/theme/common/flags/unknown.png new file mode 100644 index 00000000000..08efc7b264d Binary files /dev/null and b/htdocs/theme/common/flags/unknown.png differ diff --git a/htdocs/theme/eldy/badges.inc.php b/htdocs/theme/eldy/badges.inc.php index 36296bb0b8a..86f5971891e 100644 --- a/htdocs/theme/eldy/badges.inc.php +++ b/htdocs/theme/eldy/badges.inc.php @@ -59,6 +59,13 @@ a.badge:focus, a.badge:hover { color: #fff; } +span.badgeneutral { + padding: 2px 7px 2px 7px; + background-color: #e4e4e4; + color: #666; + border-radius: 10px; +} + /* PRIMARY */ .badge-primary{ diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index a1500d84186..e576b379a6c 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -108,6 +108,7 @@ body { margin-bottom: 0; margin-right: 0; margin-left: 0; + font-weight: 400; trans("DIRECTION").";\n"; ?> } @@ -366,6 +367,10 @@ input.pageplusone { padding-top: 4px; } +.saturatemedium { + filter: saturate(0.8); +} + .optionblue { color: var(--colortextlink); } @@ -1031,27 +1036,34 @@ select.flat.selectlimit { .tablelistofcalendars { margin-top: 25px !important; } + +/* Styles for amount on card */ +table.paymenttable td.amountpaymentcomplete, table.paymenttable td.amountremaintopay { + padding-top: 0px; + padding-bottom: 0px; +} .amountalreadypaid { } .amountpaymentcomplete { color: var(--amountpaymentcomplete); font-weight: bold; - font-size: 1.2em; + font-size: 1.7em; } .amountremaintopay { color: var(--amountremaintopaycolor); font-weight: bold; - font-size: 1.2em; + font-size: 1.7em; } .amountremaintopayback { color: var(--amountremaintopaybackcolor); font-weight: bold; - font-size: 1.2em; + font-size: 1.7em; } .amountpaymentneutral { font-weight: bold; - font-size: 1.2em; + font-size: 1.7em; } + .onlinepaymentbody .amountpaymentcomplete { background-color: var(--amountpaymentcomplete); color: #fff; @@ -1953,8 +1965,8 @@ div.statusrefbis { } img.photoref, div.photoref { /* border: 1px solid #DDD; */ - -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2); - box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.2); + box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.2); padding: 4px; height: 80px; width: 80px; @@ -2161,6 +2173,8 @@ div.menu_titre { { padding-: 2px; padding-: 2px; + font-family: Roboto,; + font-weight: 400; } div.mainmenu { @@ -2617,7 +2631,8 @@ a.help:link, a.help:visited, a.help:hover, a.help:active, span.help { text-align /* color: #f3e4ac !important; */ } .helppresentcircle { - color: var(--butactionbg); + color: var(--colorbackhmenu1); + filter: invert(0.8); margin-left: -7px; display: inline-block; margin-top: -10px; @@ -2930,7 +2945,7 @@ a.tab:link, a.tab:visited, a.tab:hover, a.tab#active { border-right: 1px solid #CCC !important; border-left: 1px solid #CCC !important; - border-top: px solid var(--colorbackhmenu1) !important; + border-top: 3px solid var(--colorbackhmenu1) !important; } a.tab:hover { @@ -4158,7 +4173,7 @@ div.titre { text-decoration: none; padding-top: 5px; padding-bottom: 5px; - /* text-transform: capitalize; */ + font-weight: 400; } div.fiche > table.table-fiche-title:first-of-type div { color: var(--colortexttitlenotab); @@ -5325,6 +5340,10 @@ div.dataTables_length select { /* Select2 */ /* ============================================================================== */ +span.select2-selection--single.flat[aria-disabled="true"] span.select2-selection__rendered { + opacity: 0.5; +} + span#select2-taskid-container[title^='--'] { opacity: 0.3; } diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 7a86c52ff1e..9d8c2b26017 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -81,7 +81,7 @@ $theme = 'eldy'; // Value of theme if (!empty($conf->global->MAIN_OVERWRITE_THEME_RES)) { $path = '/'.$conf->global->MAIN_OVERWRITE_THEME_RES; $theme = $conf->global->MAIN_OVERWRITE_THEME_RES; } // Define image path files and other constants -$fontlist = 'roboto,arial,tahoma,verdana,helvetica'; //$fontlist='helvetica, verdana, arial, sans-serif'; +$fontlist = 'arial,tahoma,verdana,helvetica'; //$fontlist='helvetica, verdana, arial, sans-serif'; //$fontlist='"open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;'; $img_head = ''; $img_button = dol_buildpath($path.'/theme/'.$theme.'/img/button_bg.png', 1); diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 0dd6acab9f7..f9922cf5b2f 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -499,6 +499,10 @@ input.pageplusone { padding-top: 4px; } +.saturatemedium { + filter: saturate(0.8); +} + .optionblue { color: rgb(); } @@ -2588,6 +2592,17 @@ font.vsmenudisabledmargin { margin: 1px 1px 1px 8px; } a.help:link, a.help:visited, a.help:hover, a.help:active, span.help { text-align: ; font-weight: normal; color: #999; text-decoration: none; } +.helppresentcircle { + color: var(--colorbackhmenu1); + filter: invert(0.5); + margin-left: -7px; + display: inline-block; + margin-top: -10px; + font-size: x-small; + vertical-align: super; + opacity: 0.95; +} + div.blockvmenulogo { border-bottom: 0 !important; diff --git a/htdocs/ticket/stats/index.php b/htdocs/ticket/stats/index.php index 4273979d45e..045943bbfda 100644 --- a/htdocs/ticket/stats/index.php +++ b/htdocs/ticket/stats/index.php @@ -32,7 +32,7 @@ $HEIGHT = DolGraph::getDefaultGraphSizeForStats('height'); if (!$user->rights->ticket->read) accessforbidden(); -$object_status = GETPOST('object_status'); +$object_status = GETPOST('object_status', 'intcomma'); $userid = GETPOST('userid', 'int'); $socid = GETPOST('socid', 'int'); @@ -44,7 +44,7 @@ if ($user->socid > 0) } $nowyear = strftime("%Y", dol_now()); -$year = GETPOST('year') > 0 ?GETPOST('year') : $nowyear; +$year = GETPOST('year') > 0 ? GETPOST('year', 'int') : $nowyear; //$startyear=$year-2; $startyear = $year - 1; $endyear = $year; @@ -235,7 +235,7 @@ print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0 // Status print ''; // Year print ''; + // Allowed in frames + print ''; + // Categories if (!empty($conf->categorie->enabled) && !empty($user->rights->categorie->lire)) { @@ -3566,18 +3577,19 @@ if ($action == 'editmeta' || $action == 'createcontainer') print ""; } - print ''; - - print ''; + if (!empty($conf->global->WEBSITE_PAGE_SHOW_INTERNAL_LINKS_TO_OBJECT)) { + print ''; + print ''; + } $fuser = new User($db); diff --git a/scripts/members/sync_members_types_dolibarr2ldap.php b/scripts/members/sync_members_types_dolibarr2ldap.php index 0a22469ec80..d0cf6ae7f04 100755 --- a/scripts/members/sync_members_types_dolibarr2ldap.php +++ b/scripts/members/sync_members_types_dolibarr2ldap.php @@ -89,7 +89,7 @@ if ($resql) { $membertype->id = $obj->rowid; $membertype->fetch($membertype->id); - print $langs->trans("UpdateMemberType")." rowid=".$membertype->id." ".$membertype - label; + print $langs->trans("UpdateMemberType")." rowid=".$membertype->id." ".$membertype->label; $oldobject = $membertype; diff --git a/test/phpunit/CodingPhpTest.php b/test/phpunit/CodingPhpTest.php index 727f8cc0ee3..9acb13432d2 100644 --- a/test/phpunit/CodingPhpTest.php +++ b/test/phpunit/CodingPhpTest.php @@ -281,7 +281,7 @@ class CodingPhpTest extends PHPUnit\Framework\TestCase preg_match_all('/sql.+\s*\'"\s*\.\s*\$(.........)/', $filecontent, $matches, PREG_SET_ORDER); foreach ($matches as $key => $val) { - if (! in_array($val[1], array('this->db-', 'this->esc', 'db->escap', 'dbsession->escap', 'db->idate', 'excludeGr', 'includeGr'))) { + if (! in_array($val[1], array('this->db-', 'this->esc', 'db->escap', 'dbsession', 'db->idate', 'excludeGr', 'includeGr'))) { $ok=false; break; } diff --git a/test/phpunit/CoreTest.php b/test/phpunit/CoreTest.php index 87c43798a0f..22649a80724 100644 --- a/test/phpunit/CoreTest.php +++ b/test/phpunit/CoreTest.php @@ -236,173 +236,4 @@ class CoreTest extends PHPUnit\Framework\TestCase return true; } - - - /** - * testSqlAndScriptInject - * - * @return void - */ - public function testSqlAndScriptInject() - { - global $dolibarr_main_prod; - - global $dolibarr_main_url_root; - global $dolibarr_main_data_root; - global $dolibarr_main_document_root; - global $dolibarr_main_data_root_alt; - global $dolibarr_main_document_root_alt; - global $dolibarr_main_db_host; - global $dolibarr_main_db_port; - global $dolibarr_main_db_type; - global $dolibarr_main_db_prefix; - - - // This is code copied from main.inc.php !!!!!!!!!!!!!!! - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps - /** - * Security: SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, PHP_SELF). - * - * @param string $val Value - * @param string $type 1=GET, 0=POST, 2=PHP_SELF - * @return int >0 if there is an injection - */ - function testSqlAndScriptInject($val, $type) - { - // phpcs:enable - $inj = 0; - // For SQL Injection (only GET and POST are used to be included into bad escaped SQL requests) - if ($type != 2) - { - $inj += preg_match('/delete\s+from/i', $val); - $inj += preg_match('/create\s+table/i', $val); - $inj += preg_match('/update.+set.+=/i', $val); - $inj += preg_match('/insert\s+into/i', $val); - $inj += preg_match('/select.+from/i', $val); - $inj += preg_match('/union.+select/i', $val); - $inj += preg_match('/into\s+(outfile|dumpfile)/i', $val); - $inj += preg_match('/(\.\.%2f)+/i', $val); - } - // For XSS Injection done by adding javascript with script - // This is all cases a browser consider text is javascript: - // When it found ' - $inj += preg_match('/onerror\s*=/i', $val); // onerror can be set on img or any html tag like - $inj += preg_match('/onfocus\s*=/i', $val); // onfocus can be set on input text html tag like - $inj += preg_match('/onload\s*=/i', $val); // onload can be set on svg tag or other tag like body - //$inj += preg_match('/on[A-Z][a-z]+\*=/', $val); // To lock event handlers onAbort(), ... - $inj += preg_match('/:|:|:/i', $val); // refused string ':' encoded (no reason to have it encoded) to lock 'javascript:...' - //if ($type == 1) - //{ - $inj += preg_match('/javascript:/i', $val); - $inj += preg_match('/vbscript:/i', $val); - //} - // For XSS Injection done by adding javascript closing html tags like with onmousemove, etc... (closing a src or href tag with not cleaned param) - if ($type == 1) $inj += preg_match('/"/i', $val); // We refused " in GET parameters value - if ($type == 2) $inj += preg_match('/[;"]/', $val); // PHP_SELF is a file system path. It can contains spaces. - return $inj; - } - - // Run tests - // More on https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet - - // Should be OK - $expectedresult=0; - - $_SERVER["PHP_SELF"]='/DIR WITH SPACE/htdocs/admin/index.php?mainmenu=home&leftmenu=setup&username=weservices'; - $result=testSqlAndScriptInject($_SERVER["PHP_SELF"], 2); - $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject 1a'); - - // Should detect XSS - $expectedresult=1; - - $_SERVER["PHP_SELF"]='/DIR WITH SPACE/htdocs/admin/index.php?mainmenu=home&leftmenu=setup&username=weservices;badaction'; - $result=testSqlAndScriptInject($_SERVER["PHP_SELF"], 2); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject 1b'); - - $test=""; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa'); - - $test=""; - $result=testSqlAndScriptInject($test, 2); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa2'); - - $test=''; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa3'); - $test=''; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa4'); - $test=''; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa5'); - $test=''; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa6'); - $test=''; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa7'); - - $test=''; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject bbb'); - - $test=''; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject ccc'); - - $test=''; - $result=testSqlAndScriptInject($test, 1); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject ddd'); - - $test='">'; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject eee'); - - $test=' - '; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject eee'); - - $test=""; // Is locked by some browser like chrome because the default directive no-referrer-when-downgrade is sent when requesting the SRC and then refused because of browser protection on img src load without referrer. - $test=""; // Same - - $test=''; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject fff1'); - $test=''; - $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject fff2'); - - // This case seems to be filtered by browsers now. - $test=''; - //$result=testSqlAndScriptInject($test, 0); - //$this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject ggg'); - - $test='
'.img_picto('', 'language').' '.$langs->trans("Language").'
'.$langs->trans("ProcessMigrateScript").''.$langs->trans("OK"); - //if (! empty($conf->use_javascript_ajax)) { - print ''; - print ' - '.$langs->trans("ShowHideDetails").''; - //} - print '
'.$langs->trans("ProcessMigrateScript").''; + if ($error == 0) { + print ''.$langs->trans("OK").''; + } else { + print ''.$langs->trans("Error").''; } + //if (! empty($conf->use_javascript_ajax)) { + print ''; + print ' - '.$langs->trans("ShowHideDetails").''; + //} + print '
'.$langs->trans("ProcessMigrateScript").''.$langs->trans("KO").''; - print '
'.$lines[$i]->comment.''; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; - elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print '
'; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; - elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print '
'; $tmp = $module->getExample(); - if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; - elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); else print $tmp; print '
'.$langs->trans("Status").''; $liststatus = $object->fields['fk_statut']['arrayofkeyval']; -print $form->selectarray('object_status', $liststatus, GETPOST('object_status', 'int'), -4, 0, 0, '', 1); +print $form->selectarray('object_status', $liststatus, GETPOST('object_status', 'intcomma'), -4, 0, 0, '', 1); print '
'.$langs->trans("Year").''; diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index 9a89ad8e81c..e68ecb8bc1d 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -246,12 +246,13 @@ class Users extends DolibarrApi * * @url GET /info * + * @param int $includepermissions Set this to 1 to have the array of permissions loaded (not done by default for performance purpose) * @return array|mixed Data without useless information * * @throws RestException 401 Insufficient rights * @throws RestException 404 User or group not found */ - public function getInfo() + public function getInfo($includepermissions = 0) { $apiUser = DolibarrApiAccess::$user; @@ -264,6 +265,10 @@ class Users extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } + if ($includepermissions) { + $this->useraccount->getRights(); + } + $usergroup = new UserGroup($this->db); $userGroupList = $usergroup->listGroupsForUser($apiUser->id, false); if (!is_array($userGroupList)) { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 41e1d55ea7c..7a40af26ac0 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -412,6 +412,7 @@ class User extends CommonObject $sql .= " u.tms as datem,"; $sql .= " u.datelastlogin as datel,"; $sql .= " u.datepreviouslogin as datep,"; + $sql .= " u.datelastpassvalidation,"; $sql .= " u.datestartvalidity,"; $sql .= " u.dateendvalidity,"; $sql .= " u.photo as photo,"; diff --git a/htdocs/website/class/websitepage.class.php b/htdocs/website/class/websitepage.class.php index 5108fe4c25b..ff072827423 100644 --- a/htdocs/website/class/websitepage.class.php +++ b/htdocs/website/class/websitepage.class.php @@ -81,6 +81,7 @@ class WebsitePage extends CommonObject */ public $lang; + public $allowed_in_frames; public $htmlheader; public $content; public $grabbed_from; @@ -160,6 +161,7 @@ class WebsitePage extends CommonObject //'status' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>true, 'position'=>1000), 'fk_website' =>array('type'=>'integer', 'label'=>'WebsiteId', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'position'=>40, 'searchall'=>0, 'foreignkey'=>'websitepage.rowid'), 'fk_page' =>array('type'=>'integer', 'label'=>'ParentPageId', 'enabled'=>1, 'visible'=>1, 'notnull'=>-1, 'position'=>45, 'searchall'=>0, 'foreignkey'=>'website.rowid'), + 'allowed_in_frames' =>array('type'=>'integer', 'label'=>'AllowedInFrames', 'enabled'=>1, 'visible'=>-1, 'position'=>48, 'searchall'=>0), 'htmlheader' =>array('type'=>'text', 'label'=>'HtmlHeader', 'enabled'=>1, 'visible'=>0, 'position'=>50, 'searchall'=>0), 'content' =>array('type'=>'mediumtext', 'label'=>'Content', 'enabled'=>1, 'visible'=>0, 'position'=>51, 'searchall'=>0), 'grabbed_from' =>array('type'=>'varchar(255)', 'label'=>'GrabbedFrom', 'enabled'=>1, 'visible'=>1, 'index'=>1, 'position'=>400, 'comment'=>'URL page content was grabbed from'), @@ -265,6 +267,7 @@ class WebsitePage extends CommonObject $sql .= " t.content,"; $sql .= " t.lang,"; $sql .= " t.fk_page,"; + $sql .= " t.allowed_in_frames,"; $sql .= " t.status,"; $sql .= " t.grabbed_from,"; $sql .= " t.date_creation,"; @@ -325,6 +328,7 @@ class WebsitePage extends CommonObject $this->content = $obj->content; $this->lang = $obj->lang; $this->fk_page = $obj->fk_page; + $this->allowed_in_frames = $obj->allowed_in_frames; $this->status = $obj->status; $this->grabbed_from = $obj->grabbed_from; $this->date_creation = $this->db->jdate($obj->date_creation); @@ -383,6 +387,7 @@ class WebsitePage extends CommonObject $sql .= " t.content,"; $sql .= " t.lang,"; $sql .= " t.fk_page,"; + $sql .= " t.allowed_in_frames,"; $sql .= " t.status,"; $sql .= " t.grabbed_from,"; $sql .= " t.date_creation,"; @@ -453,6 +458,7 @@ class WebsitePage extends CommonObject $record->content = $obj->content; $record->lang = $obj->lang; $record->fk_page = $obj->fk_page; + $record->allowed_in_frames = $obj->allowed_in_frames; $record->status = $obj->status; $record->grabbed_from = $obj->grabbed_from; $record->date_creation = $this->db->jdate($obj->date_creation); @@ -839,6 +845,7 @@ class WebsitePage extends CommonObject $this->description = 'This is my page'; $this->image = ''; $this->keywords = 'keyword1, keyword2'; + $this->allowed_in_frames = 1; $this->htmlheader = ''; $this->content = 'This is a html content'; $this->status = ''; diff --git a/htdocs/website/index.php b/htdocs/website/index.php index f7f2da2d268..f2734483acb 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -940,6 +940,7 @@ if ($action == 'addcontainer') $objectpage->otherlang = GETPOST('WEBSITE_OTHERLANG', 'aZ09comma'); $objectpage->image = GETPOST('WEBSITE_IMAGE', 'alpha'); $objectpage->keywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml')); + $objectpage->allowed_in_frames = GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09'); $objectpage->htmlheader = GETPOST('htmlheader', 'none'); $objectpage->author_alias = GETPOST('WEBSITE_AUTHORALIAS', 'alphanohtml'); $objectpage->object_type = GETPOST('WEBSITE_OBJECTCLASS'); @@ -1562,7 +1563,7 @@ if ($action == 'setashome') } } -// Update page (meta) +// Update page properties (meta) if ($action == 'updatemeta') { $db->begin(); @@ -1656,6 +1657,7 @@ if ($action == 'updatemeta') $objectpage->description = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml')); $objectpage->image = GETPOST('WEBSITE_IMAGE', 'alpha'); $objectpage->keywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml')); + $objectpage->allowed_in_frames = GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09'); $objectpage->htmlheader = trim(GETPOST('htmlheader', 'none')); $objectpage->fk_page = (GETPOST('pageidfortranslation', 'int') > 0 ? GETPOST('pageidfortranslation', 'int') : 0); $objectpage->author_alias = trim(GETPOST('WEBSITE_AUTHORALIAS', 'alphanohtml')); @@ -2831,7 +2833,6 @@ if (!GETPOST('hide_websitemenu')) print ''; // end websitehelp - if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone') { // Adding jquery code to change on the fly url of preview ext @@ -2887,7 +2888,6 @@ if (!GETPOST('hide_websitemenu')) } - $head = array(); @@ -3279,7 +3279,7 @@ if ($action == 'importsite') print '
'; } -if ($action == 'editmeta' || $action == 'createcontainer') +if ($action == 'editmeta' || $action == 'createcontainer') // Edit properties of a web site OR properties of a web page { print '
'; @@ -3366,6 +3366,7 @@ if ($action == 'editmeta' || $action == 'createcontainer') $pageimage = $objectpage->image; $pagekeywords = $objectpage->keywords; $pagelang = $objectpage->lang; + $pageallowedinframes = $objectpage->allowed_in_frames; $pagehtmlheader = $objectpage->htmlheader; $pagedatecreation = $objectpage->date_creation; $pagedatemodification = $objectpage->date_modification; @@ -3389,6 +3390,7 @@ if ($action == 'editmeta' || $action == 'createcontainer') if (GETPOST('WEBSITE_IMAGE', 'alpha')) $pageimage = GETPOST('WEBSITE_IMAGE', 'alpha'); if (GETPOST('WEBSITE_KEYWORDS', 'alpha')) $pagekeywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml')); if (GETPOST('WEBSITE_LANG', 'aZ09')) $pagelang = GETPOST('WEBSITE_LANG', 'aZ09'); + if (GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09')) $pageallowedinframes = GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09'); if (GETPOST('htmlheader', 'none')) $pagehtmlheader = GETPOST('htmlheader', 'none'); if ($action != 'createcontainer') @@ -3542,6 +3544,15 @@ if ($action == 'editmeta' || $action == 'createcontainer') } print '
'; + print $langs->trans('AllowedInFrames'); + //$htmlhelp = $langs->trans("AllowedInFramesDesc"); + //print $form->textwithpicto($langs->trans('AllowedInFrames'), $htmlhelp, 1, 'help', '', 0, 2, 'allowedinframestooltip'); + print ''; + print ''; + print '
'; - print 'ObjectClass'; - print ''; - print ''; - print '
'; - print 'ObjectID'; - print ''; - print ''; - print '
'; + print 'ObjectClass'; + print ''; + print ''; + print '
'; + print 'ObjectID'; + print ''; + print ''; + print '