From 54a0245c4debec3bf7593e7b18090a362c38af74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Maldonado?= Date: Wed, 4 Oct 2023 17:48:30 +0200 Subject: [PATCH 01/11] FIX: modification of complementary attributes in commercial proposals The db object must not be cloned in order to avoid a PHP Fatal error: Uncaught Exception: Serialization of 'PgSql\Connection' is not allowed This commit replaces the dol_clone function by the one in the 17.0 branch --- htdocs/comm/propal/card.php | 2 +- htdocs/core/lib/functions.lib.php | 28 +++++++++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 7b7389b5f79..3df49b6c207 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1467,7 +1467,7 @@ if (empty($reshook)) { // warehouse $result = $object->setWarehouse(GETPOST('warehouse_id', 'int')); } elseif ($action == 'update_extras') { - $object->oldcopy = dol_clone($object); + $object->oldcopy = dol_clone($object, 2); // Fill array 'array_options' with data from update form $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml')); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 9827414c3ff..e9ae5bdfe15 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1145,29 +1145,43 @@ function dol_buildpath($path, $type = 0, $returnemptyifnotfound = 0) } /** - * Create a clone of instance of object (new instance with same value for properties) - * With native = 0: Property that are reference are also new object (full isolation clone). This means $this->db of new object is not valid. + * Create a clone of instance of object (new instance with same value for each properties) + * With native = 0: Property that are reference are different memory area in the new object (full isolation clone). This means $this->db of new object may not be valid. * With native = 1: Use PHP clone. Property that are reference are same pointer. This means $this->db of new object is still valid but point to same this->db than original object. + * With native = 2: Property that are reference are different memory area in the new object (full isolation clone). Only scalar and array values are cloned. This means $this->db of new object is not valid. * * @param object $object Object to clone - * @param int $native 0=Full isolation method, 1=Native PHP method + * @param int $native 0=Full isolation method, 1=Native PHP method, 2=Full isolation method keeping only scalar and array properties (recommended) * @return object Clone object * @see https://php.net/manual/language.oop5.cloning.php */ function dol_clone($object, $native = 0) { - if (empty($native)) { + if ($native == 0) { + // deprecated method, use the method with native = 2 instead $tmpsavdb = null; if (isset($object->db) && isset($object->db->db) && is_object($object->db->db) && get_class($object->db->db) == 'PgSql\Connection') { $tmpsavdb = $object->db; - unset($object->db); // Such property can not be serialized when PgSql/Connection + unset($object->db); // Such property can not be serialized with pgsl (when object->db->db = 'PgSql\Connection') } - $myclone = unserialize(serialize($object)); // serialize then unserialize is hack to be sure to have a new object for all fields + $myclone = unserialize(serialize($object)); // serialize then unserialize is a hack to be sure to have a new object for all fields - if ($tmpsavdb) { + if (!empty($tmpsavdb)) { $object->db = $tmpsavdb; } + } elseif ($native == 2) { + // recommended method to have a full isolated cloned object + $myclone = new stdClass(); + $tmparray = get_object_vars($object); // return only public properties + + if (is_array($tmparray)) { + foreach ($tmparray as $propertykey => $propertyval) { + if (is_scalar($propertyval) || is_array($propertyval)) { + $myclone->$propertykey = $propertyval; + } + } + } } else { $myclone = clone $object; // PHP clone is a shallow copy only, not a real clone, so properties of references will keep the reference (refering to the same target/variable) } From 8e8528368aed06ab208e48a033af4bc649bb755f Mon Sep 17 00:00:00 2001 From: am97 Date: Tue, 10 Oct 2023 21:17:25 +0200 Subject: [PATCH 02/11] fix: result checks for PHP 8.1 (#26175) --- htdocs/admin/translation.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/translation.php b/htdocs/admin/translation.php index 1e667e7abb4..998ce46314d 100644 --- a/htdocs/admin/translation.php +++ b/htdocs/admin/translation.php @@ -116,7 +116,7 @@ if ($action == 'update') { $sql = "UPDATE ".MAIN_DB_PREFIX."overwrite_trans set transkey = '".$db->escape($transkey)."', transvalue = '".$db->escape($transvalue)."' WHERE rowid = ".((int) GETPOST('rowid', 'int')); $result = $db->query($sql); - if ($result > 0) { + if ($result) { $db->commit(); setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); $action = ""; @@ -154,7 +154,7 @@ if ($action == 'add') { $sql = "INSERT INTO ".MAIN_DB_PREFIX."overwrite_trans(lang, transkey, transvalue, entity) VALUES ('".$db->escape($langcode)."','".$db->escape($transkey)."','".$db->escape($transvalue)."', ".((int) $conf->entity).")"; $result = $db->query($sql); - if ($result > 0) { + if ($result) { $db->commit(); setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); $action = ""; @@ -176,7 +176,7 @@ if ($action == 'add') { if ($action == 'delete') { $sql = "DELETE FROM ".MAIN_DB_PREFIX."overwrite_trans WHERE rowid = ".((int) $id); $result = $db->query($sql); - if ($result >= 0) { + if ($result) { setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs'); } else { dol_print_error($db); @@ -296,7 +296,7 @@ foreach ($modulesdir as $keydir => $tmpsearchdir) { $result = $newlang->load($langkey, 0, 0, '', 0); // Load translation files + database overwrite $result = $newlangfileonly->load($langkey, 0, 0, '', 1); // Load translation files only - if ($result < 0) { + if (!$result) { print 'Failed to load language file '.$tmpfile.'
'."\n"; } else { $listoffiles[$langkey] = $tmpfile; From 465fe0ffd4129030bd28c65249e86971ef014e80 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Oct 2023 04:29:52 +0200 Subject: [PATCH 03/11] Close #24481 --- htdocs/compta/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index e426087a0e0..acce2166d11 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -5390,7 +5390,6 @@ if ($action == 'create') { if (empty($reshook)) { $params = array( 'attr' => array( - 'title' => '', 'class' => 'classfortooltip' ) ); @@ -5403,6 +5402,7 @@ if ($action == 'create') { if (!empty($conf->global->INVOICE_CAN_BE_EDITED_EVEN_IF_PAYMENT_DONE) || ($resteapayer == price2num($object->total_ttc, 'MT', 1) && empty($object->paye))) { if (!$objectidnext && $object->is_last_in_cycle()) { if ($usercanunvalidate) { + $params['attr']['title'] = ''; print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER['PHP_SELF'].'?facid='.$object->id.'&action=modif&token='.newToken(), '', true, $params); } else { $params['attr']['title'] = $langs->trans('NotEnoughPermissions'); From 62b6988438d24f4bae097b6cc87495c1e8c0dcd4 Mon Sep 17 00:00:00 2001 From: am97 Date: Wed, 11 Oct 2023 18:02:44 +0200 Subject: [PATCH 04/11] Fix: allow changing dates on refused expense report (#26185) --- htdocs/expensereport/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 80f5d0baa41..14f7cd6e408 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -320,7 +320,7 @@ if (empty($reshook)) { } } - if ($action == 'update' && $user->rights->expensereport->creer) { + if (($action == 'update' || $action == 'updateFromRefuse') && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); From b9136ee59c56e2d17823a2216e246c193b87c3c9 Mon Sep 17 00:00:00 2001 From: am97 Date: Wed, 11 Oct 2023 19:02:11 +0200 Subject: [PATCH 05/11] FIX: modification of complementary attributes in invoices (#26180) Fixes the following error: PHP Fatal error: Uncaught Exception: Serialization of PgSql\Connection is not allowed in /var/www/html/core/lib/functions.lib.php:1168 Stack trace: #0 /var/www/html/core/lib/functions.lib.php(1168): serialize() #1 /var/www/html/compta/facture/card.php(2798): dol_clone() #2 {main} --- htdocs/compta/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index acce2166d11..36c90588a34 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -2795,7 +2795,7 @@ if (empty($reshook)) { if ($action == 'update_extras') { - $object->oldcopy = dol_clone($object); + $object->oldcopy = dol_clone($object, 2); // Fill array 'array_options' with data from add form $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml')); From 4675a93fc8ded39e85a5d66aef18d675b285e177 Mon Sep 17 00:00:00 2001 From: noec764 <58433943+noec764@users.noreply.github.com> Date: Sun, 15 Oct 2023 21:18:03 +0200 Subject: [PATCH 06/11] FIX: Error handling for computed values on import (#24897) * FIX: Error handling for computed values on import * Fixing style errors. --------- Co-authored-by: stickler-ci --- .../modules/import/import_csv.modules.php | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/htdocs/core/modules/import/import_csv.modules.php b/htdocs/core/modules/import/import_csv.modules.php index e76d7a06c03..afa451a0e8b 100644 --- a/htdocs/core/modules/import/import_csv.modules.php +++ b/htdocs/core/modules/import/import_csv.modules.php @@ -650,7 +650,17 @@ class ImportCsv extends ModeleImports } $classinstance = new $class($this->db); $res = call_user_func_array(array($classinstance, $method), array(&$arrayrecord, $listfields, ($key - 1))); - $newval = $res; // We get new value computed. + if (empty($classinstance->error) && empty($classinstance->errors)) { + $newval = $res; // We get new value computed. + } else { + $this->errors[$error]['type'] = 'CLASSERROR'; + $this->errors[$error]['lib'] = implode( + "\n", + array_merge([$classinstance->error], $classinstance->errors) + ); + $errorforthistable++; + $error++; + } } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') { $newval = price2num($newval); } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'accountingaccount') { @@ -810,12 +820,22 @@ class ImportCsv extends ModeleImports } $classinstance = new $class($this->db); $res = call_user_func_array(array($classinstance, $method), array(&$arrayrecord, $listfields, ($key - 1))); - $fieldArr = explode('.', $fieldname); - if (count($fieldArr) > 0) { - $fieldname = $fieldArr[1]; + if (empty($classinstance->error) && empty($classinstance->errors)) { + $fieldArr = explode('.', $fieldname); + if (count($fieldArr) > 0) { + $fieldname = $fieldArr[1]; + } + $listfields[] = $fieldname; + $listvalues[] = $res; + } else { + $this->errors[$error]['type'] = 'CLASSERROR'; + $this->errors[$error]['lib'] = implode( + "\n", + array_merge([$classinstance->error], $classinstance->errors) + ); + $errorforthistable++; + $error++; } - $listfields[] = $fieldname; - $listvalues[] = $res; } } } else { From ee3bd43473c5e447432c33a429e10cb6006bb20b Mon Sep 17 00:00:00 2001 From: am97 Date: Mon, 23 Oct 2023 18:39:22 +0200 Subject: [PATCH 07/11] FIX user creation when LDAP is configured (#26332) --- htdocs/core/class/ldap.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 847a1bf32e3..4515ed95951 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -1058,7 +1058,7 @@ class Ldap if (is_array($attributeArray)) { // Return list with required fields $attributeArray = array_values($attributeArray); // This is to force to have index reordered from 0 (not make ldap_search fails) - dol_syslog(get_class($this)."::getRecords connection=".get_resource_type($this->connection)." userDn=".$userDn." filter=".$filter." attributeArray=(".join(',', $attributeArray).")"); + dol_syslog(get_class($this)."::getRecords connection=".$this->connectedServer.":".$this->serverPort." userDn=".$userDn." filter=".$filter." attributeArray=(".join(',', $attributeArray).")"); //var_dump($attributeArray); $this->result = @ldap_search($this->connection, $userDn, $filter, $attributeArray); } else { From 9001a1d799ab6e2f922121dfc87b2ceb25417010 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Oct 2023 02:02:23 +0200 Subject: [PATCH 08/11] Fix regression generating false warning in translation page --- htdocs/admin/translation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/translation.php b/htdocs/admin/translation.php index 998ce46314d..fce5f3f3938 100644 --- a/htdocs/admin/translation.php +++ b/htdocs/admin/translation.php @@ -296,7 +296,7 @@ foreach ($modulesdir as $keydir => $tmpsearchdir) { $result = $newlang->load($langkey, 0, 0, '', 0); // Load translation files + database overwrite $result = $newlangfileonly->load($langkey, 0, 0, '', 1); // Load translation files only - if (!$result) { + if ($result < 0) { print 'Failed to load language file '.$tmpfile.'
'."\n"; } else { $listoffiles[$langkey] = $tmpfile; From 21f602bf05551f9375e3292958de234ed2c4df67 Mon Sep 17 00:00:00 2001 From: sonikf <93765174+sonikf@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:01:51 +0300 Subject: [PATCH 09/11] fix suppliers_bills_payment link (#26361) --- htdocs/core/menus/init_menu_auguria.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index 9ac9eff352e..a01e673e862 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -222,7 +222,7 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_invoice->enabled', __HANDLER__, 'left', 1601__+MAX_llx_menu__, 'billing', '', 1600__+MAX_llx_menu__, '/fourn/facture/card.php?mainmenu=billing&action=create&leftmenu=suppliers_bills', 'NewBill', 1, 'bills', '$user->rights->fournisseur->facture->creer', '', 2, 0, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_invoice->enabled', __HANDLER__, 'left', 1602__+MAX_llx_menu__, 'billing', '', 1600__+MAX_llx_menu__, '/fourn/facture/list.php?mainmenu=billing&leftmenu=suppliers_bills', 'List', 1, 'bills', '$user->rights->fournisseur->facture->lire', '', 2, 1, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_invoice->enabled', __HANDLER__, 'left', 1603__+MAX_llx_menu__, 'billing', 'suppliers_bills_payment', 1600__+MAX_llx_menu__, '/fourn/facture/paiement.php?mainmenu=billing&leftmenu=suppliers_bills_payment', 'Payments', 1, 'bills', '$user->rights->fournisseur->facture->lire', '', 2, 2, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_invoice->enabled', __HANDLER__, 'left', 1603__+MAX_llx_menu__, 'billing', 'suppliers_bills_payment', 1600__+MAX_llx_menu__, '/fourn/paiement/list.php?mainmenu=billing&leftmenu=suppliers_bills_payment', 'Payments', 1, 'bills', '$user->rights->fournisseur->facture->lire', '', 2, 2, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_invoice->enabled', __HANDLER__, 'left', 1605__+MAX_llx_menu__, 'billing', 'suppliers_bills_reports', 1603__+MAX_llx_menu__, '/fourn/facture/rapport.php?mainmenu=billing&leftmenu=suppliers_bills_reports', 'Reporting', 2, 'bills', '$user->rights->fournisseur->facture->lire', '', 2, 1, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_invoice->enabled', __HANDLER__, 'left', 1604__+MAX_llx_menu__, 'billing', 'customers_bills_stats', 1600__+MAX_llx_menu__, '/compta/facture/stats/index.php?mainmenu=billing&leftmenu=customers_bills_stats&mode=supplier', 'Statistics', 1, 'bills', '$user->rights->fournisseur->facture->lire', '', 2, 8, __ENTITY__); From 6445189eb44be96696f4b04ecd90d499304bb977 Mon Sep 17 00:00:00 2001 From: HENRY Florian Date: Thu, 26 Oct 2023 12:37:47 +0200 Subject: [PATCH 10/11] fix: document linked in asset module permission (#26357) --- htdocs/asset/document.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/asset/document.php b/htdocs/asset/document.php index 96b222b26c1..be4aa3b1557 100644 --- a/htdocs/asset/document.php +++ b/htdocs/asset/document.php @@ -72,7 +72,7 @@ if ($id > 0 || !empty($ref)) { $upload_dir = $conf->asset->multidir_output[$object->entity ? $object->entity : $conf->entity]."/".get_exdir(0, 0, 0, 1, $object); } -$permissiontoadd = $user->rights->asset->asset->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php +$permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php // Security check (enable the most restrictive one) if ($user->socid > 0) accessforbidden(); From 301064afb610e73c836753ff3220c89315849620 Mon Sep 17 00:00:00 2001 From: daraelmin Date: Thu, 2 Nov 2023 01:33:46 +0100 Subject: [PATCH 11/11] Merge branch '17.0' of git@github.com:Dolibarr/dolibarr.git into 17.0 --- htdocs/adherents/subscription.php | 8 +++++--- htdocs/public/payment/paymentok.php | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index cf0ad445c92..54ea3ebe998 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -79,9 +79,6 @@ $extrafields->fetch_name_optionals_label($object->table_element); $errmsg = ''; -$defaultdelay = 1; -$defaultdelayunit = 'y'; - // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('subscription')); @@ -211,6 +208,8 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! // Subscription informations $datesubscription = 0; $datesubend = 0; + $defaultdelay = !empty($adht->duration_value) ? $adht->duration_value : 1; + $defaultdelayunit = !empty($adht->duration_unit) ? $adht->duration_unit : 'y'; $paymentdate = ''; // Do not use 0 here, default value is '' that means not filled where 0 means 1970-01-01 if (GETPOST("reyear", "int") && GETPOST("remonth", "int") && GETPOST("reday", "int")) { $datesubscription = dol_mktime(0, 0, 0, GETPOST("remonth", "int"), GETPOST("reday", "int"), GETPOST("reyear", "int")); @@ -469,6 +468,9 @@ if ($rowid > 0) { $adht->fetch($object->typeid); + $defaultdelay = !empty($adht->duration_value) ? $adht->duration_value : 1; + $defaultdelayunit = !empty($adht->duration_unit) ? $adht->duration_unit : 'y'; + $head = member_prepare_head($object); $rowspan = 10; diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 241fa09dabc..44411db975d 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -386,9 +386,6 @@ if ($ispaymentok) { // Create complementary actions (this include creation of thirdparty) // Send confirmation email - $defaultdelay = 1; - $defaultdelayunit = 'y'; - // Record subscription include_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; include_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php'; @@ -399,6 +396,9 @@ if ($ispaymentok) { $result1 = $object->fetch((int) $tmptag['MEM']); $result2 = $adht->fetch($object->typeid); + $defaultdelay = !empty($adht->duration_value) ? $adht->duration_value : 1; + $defaultdelayunit = !empty($adht->duration_unit) ? $adht->duration_unit : 'y'; + dol_syslog("We have to process member with id=".$tmptag['MEM']." result1=".$result1." result2=".$result2, LOG_DEBUG, 0, '_payment'); if ($result1 > 0 && $result2 > 0) {