diff --git a/dev/build/generate_filelist_xml.php b/dev/build/generate_filelist_xml.php
index 7c1fb1d5a30..f73bdadd47b 100755
--- a/dev/build/generate_filelist_xml.php
+++ b/dev/build/generate_filelist_xml.php
@@ -115,7 +115,7 @@ while ($i < $argc) {
$includeconstants[$tmp[0]][$tmp[1]] = $tmp[2];
}
if (!empty($result["buildzip"])) {
- $buildzip = 1;
+ $buildzip = $result["buildzip"];
}
$i++;
}
@@ -134,7 +134,7 @@ $savrelease = $release;
$tmpver = explode('-', $release, 2);
if ($tmpver[0] == 'auto') {
$release = DOL_VERSION;
- if (!empty($tmpver[1]) && $tmpver[0] == 'auto') {
+ if (!empty($tmpver[1])) {
$release .= '-'.$tmpver[1];
}
}
@@ -419,12 +419,12 @@ foreach ($arrayofunalterablefiles as $entry) {
exit(1);
}
if ($newdir != $dir) {
- if ($needtoclose) {
- if ($release) {
- fputs($fp, ' '."\n");
- }
- $needtoclose = 0;
+ //if ($needtoclose) {
+ if ($release) {
+ fputs($fp, ' '."\n");
}
+ $needtoclose = 0;
+ //}
if ($release) {
fputs($fp, '
'."\n");
}
diff --git a/dev/build/makepack-dolibarr.php b/dev/build/makepack-dolibarr.php
index 026b0235140..7ebbd98fbe0 100755
--- a/dev/build/makepack-dolibarr.php
+++ b/dev/build/makepack-dolibarr.php
@@ -230,6 +230,8 @@ if (preg_match("/define\('DOL_VERSION',\s*'([\d\.a-z\-]+)'\)/i", $filefuncConten
$PROJVERSION = $matches[1];
}
if (empty($PROJVERSION)) {
+ $DOL_MAJOR_VERSION = 'notfound';
+ $DOL_MINOR_VERSION = 'notfound';
if (preg_match("/define\('DOL_MAJOR_VERSION',\s*'([\d\.a-z\-]+)'\)/i", $filefuncContent, $matches)) {
$DOL_MAJOR_VERSION = $matches[1];
}
@@ -269,7 +271,7 @@ if (strpos($newbuild, '-') === false) {
$newbuild .= '-0.4'; // finale (fedora)
}
$REL1 = preg_replace('/-.*$/', '', $newbuild);
-if ($RPMSUBVERSION === 'auto') {
+if ($RPMSUBVERSION === 'auto') { // @phpstan-ignore-line
$RPMSUBVERSION = preg_replace('/^.*-/', '', $newbuild);
}
$FILENAMETGZ2 = "$PROJECT-$MAJOR.$MINOR.$REL1";
@@ -314,10 +316,10 @@ for ($i = 1; $i < $argc; $i++) {
}
// Force output dir if env vars are defined
-if ($ENVDESTIBETARC && preg_match('/[a-z]/i', $BUILD)) {
+if ($ENVDESTIBETARC && preg_match('/[a-z]/i', $BUILD)) { // @phpstan-ignore-line
$DESTI = $ENVDESTIBETARC;
}
-if ($ENVDESTISTABLE && preg_match('/^[0-9]+$/', $BUILD)) {
+if ($ENVDESTISTABLE && preg_match('/^[0-9]+$/', $BUILD)) { // @phpstan-ignore-line
$DESTI = $ENVDESTISTABLE;
}
@@ -349,12 +351,12 @@ if ($target) {
$targetUpper = strtoupper($target);
if ($targetUpper === 'ALL') {
foreach ($LISTETARGET as $key) {
- if ($key !== 'SNAPSHOT' && $key !== 'SF' && $key !== 'ASSO') {
+ if ($key !== 'SNAPSHOT' && $key !== 'SF' && $key !== 'ASSO') { // @phpstan-ignore-line
$CHOOSEDTARGET[$key] = 1;
}
}
}
- if ($targetUpper !== 'ALL' && $targetUpper !== 'SF' && $targetUpper !== 'ASSO') {
+ if ($targetUpper !== 'ALL' && $targetUpper !== 'SF' && $targetUpper !== 'ASSO') { // @phpstan-ignore-line
$CHOOSEDTARGET[$targetUpper] = 1;
}
if ($targetUpper === 'SF') {
@@ -399,7 +401,7 @@ if ($target) {
} elseif ($NUM_SCRIPT === '0') {
$CHOOSEDTARGET['-CHKSUM'] = 1;
foreach ($LISTETARGET as $key) {
- if ($key !== 'SNAPSHOT' && $key !== 'ASSO' && $key !== 'SF') {
+ if ($key !== 'SNAPSHOT' && $key !== 'ASSO' && $key !== 'SF') { // @phpstan-ignore-line
$CHOOSEDTARGET[$key] = 1;
}
}
@@ -495,7 +497,7 @@ foreach ($CHOOSEDTARGET as $tgt => $val) {
ksort($CHOOSEDPUBLISH);
foreach ($CHOOSEDPUBLISH as $tgt => $val) {
- if ($val < 0) { continue; }
+ if ($val < 0) { continue; } // @phpstan-ignore-line
if ($tgt === 'ASSO') { $nbofpublishneedchangelog++; }
if ($tgt === 'SF') { $nbofpublishneedchangelog++; $nbofpublishneedtag++; }
$nboftargetok++;
@@ -621,7 +623,7 @@ if ($nboftargetok) {
// ========================================================================
if ($nboftargetneedbuildroot) {
- if (!$copyalreadydone) {
+ if (!$copyalreadydone) { // @phpstan-ignore-line
echo "Creation of a buildroot used for all packages\n";
echo "Delete directory $BUILDROOT\n";
@@ -1297,7 +1299,7 @@ if ($nboftargetok) {
ksort($CHOOSEDPUBLISH);
foreach ($CHOOSEDPUBLISH as $tgt => $val) {
- if ($val < 0) { continue; }
+ if ($val < 0) { continue; } // @phpstan-ignore-line
echo "\nList of files to publish (BUILD=$BUILD)\n";
diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php
index 38a10d825e3..418cb375bd8 100644
--- a/htdocs/accountancy/admin/productaccount.php
+++ b/htdocs/accountancy/admin/productaccount.php
@@ -349,7 +349,7 @@ if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) {
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = p." . $db->sanitize($accountancy_field_name) . " AND aa.fk_pcg_version = '" . $db->escape($pcgvercode) . "'";
}
if (!empty($searchCategoryProductList)) {
- $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; // We'll need this table joined to the select in order to filter by categ
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; // We'll need this table joined to the select in order to filter by categ
}
$sql .= ' WHERE p.entity IN ('.getEntity('product').')';
if (strlen(trim($search_current_account))) {
diff --git a/htdocs/adherents/class/subscription.class.php b/htdocs/adherents/class/subscription.class.php
index ecfad20791f..9d6485c3921 100644
--- a/htdocs/adherents/class/subscription.class.php
+++ b/htdocs/adherents/class/subscription.class.php
@@ -547,9 +547,9 @@ class Subscription extends CommonObject
*/
public function info($id)
{
- $sql = 'SELECT c.rowid, c.datec, c.tms as datem, c.fk_user_creat';
- $sql .= ' FROM '.MAIN_DB_PREFIX.'subscription as c';
- $sql .= ' WHERE c.rowid = '.((int) $id);
+ $sql = "SELECT c.rowid, c.datec, c.tms as datem, c.fk_user_creat";
+ $sql .= " FROM ".MAIN_DB_PREFIX."subscription as c";
+ $sql .= " WHERE c.rowid = ".((int) $id);
$resql = $this->db->query($sql);
if ($resql) {
diff --git a/htdocs/admin/external_rss.php b/htdocs/admin/external_rss.php
index 0b01aef5a18..9b30053bee6 100644
--- a/htdocs/admin/external_rss.php
+++ b/htdocs/admin/external_rss.php
@@ -148,7 +148,7 @@ if (GETPOST("delete")) {
$obj = $db->fetch_object($resql);
$sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes";
- $sql .= " WHERE entity = ".$conf->entity;
+ $sql .= " WHERE entity = ".((int) $conf->entity);
$sql .= " AND box_id = ".((int) $obj->rowid);
$resql = $db->query($sql);
diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php
index 7e96849bb97..100dac6c8c9 100644
--- a/htdocs/comm/propal/card.php
+++ b/htdocs/comm/propal/card.php
@@ -3077,7 +3077,7 @@ if ($action == 'create') {
// Thirdparty
$morehtmlref .= '
' . $soc->getNomUrl(1, 'customer');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $soc->id > 0) {
- $morehtmlref .= ' (' . $langs->trans("OtherProposals") . ')';
+ $morehtmlref .= ' (' . $langs->trans("OtherProposals") . ')';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php
index edc443833b3..9876695778e 100644
--- a/htdocs/commande/card.php
+++ b/htdocs/commande/card.php
@@ -2958,7 +2958,7 @@ if ($action == 'create' && $usercancreate) {
// Thirdparty
$morehtmlref .= '
' . $soc->getNomUrl(1, 'customer');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' (' . $langs->trans("OtherOrders") . ')';
+ $morehtmlref .= ' (' . $langs->trans("OtherOrders") . ')';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php
index eb15a2c0a2e..857cd103275 100644
--- a/htdocs/compta/facture/card.php
+++ b/htdocs/compta/facture/card.php
@@ -5384,7 +5384,7 @@ if ($action == 'create') {
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1, 'customer');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherBills").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherBills").')';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php
index 476fdfcd79d..a883b6751fa 100644
--- a/htdocs/compta/facture/prelevement.php
+++ b/htdocs/compta/facture/prelevement.php
@@ -372,11 +372,11 @@ if ($object->id > 0) {
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1);
if ($type == 'bank-transfer') {
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ';
+ $morehtmlref .= ' ';
}
} else {
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ';
+ $morehtmlref .= ' ';
}
}
// Project
@@ -386,7 +386,7 @@ if ($object->id > 0) {
if (0) { // @phpstan-ignore-line
$morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
if ($action != 'classify') {
- $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' ';
+ $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' ';
}
$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
} else {
diff --git a/htdocs/contrat/agenda.php b/htdocs/contrat/agenda.php
index 438b11096dc..b53c97649e1 100644
--- a/htdocs/contrat/agenda.php
+++ b/htdocs/contrat/agenda.php
@@ -205,7 +205,7 @@ if ($object->id > 0) {
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1);
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherContracts").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherContracts").')';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php
index 9fd4a9c1a71..4cdb1d36c3b 100644
--- a/htdocs/contrat/card.php
+++ b/htdocs/contrat/card.php
@@ -1522,7 +1522,7 @@ if ($action == 'create') {
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1);
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherContracts").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherContracts").')';
}
// Project
if (isModEnabled('project')) {
@@ -1531,7 +1531,7 @@ if ($action == 'create') {
if ($permissiontoadd) {
$morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
if ($action != 'classify') {
- $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' ';
+ $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' ';
}
$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
} else {
diff --git a/htdocs/contrat/class/contratligne.class.php b/htdocs/contrat/class/contratligne.class.php
index 877f99d501d..99c4404e0e0 100644
--- a/htdocs/contrat/class/contratligne.class.php
+++ b/htdocs/contrat/class/contratligne.class.php
@@ -833,7 +833,7 @@ class ContratLigne extends CommonObjectLine
if ($this->date_end > 0) {
$sql .= ",date_fin_validite";
}
- $sql .= ") VALUES ($this->fk_contrat, '', '".$this->db->escape($this->description)."',";
+ $sql .= ") VALUES (".((int) $this->fk_contrat).", '', '".$this->db->escape($this->description)."',";
$sql .= ($this->fk_product > 0 ? $this->fk_product : "null").",";
$sql .= " '".$this->db->escape((string) $this->qty)."',";
$sql .= " '".$this->db->escape($this->vat_src_code)."',";
diff --git a/htdocs/contrat/document.php b/htdocs/contrat/document.php
index 9aeaec27fbf..e2ee9a9f7d6 100644
--- a/htdocs/contrat/document.php
+++ b/htdocs/contrat/document.php
@@ -156,7 +156,7 @@ if ($object->id) {
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1);
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherContracts").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherContracts").')';
}
// Project
if (isModEnabled('project')) {
@@ -165,7 +165,7 @@ if ($object->id) {
if (0) { // @phpstan-ignore-line
$morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
if ($action != 'classify') {
- $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' ';
+ $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' ';
}
$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
} else {
diff --git a/htdocs/contrat/messaging.php b/htdocs/contrat/messaging.php
index c8140647354..c0dd3069a8c 100644
--- a/htdocs/contrat/messaging.php
+++ b/htdocs/contrat/messaging.php
@@ -194,7 +194,7 @@ $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1);
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherContracts").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherContracts").')';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index 9ab5d24404e..27500c38439 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -7235,6 +7235,15 @@ abstract class CommonObject
// if the extrafields row already exists for the object, we update it
if ($linealreadyfound) {
array_shift($sqlColumnValues); // drop the 'fk_object' column because its value won't change
+ if (empty($sqlColumnValues)) {
+ // No column of the target element to update. This happens when the object was created from
+ // another element whose extrafields do not exist on this element (e.g. invoice created from a
+ // shipment: the source line extrafields are copied into array_options but none match facturedet).
+ // The existing row is already correct, so there is nothing to update: avoid an empty "SET" clause
+ // that would produce an invalid SQL statement.
+ $this->db->commit();
+ return 1;
+ }
$sqlColumnValueString = implode(
',',
/**
@@ -9608,10 +9617,12 @@ abstract class CommonObject
if (($mode == 'create') && !in_array(abs($visibility), array(1, 3))) {
continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list
} elseif (($mode == 'edit') && !in_array(abs($visibility), array(1, 3, 4))) {
- // We need to make sure, that the values of hidden extrafields are also part of $_POST. Otherwise, they would be empty after an update of the object. See also getOptionalsFromPost
+ // We need to make sure, that the values of hidden extrafields are also part of $_POST.
+ // Otherwise, they would be empty after an update of the object. See also getOptionalsFromPost
+ // TODO: We should not have this hidden field, and action='update' should be done only if field was POSTED by form.
$ef_name = 'options_' . $key;
$ef_value = $this->array_options[$ef_name] ?? '';
- $out .= '' . "\n";
+ $out .= '' . "\n"; // If trouble to preserve content, we can try dol_htmlentities() instead, but real solution is to remove completely the hidden field (see previous TODO).
continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list and <> 4 = not visible at the creation
} elseif ($mode == 'view' && empty($visibility)) {
continue;
diff --git a/htdocs/core/class/discount.class.php b/htdocs/core/class/discount.class.php
index 60f9d60bc53..28fed72cf21 100644
--- a/htdocs/core/class/discount.class.php
+++ b/htdocs/core/class/discount.class.php
@@ -384,7 +384,7 @@ class DiscountAbsolute extends CommonObject
$sql .= " multicurrency_amount_ht, multicurrency_amount_tva, multicurrency_amount_ttc,";
$sql .= " fk_facture_source, fk_invoice_supplier_source, multicurrency_code, multicurrency_tx";
$sql .= ")";
- $sql .= " VALUES (".$conf->entity.", '".$this->db->idate($this->datec != '' ? $this->datec : dol_now())."', ".((int) $this->socid).", ".(empty($this->discount_type) ? 0 : intval($this->discount_type)).", ".((int) $userid).", '".$this->db->escape($this->description)."',";
+ $sql .= " VALUES (".((int) $conf->entity).", '".$this->db->idate($this->datec != '' ? $this->datec : dol_now())."', ".((int) $this->socid).", ".(empty($this->discount_type) ? 0 : intval($this->discount_type)).", ".((int) $userid).", '".$this->db->escape($this->description)."',";
$sql .= " ".price2num($this->amount_ht).", ".price2num($this->amount_tva).", ";
$sql .= " ".($this->total_localtax1 ? price2num($this->total_localtax1) : 0).", ".($this->total_localtax2 ? price2num($this->total_localtax2) : 0).", ".price2num($this->amount_ttc).", ".price2num($this->tva_tx).",";
$sql .= " ".price2num($this->localtax1_tx).", ".price2num($this->localtax1_type).", ";
diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php
index 9bc6a1ad301..a3c95e6cf38 100644
--- a/htdocs/core/lib/date.lib.php
+++ b/htdocs/core/lib/date.lib.php
@@ -1006,8 +1006,11 @@ function num_public_holiday($timestampStart, $timestampEnd, $countryCodeOrId = '
}
// Increase number of days (on go up into loop)
+ // Advance by exactly one GMT day. We can use += instead of dol_time_plus_duree() here because
+ // inputs of this function are GMT dates (checked above), so a day
+ // is always exactly 86400 seconds.
//var_dump("before ".$jour.' '.$mois.' '.$annee.' '.$timestampStart);
- $timestampStart = dol_time_plus_duree($timestampStart, 1, 'd');
+ $timestampStart += 86400;
//var_dump("after ".$jour.' '.$mois.' '.$annee.' '.$timestampStart);
$i++;
@@ -1477,7 +1480,7 @@ function getWeekNumbersOfMonth($month, $year)
{
$nb_days = cal_days_in_month(CAL_GREGORIAN, $month, $year);
$TWeek = array();
- for ($day = 1; $day < $nb_days; $day++) {
+ for ($day = 1; $day <= $nb_days; $day++) {
$week_number = getWeekNumber($day, $month, $year);
$TWeek[$week_number] = $week_number;
}
diff --git a/htdocs/core/modules/modAccounting.class.php b/htdocs/core/modules/modAccounting.class.php
index 067c030e798..815cdc37110 100644
--- a/htdocs/core/modules/modAccounting.class.php
+++ b/htdocs/core/modules/modAccounting.class.php
@@ -258,10 +258,11 @@ class modAccounting extends DolibarrModules
$this->export_sql_start[$r] = 'SELECT DISTINCT ';
$this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'accounting_account as aa';
- $this->export_sql_end[$r] .= ' ,'.MAIN_DB_PREFIX.'accounting_system as ac';
- $this->export_sql_end[$r] .= ' ,'.MAIN_DB_PREFIX.'accounting_account as aa2';
- $this->export_sql_end[$r] .= ' WHERE ac.pcg_version = aa.fk_pcg_version AND aa.entity IN ('.getEntity('accounting').')';
- $this->export_sql_end[$r] .= ' AND aa2.rowid = aa.account_parent AND aa2.active = 1 AND ac.pcg_version = aa2.fk_pcg_version AND aa2.entity IN ('.getEntity('accounting').')';
+ $this->export_sql_end[$r] .= ' INNER JOIN '.MAIN_DB_PREFIX.'accounting_system as ac ON ac.pcg_version = aa.fk_pcg_version';
+ // LEFT JOIN on the parent account: keep accounts that have no parent (root accounts) or whose parent is
+ // inactive or belongs to another chart (common when a custom chart is derived from a base one).
+ $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'accounting_account as aa2 ON aa2.rowid = aa.account_parent AND aa2.entity IN ('.getEntity('accounting').')';
+ $this->export_sql_end[$r] .= ' WHERE aa.entity IN ('.getEntity('accounting').')';
// Imports
diff --git a/htdocs/core/modules/modBlockedLog.class.php b/htdocs/core/modules/modBlockedLog.class.php
index 145d4da8572..2bef8a3f408 100644
--- a/htdocs/core/modules/modBlockedLog.class.php
+++ b/htdocs/core/modules/modBlockedLog.class.php
@@ -1,6 +1,7 @@
- * Copyright (C) 2026 MDW
+/* Copyright (C) 2017-2025 Laurent Destailleur
+ * Copyright (C) 2026 Regis Houssin
+ * Copyright (C) 2026 MDW
*
* 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
diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php
index 30da0f8780e..cc222ea8043 100644
--- a/htdocs/fourn/commande/card.php
+++ b/htdocs/fourn/commande/card.php
@@ -2448,7 +2448,7 @@ if ($action == 'create') {
}
$morehtmlref .= $object->thirdparty->getNomUrl(1, 'supplier');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
}
}
diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php
index 980a1225d3d..a6ac333555d 100644
--- a/htdocs/fourn/facture/card.php
+++ b/htdocs/fourn/facture/card.php
@@ -3375,7 +3375,7 @@ if ($action == 'create') {
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1, 'supplier');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ';
+ $morehtmlref .= ' ';
}
// Project
if (isModEnabled('project')) {
@@ -4311,7 +4311,7 @@ if ($action == 'create') {
}
// Create payment
- if ($object->type != FactureFournisseur::TYPE_CREDIT_NOTE && $object->status == FactureFournisseur::STATUS_VALIDATED && $object->paid == 0) {
+ if ($object->type != FactureFournisseur::TYPE_CREDIT_NOTE && $object->status == FactureFournisseur::STATUS_VALIDATED && $object->paid == 0 && $usercancreate) {
print ''.$langs->trans('DoPayment').''; // must use facid because id is for payment id not invoice
}
@@ -4321,7 +4321,7 @@ if ($action == 'create') {
if ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE && $object->status == 1 && $object->paid == 0) {
if ($resteapayer == 0) {
print ''.$langs->trans('DoPaymentBack').'';
- } else {
+ } elseif ($usercancreate) {
print ''.$langs->trans('DoPaymentBack').'';
}
}
diff --git a/htdocs/fourn/facture/contact.php b/htdocs/fourn/facture/contact.php
index b1ac80762d9..9128fdb0c2c 100644
--- a/htdocs/fourn/facture/contact.php
+++ b/htdocs/fourn/facture/contact.php
@@ -162,7 +162,7 @@ if ($id > 0 || !empty($ref)) {
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1);
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ';
+ $morehtmlref .= ' ';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/fourn/facture/document.php b/htdocs/fourn/facture/document.php
index 7e6fcd718b2..6aa4d568cbf 100644
--- a/htdocs/fourn/facture/document.php
+++ b/htdocs/fourn/facture/document.php
@@ -126,7 +126,7 @@ if ($object->id > 0 && $upload_dir !== null) {
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1);
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ';
+ $morehtmlref .= ' ';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/fourn/facture/info.php b/htdocs/fourn/facture/info.php
index 512f63b85fd..78a231ef6ac 100644
--- a/htdocs/fourn/facture/info.php
+++ b/htdocs/fourn/facture/info.php
@@ -93,7 +93,7 @@ $morehtmlref .= $form->editfieldval("RefSupplierBill", 'ref_supplier', $object->
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1);
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ';
+ $morehtmlref .= ' ';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/fourn/facture/note.php b/htdocs/fourn/facture/note.php
index bd78cc64fd6..b2f5adedcde 100644
--- a/htdocs/fourn/facture/note.php
+++ b/htdocs/fourn/facture/note.php
@@ -122,7 +122,7 @@ if ($object->id > 0) {
// Thirdparty
$morehtmlref .= '
'.$object->thirdparty->getNomUrl(1);
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ';
+ $morehtmlref .= ' ';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php
index a0236cff7cf..db1de33ce7d 100644
--- a/htdocs/install/upgrade2.php
+++ b/htdocs/install/upgrade2.php
@@ -5658,7 +5658,7 @@ function migrate_blockedlog_add_hmac_key()
$hmac_secret_key = 'BLOCKEDLOGHMAC'.$randomsecret; // Example: 'BLOCKEDLOGHMACY3Ewx37RXbSd8gL9JV8p7Wqw7qvq2K2A'
- $result = dolibarr_set_const($db, 'BLOCKEDLOG_HMAC_KEY', $hmac_secret_key, 'chaine', 0, 'The secret key for HMAC used for blockedlog record', 0); // Will encrypt the value using dolCrypt and store it.
+ $result = dolibarr_set_const($db, 'BLOCKEDLOG_HMAC_KEY', $hmac_secret_key, 'chaine', 0, 'The secret key for HMAC used for blockedlog record', $conf->entity); // Will encrypt the value using dolCrypt and store it.
if ($result < 0) {
dol_print_error($db);
diff --git a/htdocs/mrp/mo_agenda.php b/htdocs/mrp/mo_agenda.php
index c10f3d10e77..1dc616d2315 100644
--- a/htdocs/mrp/mo_agenda.php
+++ b/htdocs/mrp/mo_agenda.php
@@ -170,7 +170,7 @@ if ($object->id > 0) {
if (is_object($object->thirdparty)) {
$morehtmlref .= $object->thirdparty->getNomUrl(1, 'customer');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
}
}
// Project
diff --git a/htdocs/mrp/mo_card.php b/htdocs/mrp/mo_card.php
index e9192c85597..042119b28ce 100644
--- a/htdocs/mrp/mo_card.php
+++ b/htdocs/mrp/mo_card.php
@@ -691,7 +691,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
if (is_object($object->thirdparty)) {
$morehtmlref .= $object->thirdparty->getNomUrl(1, 'customer');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
}
}
// Project
diff --git a/htdocs/mrp/mo_document.php b/htdocs/mrp/mo_document.php
index e2fdcc269f1..84af4445a09 100644
--- a/htdocs/mrp/mo_document.php
+++ b/htdocs/mrp/mo_document.php
@@ -142,7 +142,7 @@ if ($object->id && $upload_dir !== null) {
if (is_object($object->thirdparty)) {
$morehtmlref .= $object->thirdparty->getNomUrl(1, 'customer');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
}
}
// Project
diff --git a/htdocs/mrp/mo_movements.php b/htdocs/mrp/mo_movements.php
index 928e320d95e..5c54251c357 100644
--- a/htdocs/mrp/mo_movements.php
+++ b/htdocs/mrp/mo_movements.php
@@ -329,7 +329,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
if (is_object($object->thirdparty)) {
$morehtmlref .= $object->thirdparty->getNomUrl(1, 'customer');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
}
}
// Project
diff --git a/htdocs/mrp/mo_note.php b/htdocs/mrp/mo_note.php
index edacf43f88d..b98968dbbb5 100644
--- a/htdocs/mrp/mo_note.php
+++ b/htdocs/mrp/mo_note.php
@@ -119,7 +119,7 @@ if ($id > 0 || !empty($ref)) {
if (is_object($object->thirdparty)) {
$morehtmlref .= $object->thirdparty->getNomUrl(1, 'customer');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
}
}
// Project
diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php
index 2cc6ed2716e..ced1ab85f89 100644
--- a/htdocs/mrp/mo_production.php
+++ b/htdocs/mrp/mo_production.php
@@ -710,7 +710,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
if (is_object($object->thirdparty)) {
$morehtmlref .= $object->thirdparty->getNomUrl(1, 'customer');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
}
}
diff --git a/htdocs/product/stock/stocktransfer/stocktransfer_card.php b/htdocs/product/stock/stocktransfer/stocktransfer_card.php
index 4e6ed30b29a..744d2a75bc1 100644
--- a/htdocs/product/stock/stocktransfer/stocktransfer_card.php
+++ b/htdocs/product/stock/stocktransfer/stocktransfer_card.php
@@ -621,7 +621,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
// Thirdparty
$morehtmlref .= empty($object->thirdparty) ? '' : $object->thirdparty->getNomUrl(1, 'customer');
if (!getDolGlobalInt('MAIN_DISABLE_OTHER_LINK') && !empty($object->thirdparty) && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/product/stock/stocktransfer/stocktransfer_contact.php b/htdocs/product/stock/stocktransfer/stocktransfer_contact.php
index 94a02f0af4d..11828f6df4f 100644
--- a/htdocs/product/stock/stocktransfer/stocktransfer_contact.php
+++ b/htdocs/product/stock/stocktransfer/stocktransfer_contact.php
@@ -163,7 +163,7 @@ if ($object->id > 0) {
// Thirdparty
$morehtmlref .= empty($object->thirdparty) ? '' : $object->thirdparty->getNomUrl(1, 'customer');
if (!getDolGlobalInt('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherOrders").')';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php
index bc9dc9dff64..ab913073475 100644
--- a/htdocs/public/payment/paymentok.php
+++ b/htdocs/public/payment/paymentok.php
@@ -392,7 +392,7 @@ if (isModEnabled('stripe') && $paymentmethod === 'stripe') {
// Check we are coming from the newpaymentpage
// Bypass session check when returning from Stripe confirmPayment() (mode STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION=2)
// In that case, payment_intent is passed in GET by Stripe and PaymentIntent::retrieve() below acts as verification
- if (empty(GETPOST('payment_intent', 'alphanohtml')) && GETPOST('paymentoksessioncode') !== $_SESSION['paymentoksessioncode']) {
+ if (!GETPOST('payment_intent', 'alphanohtml') && GETPOST('paymentoksessioncode') !== $_SESSION['paymentoksessioncode']) {
$error++;
$errmsg = 'Attempted direct access to the paymentok page without a valid session.';
dol_syslog($errmsg, LOG_ERR, 0, '_payment');
diff --git a/htdocs/societe/class/companybankaccount.class.php b/htdocs/societe/class/companybankaccount.class.php
index 2a5e8948cfc..c9b0a64ae84 100644
--- a/htdocs/societe/class/companybankaccount.class.php
+++ b/htdocs/societe/class/companybankaccount.class.php
@@ -405,7 +405,7 @@ class CompanyBankAccount extends Account
$this->db->begin();
$sql = "INSERT INTO ".MAIN_DB_PREFIX."societe_rib (fk_soc, type, datec, model_pdf)";
- $sql .= " VALUES (".((int) $this->socid).", '".$this->type."', '".$this->db->idate($this->datec)."',";
+ $sql .= " VALUES (".((int) $this->socid).", '".$this->db->escape($this->type)."', '".$this->db->idate($this->datec)."',";
$sql .= " '".$this->db->escape(getDolGlobalString("BANKADDON_PDF"))."'";
$sql .= ")";
$resql = $this->db->query($sql);
diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php
index cacec75e83b..79ea5f23658 100644
--- a/htdocs/supplier_proposal/card.php
+++ b/htdocs/supplier_proposal/card.php
@@ -1941,7 +1941,7 @@ if ($action == 'create') {
// Thirdparty
$morehtmlref .= $object->thirdparty->getNomUrl(1, 'supplier');
if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) {
- $morehtmlref .= ' ('.$langs->trans("OtherProposals").')';
+ $morehtmlref .= ' ('.$langs->trans("OtherProposals").')';
}
// Project
if (isModEnabled('project')) {
diff --git a/htdocs/user/class/userbankaccount.class.php b/htdocs/user/class/userbankaccount.class.php
index 19db5f1514e..be10af47621 100644
--- a/htdocs/user/class/userbankaccount.class.php
+++ b/htdocs/user/class/userbankaccount.class.php
@@ -96,7 +96,7 @@ class UserBankAccount extends Account
$now = dol_now();
$sql = "INSERT INTO ".$this->db->prefix()."user_rib (fk_user, datec)";
- $sql .= " VALUES (".$this->userid.", '".$this->db->idate($now)."')";
+ $sql .= " VALUES (".((int) $this->userid).", '".$this->db->idate($now)."')";
$resql = $this->db->query($sql);
if ($resql) {
if ($this->db->affected_rows($resql)) {
diff --git a/test/phpunit/CodingPhpTest.php b/test/phpunit/CodingPhpTest.php
index 65bec3fd9b5..01d385aab51 100644
--- a/test/phpunit/CodingPhpTest.php
+++ b/test/phpunit/CodingPhpTest.php
@@ -118,7 +118,7 @@ class CodingPhpTest extends CommonClassTest
// To process only 1 file, uncomment this
/*
foreach($returnlist as $key => $val) {
- if ($val[0]['name'] != 'societe.class.php') {
+ if ($val[0]['name'] != 'companybankaccount.class.php') {
unset($returnlist[$key]);
}
}
@@ -440,21 +440,79 @@ class CodingPhpTest extends CommonClassTest
$this->assertTrue($ok, 'Found a forged SQL string that does not use escape or int cast for file '.$file['relativename']);
//exit;
- // Check sql string VALUES ... , ".$xxx
- // with xxx that is not 'db-' (for $db->escape). It means we forget a ' if string, or an (int) if int, when forging sql request.
+ // Check that forged sql string is using ' instead of " as string PHP quotes
$ok = true;
$matches = array();
- preg_match_all('/(VALUES).*,\s*"\s*\.\s*\$(...)/', $filecontent, $matches, PREG_SET_ORDER);
+ preg_match_all('/\$sql \.= \'\s*VALUES.*\$/', $filecontent, $matches, PREG_SET_ORDER);
foreach ($matches as $key => $val) {
- if ($val[1] == 'VALUES' && $val[2] == 'db-') { // exclude $db->escape(
- continue;
- }
- if ($val[1] == 'VALUES' && $val[2] == 'thi' && preg_match('/this->db->encrypt/', $val[0])) { // exclude ".$this->db->encrypt(
- continue;
- }
+ //if ($val[1] != '\'"' && $val[1] != '\'\'') {
var_dump($matches);
$ok = false;
break;
+ //}
+ //if ($reg[0] != 'db') $ok=false;
+ }
+ //print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
+ $this->assertTrue($ok, 'Found a forged SQL string that mix on same line the use of \' for PHP string and PHP variables in file '.$file['relativename'].' Use " to forge PHP string like this: $sql = "SELECT ".$myvar...');
+ //exit;
+
+ // Check that forged sql string is using ' instead of " as string PHP quotes
+ $ok = true;
+ $matches = array();
+ preg_match_all('/\$sql \.?= \'SELECT.*\$/', $filecontent, $matches, PREG_SET_ORDER);
+ foreach ($matches as $key => $val) {
+ var_dump($matches);
+ $ok = false;
+ break;
+ }
+ $this->assertTrue($ok, 'Found a forged SQL string that mix on same line the use of \' for PHP string and PHP variables in file '.$file['relativename'].' Use " to forge PHP string like this: $sql = "SELECT ".$myvar...');
+
+ // Check sql string VALUES ... , ".$xxx or string VALUES ... , '".$xxx
+ // with xxx that is not 'db-' (for $db->escape). It means we forget a ' if string, or an (int) if int, when forging sql request.
+ // ... = " VALUES (".((int) $this->socid).", '".$this->type."', '".$this->db->idate($this->datec)."',";
+
+ $ok = true;
+ $matches = array();
+ preg_match_all('/(VALUES).*,\s*\'?"\s*\.\s*\$([a-z\-\>]+)/', $filecontent, $matches, PREG_SET_ORDER);
+ foreach ($matches as $key => $val) {
+ $matches2 = array();
+ preg_match_all('/,\s*\'?"\s*\.\s*\$([a-z\-\>]+)/', $val[0], $matches2, PREG_SET_ORDER);
+ foreach ($matches2 as $key2 => $val2) {
+ if ($val2[1] == 'mydb->escape') { // exclude ".$mydb->escape(
+ continue;
+ }
+ if ($val2[1] == 'dbsession->escape') { // exclude ".$dbsession->escape(
+ continue;
+ }
+ if ($val2[1] == 'dbsession->idate') { // exclude ".$dbsession->escape(
+ continue;
+ }
+ if ($val2[1] == 'this->db->encrypt') { // exclude ".$this->db->encrypt(
+ continue;
+ }
+ if ($val2[1] == 'this->db->escape') { // exclude ".$this->db->escape(
+ continue;
+ }
+ if ($val2[1] == 'this->db->idate') { // exclude ".$this->db->idate(
+ continue;
+ }
+ if ($val2[1] == 'db->encrypt') { // exclude ".$db->encrypt(
+ continue;
+ }
+ if ($val2[1] == 'db->escape') { // exclude ".$db->escape(
+ continue;
+ }
+ if ($val2[1] == 'db->idate') { // exclude ".$db->idate(
+ continue;
+ }
+ if ($val2[1] == 'this->escape') { // exclude ".$this->db->encrypt(
+ continue;
+ }
+
+ var_dump($matches2);
+ $ok = false;
+ break;
+ }
}
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
$this->assertTrue($ok, 'Found non quoted or not casted var in sql request '.$file['relativename'].' - Bad.');