From d58fbd8eb4393d8f7932158a1fcf5d0d0138a373 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 27 Feb 2025 06:51:00 +0100 Subject: [PATCH 01/71] NEW Add invoice tags --- htdocs/categories/class/categorie.class.php | 36 ++++--- htdocs/categories/viewcat.php | 87 +++++++++++++++++ htdocs/compta/facture/card.php | 94 ++++++++++++++----- htdocs/compta/facture/class/facture.class.php | 31 +++++- htdocs/core/menus/standard/eldy.lib.php | 9 +- htdocs/core/modules/modCategorie.class.php | 49 ++++++++-- htdocs/langs/en_US/categories.lang | 1 + 7 files changed, 262 insertions(+), 45 deletions(-) diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index 6620bda7696..77fcaff32a8 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -1,18 +1,19 @@ - * Copyright (C) 2005 Davoleau Brice - * Copyright (C) 2005 Rodolphe Quiedeville - * Copyright (C) 2006-2012 Regis Houssin - * Copyright (C) 2006-2012 Laurent Destailleur - * Copyright (C) 2007 Patrick Raguin - * Copyright (C) 2013-2016 Juanjo Menent - * Copyright (C) 2013-2018 Philippe Grand - * Copyright (C) 2015 Marcos García - * Copyright (C) 2015 Raphaël Doursenaud - * Copyright (C) 2016-2024 Charlene Benke - * Copyright (C) 2018-2024 Frédéric France - * Copyright (C) 2023-2024 Benjamin Falière - * Copyright (C) 2024 MDW +/* Copyright (C) 2005 Matthieu Valleton + * Copyright (C) 2005 Davoleau Brice + * Copyright (C) 2005 Rodolphe Quiedeville + * Copyright (C) 2006-2012 Regis Houssin + * Copyright (C) 2006-2012 Laurent Destailleur + * Copyright (C) 2007 Patrick Raguin + * Copyright (C) 2013-2016 Juanjo Menent + * Copyright (C) 2013-2018 Philippe Grand + * Copyright (C) 2015 Marcos García + * Copyright (C) 2015 Raphaël Doursenaud + * Copyright (C) 2016-2024 Charlene Benke + * Copyright (C) 2018-2024 Frédéric France + * Copyright (C) 2022-2023 Solution Libre SAS + * Copyright (C) 2023-2024 Benjamin Falière + * Copyright (C) 2024 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 @@ -64,6 +65,7 @@ class Categorie extends CommonObject const TYPE_KNOWLEDGEMANAGEMENT = 'knowledgemanagement'; const TYPE_FICHINTER = 'fichinter'; const TYPE_ORDER = 'order'; + const TYPE_INVOICE = 'invoice'; /** * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png @@ -91,6 +93,7 @@ class Categorie extends CommonObject 'knowledgemanagement' => 13, 'fichinter' => 14, 'order' => 16, + 'invoice' => 17, ); /** @@ -115,6 +118,7 @@ class Categorie extends CommonObject 13 => 'knowledgemanagement', 14 => 'fichinter', 16 => 'order', + 17 => 'invoice', ); /** @@ -162,6 +166,7 @@ class Categorie extends CommonObject 'knowledgemanagement' => 'KnowledgeRecord', 'fichinter' => 'Fichinter', 'order' => 'Commande', + 'invoice' => 'Facture' ); /** @@ -186,6 +191,7 @@ class Categorie extends CommonObject 'knowledgemanagement' => 'KnowledgemanagementsCategoriesArea', 'fichinter' => 'FichintersCategoriesArea', 'order' => 'OrderCategoriesArea', + 'invoice' => 'InvoiceCategoriesArea' ); /** @@ -203,6 +209,7 @@ class Categorie extends CommonObject 'knowledgemanagement' => 'knowledgemanagement_knowledgerecord', 'fichinter' => 'fichinter', 'order' => 'commande', + 'invoice' => 'facture' ); /** @@ -268,6 +275,7 @@ class Categorie extends CommonObject * @see Categorie::TYPE_TICKET * @see Categorie::TYPE_FICHINTER * @see Categorie::TYPE_ORDER + * @see Categorie::TYPE_INVOICE */ public $type; diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index f3108ad6023..5fd990f462e 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -6,6 +6,7 @@ * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2020 Tobias Sekan * Copyright (C) 2020 Josep Lluís Amador + * Copyright (C) 2022-2023 Solution Libre SAS * Copyright (C) 2024 MDW * Copyright (C) 2024 Frédéric France * Copyright (C) 2024 Alexandre Spangaro @@ -176,6 +177,11 @@ if ($id > 0 && $removeelem > 0 && $action == 'unlink') { // Test on permission n $tmpobject = new Commande($db); $result = $tmpobject->fetch($removeelem); $elementtype = 'order'; + } elseif ($type == Categorie::TYPE_INVOICE && $user->hasRight('facture', 'creer')) { + require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + $tmpobject = new Facture($db); + $result = $tmpobject->fetch($removeelem); + $elementtype = 'invoice'; } else { dol_print_error(null, "Not supported value of type = ".$type); } @@ -247,6 +253,10 @@ if ($elemid && $action == 'addintocategory') { // Test on permission not require require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; $newobject = new Commande($db); $elementtype = 'order'; + } elseif ($type == Categorie::TYPE_INVOICE && $user->hasRight('facture', 'creer')) { + require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + $newobject = new Facture($db); + $elementtype = 'order'; } else { dol_print_error(null, "Not supported value of type = ".$type); } @@ -1498,6 +1508,83 @@ if ($type == Categorie::TYPE_ORDER) { } } +// List of Invoices +if ($type == Categorie::TYPE_INVOICE) { + require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + + $permission = $user->rights->facture->creer; + + $objects = $object->getObjectsInCateg($type, 0, $limit, $offset); + if ($objects < 0) { + dol_print_error($db, $object->error, $object->errors); + } else { + // Form to add record into a category + $showclassifyform = 1; + if ($showclassifyform) { + print '
'; + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print '
'; + print $langs->trans("AddInvoiceIntoCategory").'  '; + $form->selectInvoice(-1, '', 'elemid', 24, 0, '1', 0, 0, 0, 'maxwidth500', '', ''); + print '
'; + print '
'; + } + + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + + print '
'; + $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($objects); $nbtotalofrecords = ''; $newcardbutton = ''; + + print_barre_liste($langs->trans("BillsCustomers"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'bill', 0, $newcardbutton, '', $limit); + + print "\n"; + print ''."\n"; + + if (count($objects) > 0) { + $i = 0; + foreach ($objects as $key => $invoice) { + $i++; + if ($i > $limit) { + break; + } + + print "\t".''."\n"; + print '\n"; + print '\n"; + // Link to delete from category + print '\n"; + } + } else { + print ''; + } + print "
'.$langs->trans("Ref").'
'; + print $invoice->getNomUrl(1); + print "'.$invoice->ref."'; + if ($permission) { + print ""; + print $langs->trans("DeleteFromCat"); + print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); + print ""; + } + print "
'.$langs->trans("ThisCategoryHasNoItems").'
\n"; + + print '
'."\n"; + } +} + // Note that $action and $object may have been modified by some hooks $parameters = array('type' => $type, 'id' => $id, 'label' => $label); $reshook = $hookmanager->executeHooks('addMoreCategoriesList', $parameters, $object, $action); diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 0d3db095797..6387df729de 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -1,24 +1,24 @@ - * Copyright (C) 2004 Eric Seigne - * Copyright (C) 2004-2020 Laurent Destailleur - * Copyright (C) 2005 Marc Barilley / Ocebo - * Copyright (C) 2005-2015 Regis Houssin - * Copyright (C) 2006 Andre Cianfarani - * Copyright (C) 2010-2015 Juanjo Menent - * Copyright (C) 2012-2023 Christophe Battarel - * Copyright (C) 2012-2013 Cédric Salvador - * Copyright (C) 2012-2014 Raphaël Doursenaud - * Copyright (C) 2013 Jean-Francois FERRY - * Copyright (C) 2013-2014 Florian Henry - * Copyright (C) 2013 Cédric Salvador - * Copyright (C) 2014-2024 Ferran Marcet - * Copyright (C) 2015-2016 Marcos García - * Copyright (C) 2018-2025 Frédéric France - * Copyright (C) 2022 Gauthier VERDOL - * Copyright (C) 2023 Nick Fragoulis - * Copyright (C) 2024-2025 MDW - * Copyright (C) 2024 Alexandre Spangaro +/* Copyright (C) 2002-2006 Rodolphe Quiedeville + * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2004-2020 Laurent Destailleur + * Copyright (C) 2005 Marc Barilley / Ocebo + * Copyright (C) 2005-2015 Regis Houssin + * Copyright (C) 2006 Andre Cianfarani + * Copyright (C) 2010-2015 Juanjo Menent + * Copyright (C) 2012-2023 Christophe Battarel + * Copyright (C) 2012-2013 Cédric Salvador + * Copyright (C) 2012-2014 Raphaël Doursenaud + * Copyright (C) 2013 Jean-Francois FERRY + * Copyright (C) 2013-2014 Florian Henry + * Copyright (C) 2014-2024 Ferran Marcet + * Copyright (C) 2015-2016 Marcos García + * Copyright (C) 2018-2025 Frédéric France + * Copyright (C) 2022 Gauthier VERDOL + * Copyright (C) 2022-2023 Solution Libre SAS + * Copyright (C) 2023 Nick Fragoulis + * Copyright (C) 2024-2025 MDW + * Copyright (C) 2024-2025 Alexandre Spangaro * * 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 @@ -42,6 +42,7 @@ // Libraries require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; @@ -600,6 +601,8 @@ if (empty($reshook)) { } } elseif ($action == 'set_incoterms' && isModEnabled('incoterm') && $usercancreate) { // Set incoterm $result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOST('location_incoterms')); + } elseif ($action == 'settags' && isModEnabled('categorie')) { // Set tags + $result = $object->setCategories(GETPOST('categories', 'array')); } elseif ($action == 'setbankaccount' && $usercancreate) { // bank account $result = $object->setBankAccount(GETPOSTINT('fk_account')); } elseif ($action == 'setremisepercent' && $usercancreate) { @@ -2109,6 +2112,13 @@ if (empty($reshook)) { // End of object creation, we show it if ($id > 0 && !$error) { + if (isModEnabled('categorie')) { + $categories = GETPOST('categories', 'array'); + if (method_exists($object, 'setCategories')) { + $object->setCategories($categories); + } + } + $db->commit(); // Define output language @@ -4096,6 +4106,16 @@ if ($action == 'create') { print ''; } + // Category + if (isModEnabled('categorie')) { + // Categories + print ''.$langs->trans("Categories").''; + $cate_arbo = $form->select_all_categories(Categorie::TYPE_INVOICE, '', 'parent', 64, 0, 1); + $arrayselected = GETPOST('categories', 'array'); + print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print ""; + } + // Other attributes $parameters = array('objectsrc' => !empty($objectsrc) ? $objectsrc : 0, 'colspan' => ' colspan="2"', 'cols' => '2', 'socid' => $socid); $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -4975,7 +4995,39 @@ if ($action == 'create') { print ''; } - + // Categories + if (isModEnabled('categorie')) { + print ''; + print '
'; + print $langs->trans("Categories"); + print ''; + if ($usercancreate) { + print ''.img_edit().''; + } else { + print ' '; + } + print '
'; + print ''; + print ''; + $cate_arbo = $form->select_all_categories(Categorie::TYPE_INVOICE, '', 'parent', 64, 0, 1); + if ($action == 'edittags') { + print '
'; + print ''; + print ''; + $c = new Categorie($db); + $cats = $c->containing($object->id, Categorie::TYPE_INVOICE); + $arrayselected=[]; + foreach ($cats as $cat) { + $arrayselected[] = $cat->id; + } + print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, $arrayselected, 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, '0'); + print ''; + print '
'; + } else { + print $form->showCategories($object->id, Categorie::TYPE_INVOICE, 1); + } + print ""; + } $displayWarranty = false; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index d11023de8a8..04492e92921 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -15,9 +15,10 @@ * Copyright (C) 2013 Cedric Gross * Copyright (C) 2013 Florian Henry * Copyright (C) 2016-2025 Ferran Marcet - * Copyright (C) 2018-2024 Alexandre Spangaro + * Copyright (C) 2018-2025 Alexandre Spangaro * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2022 Sylvain Legrand + * Copyright (C) 2022-2023 Solution Libre SAS * Copyright (C) 2023 Gauthier VERDOL * Copyright (C) 2023 Nick Fragoulis * Copyright (C) 2024-2025 MDW @@ -2839,6 +2840,18 @@ class Facture extends CommonInvoice // End call triggers } + // Remove linked categories. + if (!$error) { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_invoice"; + $sql .= " WHERE fk_invoice = ".((int) $this->id); + + $result = $this->db->query($sql); + if (!$result) { + $error++; + $this->errors[] = $this->db->lasterror(); + } + } + // Removed extrafields if (!$error) { $result = $this->deleteExtraFields(); @@ -4704,6 +4717,22 @@ class Facture extends CommonInvoice } */ + /** + * Sets object to supplied categories. + * + * Deletes object from existing categories not supplied. + * Adds it to non existing supplied categories. + * Existing categories are left untouch. + * + * @param int[]|int $categories Category or categories IDs + * @return void + */ + public function setCategories($categories) + { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + return parent::setCategoriesCommon($categories, Categorie::TYPE_INVOICE); + } + /** * Return next reference of customer invoice not already used (or last reference) * according to numbering module defined into constant FACTURE_ADDON diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 280f7b0abd0..df13db0447c 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -7,8 +7,9 @@ * Copyright (C) 2018 Ferran Marcet * Copyright (C) 2018-2024 Frédéric France * Copyright (C) 2021 Gauthier VERDOL + * Copyright (C) 2022-2023 Solution Libre SAS * Copyright (C) 2024-2025 MDW - * Copyright (C) 2024 Alexandre Spangaro + * Copyright (C) 2024-2025 Alexandre Spangaro * * 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 @@ -1514,6 +1515,12 @@ function get_left_menu_billing($mainmenu, &$newmenu, $usemenuhider = 1, $leftmen } $newmenu->add("/compta/facture/stats/index.php?leftmenu=customers_bills_stats", $langs->trans("Statistics"), 1, $user->hasRight('facture', 'lire'), '', $mainmenu, 'customers_bills_stats'); + + // Categories + if (isModEnabled('categorie')) { + $langs->load("categories"); + $newmenu->add("/categories/index.php?leftmenu=cat&type=14", $langs->trans("Categories"), 1, $user->rights->categorie->lire, '', $mainmenu, 'cat'); + } } // Suppliers invoices diff --git a/htdocs/core/modules/modCategorie.class.php b/htdocs/core/modules/modCategorie.class.php index 767e37c6b26..fc178d621d9 100644 --- a/htdocs/core/modules/modCategorie.class.php +++ b/htdocs/core/modules/modCategorie.class.php @@ -1,11 +1,11 @@ - * Copyright (C) 2005-2014 Laurent Destailleur - * Copyright (C) 2012-2016 Juanjo Menent - * Copyright (C) 2020 Stéphane Lesage - * Copyright (C) 2024 MDW - * Copyright (C) 2025 Frédéric France - * Copyright (C) 2022-2023 Solution Libre SAS +/* Copyright (C) 2005 Matthieu Valleton + * Copyright (C) 2005-2014 Laurent Destailleur + * Copyright (C) 2012-2016 Juanjo Menent + * Copyright (C) 2020 Stéphane Lesage + * Copyright (C) 2022-2023 Solution Libre SAS + * Copyright (C) 2024 MDW + * Copyright (C) 2025 Frédéric France * * 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 @@ -170,6 +170,9 @@ class modCategorie extends DolibarrModules if (isModEnabled('order')) { $typeexample .= ($typeexample ? " / " : "")."16=Order"; } + if (isModEnabled('facture')) { + $typeexample .= ($typeexample ? " / " : "")."17=Invoice"; + } // Definition of vars $this->export_fields_array[$r] = array('cat.rowid' => "CategId", 'cat.label' => "Label", 'cat.type' => "Type", 'cat.description' => "Description", 'cat.fk_parent' => "ParentCategoryID", 'pcat.label' => "ParentCategoryLabel", 'cat.color' => "Color", 'cat.date_creation' => "DateCreation", 'cat.tms' => "DateLastModification"); @@ -492,6 +495,24 @@ class modCategorie extends DolibarrModules ); } + // 17 Invoice + if (isModEnabled("facture")) { + ++$r; + $this->exportTagLinks( + $r, + 17, + 'Facture', + 'isModEnabled("facture")', + ['facture', 'facture', 'export'], + [ + 'rowid' => [ + 'name' => 'InvoiceID', + 'type' => 'Numeric' + ] + ] + ); + } + // Imports //-------- @@ -509,7 +530,7 @@ class modCategorie extends DolibarrModules 'ca.label' => "Label*", 'ca.type' => "Type*", 'ca.description' => "Description", 'ca.fk_parent' => 'ParentCategory' ); - $this->import_regex_array[$r] = array('ca.type' => '^(0|1|2|3|4|5|6|7|8|9|10|11|16)$'); + $this->import_regex_array[$r] = array('ca.type' => '^(0|1|2|3|4|5|6|7|8|9|10|11|16|17)$'); $this->import_convertvalue_array[$r] = array( 'ca.fk_parent' => array( 'rule' => 'fetchidfromcodeandlabel', @@ -691,6 +712,18 @@ class modCategorie extends DolibarrModules 'Commande' ); } + + // 17 Invoice + if (isModEnabled("facture")) { + ++$r; + $this->importTagLinks( + $r, + 'facture', + '/compta/facture/class/facture.class.php', + 'Facture', + 'Facture' + ); + } } /** diff --git a/htdocs/langs/en_US/categories.lang b/htdocs/langs/en_US/categories.lang index bb369a1dea8..08521ac082d 100644 --- a/htdocs/langs/en_US/categories.lang +++ b/htdocs/langs/en_US/categories.lang @@ -79,6 +79,7 @@ CatContactList=List of contacts tags/categories CatProjectsList=List of projects tags/categories CatUsersList=List of users tags/categories CatOrdersLinks=Links between orders and tags/categories +CatInvoicesLinks=Links between invoices and tags/categories CatSupLinks=Links between vendors and tags/categories CatCusLinks=Links between customers/prospects and tags/categories CatContactsLinks=Links between contacts/addresses and tags/categories From 5a5eb35c0c8bcb90e1db25cf1a5c396a226e3cd3 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 27 Feb 2025 09:15:31 +0100 Subject: [PATCH 02/71] Translate --- htdocs/langs/en_US/categories.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/categories.lang b/htdocs/langs/en_US/categories.lang index 08521ac082d..d5a1d27cf16 100644 --- a/htdocs/langs/en_US/categories.lang +++ b/htdocs/langs/en_US/categories.lang @@ -97,6 +97,7 @@ AddCustomerIntoCategory=Assign the category to the customer AddSupplierIntoCategory=Assign the category to the supplier AddFichinterIntoCategory=Assign the category to the intervention AddOrderIntoCategory=Assign the category to the order +AddInvoiceIntoCategory=Assign the category to the invoice AssignCategoryTo=Assign the category to ShowCategory=Show tag/category ByDefaultInList=By default in list From 98461cc9576c5ebabce671d0c26d6081426d7e85 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 27 Feb 2025 09:34:59 +0100 Subject: [PATCH 03/71] CI --- htdocs/categories/viewcat.php | 5 +++-- htdocs/compta/facture/card.php | 8 ++++---- htdocs/core/menus/standard/eldy.lib.php | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 5fd990f462e..69853036b61 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -1519,7 +1519,7 @@ if ($type == Categorie::TYPE_INVOICE) { dol_print_error($db, $object->error, $object->errors); } else { // Form to add record into a category - $showclassifyform = 1; + $showclassifyform = $user->hasRight('facture', 'write'); if ($showclassifyform) { print '
'; print '
'; @@ -1548,6 +1548,7 @@ if ($type == Categorie::TYPE_INVOICE) { print '
'; $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($objects); $nbtotalofrecords = ''; $newcardbutton = ''; + // @phan-suppress-next-line PhanPluginSuspiciousParamOrder print_barre_liste($langs->trans("BillsCustomers"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'bill', 0, $newcardbutton, '', $limit); print "\n"; @@ -1571,7 +1572,7 @@ if ($type == Categorie::TYPE_INVOICE) { if ($permission) { print ""; print $langs->trans("DeleteFromCat"); - print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); + print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', 0, 0, 0, '', 'paddingleft'); print ""; } print "\n"; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 6387df729de..f86cdae5981 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -601,7 +601,7 @@ if (empty($reshook)) { } } elseif ($action == 'set_incoterms' && isModEnabled('incoterm') && $usercancreate) { // Set incoterm $result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOST('location_incoterms')); - } elseif ($action == 'settags' && isModEnabled('categorie')) { // Set tags + } elseif ($action == 'settags' && isModEnabled('category')) { // Set tags $result = $object->setCategories(GETPOST('categories', 'array')); } elseif ($action == 'setbankaccount' && $usercancreate) { // bank account $result = $object->setBankAccount(GETPOSTINT('fk_account')); @@ -2112,7 +2112,7 @@ if (empty($reshook)) { // End of object creation, we show it if ($id > 0 && !$error) { - if (isModEnabled('categorie')) { + if (isModEnabled('category')) { $categories = GETPOST('categories', 'array'); if (method_exists($object, 'setCategories')) { $object->setCategories($categories); @@ -4107,7 +4107,7 @@ if ($action == 'create') { } // Category - if (isModEnabled('categorie')) { + if (isModEnabled('category')) { // Categories print ''; @@ -1459,9 +1459,9 @@ if ($action == 'create') { print '
'.$langs->trans("Categories").''; $cate_arbo = $form->select_all_categories(Categorie::TYPE_INVOICE, '', 'parent', 64, 0, 1); @@ -4996,7 +4996,7 @@ if ($action == 'create') { } // Categories - if (isModEnabled('categorie')) { + if (isModEnabled('category')) { print '
'; print '"; } diff --git a/htdocs/core/modules/modCategorie.class.php b/htdocs/core/modules/modCategorie.class.php index 4584c7d8bba..6a431545860 100644 --- a/htdocs/core/modules/modCategorie.class.php +++ b/htdocs/core/modules/modCategorie.class.php @@ -714,11 +714,11 @@ class modCategorie extends DolibarrModules } // 17 Invoice - if (isModEnabled("facture")) { + if (isModEnabled("invoice")) { ++$r; $this->importTagLinks( $r, - 'facture', + 'invoice', '/compta/facture/class/facture.class.php', 'Facture', 'Facture' From 9bc2d08ab101c6ff535306d0e5a59e31083e6be9 Mon Sep 17 00:00:00 2001 From: omogenot Date: Thu, 27 Feb 2025 17:21:31 +0100 Subject: [PATCH 07/71] Update export_excel2007.modules.php Fix Excel Export for zero values --- htdocs/core/modules/export/export_excel2007.modules.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/export/export_excel2007.modules.php b/htdocs/core/modules/export/export_excel2007.modules.php index bcfc547fd4f..c56d3f56d1a 100644 --- a/htdocs/core/modules/export/export_excel2007.modules.php +++ b/htdocs/core/modules/export/export_excel2007.modules.php @@ -336,9 +336,9 @@ class ExportExcel2007 extends ModeleExports continue; } - $newvalue = !empty($objp->$alias) ? $objp->$alias : ''; + // $newvalue = !empty($objp->$alias) ? $objp->$alias : ''; - $newvalue = $this->excel_clean($newvalue); + $newvalue = $this->excel_clean($objp->$alias); $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { From 87b9305f1a6fb63e401e1d3e846dfc9720a56715 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sun, 2 Mar 2025 22:10:46 +0100 Subject: [PATCH 08/71] Fix feedback --- htdocs/categories/viewcat.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 69853036b61..aeb42e48008 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -9,7 +9,7 @@ * Copyright (C) 2022-2023 Solution Libre SAS * Copyright (C) 2024 MDW * Copyright (C) 2024 Frédéric France - * Copyright (C) 2024 Alexandre Spangaro + * Copyright (C) 2024-2025 Alexandre Spangaro * Copyright (C) 2023-2024 Charlene Benke * * This program is free software; you can redistribute it and/or modify @@ -256,7 +256,7 @@ if ($elemid && $action == 'addintocategory') { // Test on permission not require } elseif ($type == Categorie::TYPE_INVOICE && $user->hasRight('facture', 'creer')) { require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $newobject = new Facture($db); - $elementtype = 'order'; + $elementtype = 'invoice'; } else { dol_print_error(null, "Not supported value of type = ".$type); } From 7e142374d29dd4a93d2001a885291732b05f3d0a Mon Sep 17 00:00:00 2001 From: iouston <4319513+iouston@users.noreply.github.com> Date: Mon, 3 Mar 2025 17:45:53 +0100 Subject: [PATCH 09/71] add status class --- htdocs/compta/facture/list.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 0d0cf80fc5d..66cd5e986a3 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -2149,7 +2149,7 @@ if ($num > 0) { if ($mode == 'kanban') { if ($i == 0) { - print 'db->prefix().$this->table_element.$mode; - $sql .= " WHERE piece_num = ".(int) $piecenum; - $sql .= " AND date_validated IS NULL"; // For security, exclusion of validated entries at the time of deletion - $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features - $sql .= $sql_filter; - - $resql = $this->db->query($sql); - - if (!$resql) { - $this->errors[] = "Error ".$this->db->lasterror(); - foreach ($this->errors as $errmsg) { - dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR); - $this->error .= ($this->error ? ', '.$errmsg : $errmsg); + // Call triggers + if (! $error && ! $notrigger) { + $result = $this->call_trigger('BOOKKEEPING_DELETE', $user); + if ($result < 0) { + $error++; } - $this->db->rollback(); - return -1; - } else { - $nbprocessed = $this->db->affected_rows($resql); } - $this->db->commit(); + if (!$error) { + // first check if line not yet in bookkeeping + $sql = "DELETE"; + $sql .= " FROM ".$this->db->prefix().$this->table_element.$mode; + $sql .= " WHERE piece_num = ".(int) $piecenum; + $sql .= " AND date_validated IS NULL"; // For security, exclusion of validated entries at the time of deletion + $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features + $sql .= $sql_filter; + + $resql = $this->db->query($sql); + + if (!$resql) { + $this->errors[] = "Error ".$this->db->lasterror(); + foreach ($this->errors as $errmsg) { + dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR); + $this->error .= ($this->error ? ', '.$errmsg : $errmsg); + } + $this->db->rollback(); + return -1; + } else { + $nbprocessed = $this->db->affected_rows($resql); + } + } - return $nbprocessed; + // Commit or rollback + if ($error) { + $this->db->rollback(); + return -1 * $error; + } else { + $this->db->commit(); + return $nbprocessed; + } } /** From 09d0f83865adbfd4fbac6d995303c3a0686de96e Mon Sep 17 00:00:00 2001 From: Quentin-Seekness <72733832+Quentin-Seekness@users.noreply.github.com> Date: Tue, 4 Mar 2025 10:49:36 +0100 Subject: [PATCH 11/71] Pre-commit fix --- htdocs/accountancy/class/bookkeeping.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index eeb427a7221..d32e8cb6dc4 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1711,7 +1711,7 @@ class BookKeeping extends CommonObject * * @param int $piecenum Piecenum to delete * @param string $mode Mode ('' or '_tmp') - * @param int $notrigger 0=launch triggers after, 1=disable triggers + * @param int $notrigger 0=launch triggers after, 1=disable triggers * @return int Nb of record deleted */ public function deleteMvtNum($piecenum, $mode = '', $notrigger = 0) @@ -1744,9 +1744,9 @@ class BookKeeping extends CommonObject $sql .= " AND date_validated IS NULL"; // For security, exclusion of validated entries at the time of deletion $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features $sql .= $sql_filter; - + $resql = $this->db->query($sql); - + if (!$resql) { $this->errors[] = "Error ".$this->db->lasterror(); foreach ($this->errors as $errmsg) { From 89ff86504b78526ecf55e1451efa6d5e5df88e59 Mon Sep 17 00:00:00 2001 From: Quentin-Seekness <72733832+Quentin-Seekness@users.noreply.github.com> Date: Tue, 4 Mar 2025 10:53:29 +0100 Subject: [PATCH 12/71] Fix precommit --- htdocs/accountancy/class/bookkeeping.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index d32e8cb6dc4..1befc5c4332 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1711,7 +1711,7 @@ class BookKeeping extends CommonObject * * @param int $piecenum Piecenum to delete * @param string $mode Mode ('' or '_tmp') - * @param int $notrigger 0=launch triggers after, 1=disable triggers + * @param int $notrigger 0=launch triggers after, 1=disable triggers * @return int Nb of record deleted */ public function deleteMvtNum($piecenum, $mode = '', $notrigger = 0) From af93e6d39fa8ffca3578900e86bf7f33deb9bf0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Tue, 4 Mar 2025 16:20:30 +0100 Subject: [PATCH 13/71] fix ajax tooltip --- htdocs/comm/action/class/actioncomm.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index bb38c246127..10604bc532b 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -1639,10 +1639,10 @@ class ActionComm extends CommonObject $datas['space'] = '
'; // $datas['email'] = '
'.img_picto('', 'email').' '.$langs->trans("Email").''; $datas['mailtopic'] = '
'.$langs->trans('MailTopic').': '.dol_escape_htmltag($this->email_subject); - $datas['mailfrom'] = '
'.$langs->trans('MailFrom').': '.str_replace(array('<', '>'), array('&lt', '&gt'), $this->email_from); - $datas['mailto'] = '
'.$langs->trans('MailTo').': '.str_replace(array('<', '>'), array('&lt', '&gt'), $this->email_to); + $datas['mailfrom'] = '
'.$langs->trans('MailFrom').': '.dol_htmlentities($this->email_from); + $datas['mailto'] = '
'.$langs->trans('MailTo').': '.dol_htmlentities($this->email_to); if (!empty($this->email_tocc)) { - $datas['mailcc'] = '
'.$langs->trans('MailCC').': '.str_replace(array('<', '>'), array('&lt', '&gt'), $this->email_tocc); + $datas['mailcc'] = '
'.$langs->trans('MailCC').': '.dol_htmlentities($this->email_tocc); } /* Disabled because bcc must remain by definition not visible if (!empty($this->email_tobcc)) { From 86cf64936b14728f82a97a16aa104e9e2e4350df Mon Sep 17 00:00:00 2001 From: Mohamed DAOUD Date: Tue, 4 Mar 2025 16:48:26 +0100 Subject: [PATCH 14/71] Fix external modules page --- htdocs/admin/remotestore/class/externalModules.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/remotestore/class/externalModules.class.php b/htdocs/admin/remotestore/class/externalModules.class.php index 4ba228b24a4..42d73650ed0 100644 --- a/htdocs/admin/remotestore/class/externalModules.class.php +++ b/htdocs/admin/remotestore/class/externalModules.class.php @@ -187,11 +187,13 @@ class ExternalModules $url = $this->dolistore_api_url . (preg_match('/\/$/', $this->dolistore_api_url) ? '' : '/') . $resource; + $options['apikey'] = $this->dolistore_api_key; + if ($options) { $url .= '?' . http_build_query($options); } - $response = getURLContent($url, 'POST', '', 1, $httpheader); + $response = getURLContent($url, 'GET', '', 1, $httpheader); $body = $response['content']; $body = json_decode($body, true); From 97aabd486b413c2e7a4714f496eccd4d90d1a4b4 Mon Sep 17 00:00:00 2001 From: Mohamed DAOUD Date: Tue, 4 Mar 2025 17:01:31 +0100 Subject: [PATCH 15/71] fix missing translation --- htdocs/langs/en_US/admin.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index bb1141b7719..439d6cd0707 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2635,3 +2635,4 @@ SelectFeatureToTest=Select the feature to test AIModelForFeature=AI model for features (AI service %s) communityRepo=Community repository online=Online +NotConnected=Not connected From 4c749fe5cd603c0d94bfb51bf0b4fad53bd6a3c1 Mon Sep 17 00:00:00 2001 From: Mohamed DAOUD Date: Tue, 4 Mar 2025 17:38:07 +0100 Subject: [PATCH 16/71] Fix Phan --- htdocs/admin/remotestore/class/externalModules.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/remotestore/class/externalModules.class.php b/htdocs/admin/remotestore/class/externalModules.class.php index 42d73650ed0..d35ff570921 100644 --- a/htdocs/admin/remotestore/class/externalModules.class.php +++ b/htdocs/admin/remotestore/class/externalModules.class.php @@ -166,7 +166,7 @@ class ExternalModules * * @param string $resource Resource name * @param array|false $options Options for the request - * @return array{status_code:int,response:null|string|array,header:string} + * @return array{status_code:int,response:null|string|array} */ public function callApi($resource, $options = false) { @@ -645,10 +645,11 @@ class ExternalModules * * @param string $file_source_url URL of the remote source * @param int $cache_time Cache time - * @return string Uri of the cache file + * @return bool|string File content */ public function getRemoteYamlFile($file_source_url, $cache_time) { + $yaml = ''; $cache_file = $this->cache_file; $cache_folder = dirname($cache_file); From e6784e1dd82926e61e285a2aed1c02d2d54842ec Mon Sep 17 00:00:00 2001 From: Mohamed DAOUD Date: Tue, 4 Mar 2025 18:09:40 +0100 Subject: [PATCH 17/71] fix CI --- htdocs/admin/remotestore/class/externalModules.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/remotestore/class/externalModules.class.php b/htdocs/admin/remotestore/class/externalModules.class.php index d35ff570921..123f4d79677 100644 --- a/htdocs/admin/remotestore/class/externalModules.class.php +++ b/htdocs/admin/remotestore/class/externalModules.class.php @@ -605,7 +605,7 @@ class ExternalModules /** * Check the status code of the request * - * @param array{status_code:int,response:null|string|array{errors:array{code:int,message:string}[]},header:string} $request Response elements of CURL request + * @param array{status_code:int,response:null|string|array{errors:array{code:int,message:string}[]}} $request Response elements of CURL request * * @return string|null */ From 862fffec248c887c2b0a634321754ce26c88c0f8 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Tue, 4 Mar 2025 23:36:13 +0100 Subject: [PATCH 18/71] Ignore warning --- htdocs/societe/list.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index cce3e430b6c..3a30b52a6e5 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -338,6 +338,7 @@ $arrayfields['sales.representative'] = array('label' => $langs->trans("SalesRepr include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; $object->fields = dol_sort_array($object->fields, 'position'); +// @phpstan-ignore-next-line $arrayfields = dol_sort_array($arrayfields, 'position'); '@phan-var-force array,position?:int,help?:string}> $arrayfields'; // dol_sort_array looses type for Phan From 82491e85689d57312824801c2da7bcac04214036 Mon Sep 17 00:00:00 2001 From: Jyhere Date: Wed, 5 Mar 2025 09:30:15 +0100 Subject: [PATCH 19/71] FIX: Warning when getNomUrl is called before top_httphead If Societe::getNomUrl() is called before top_httphead, this triggers a Cannot modify header warning --- htdocs/societe/class/societe.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 1828e733dba..804505918b1 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3095,8 +3095,6 @@ class Societe extends CommonObject } else { $label = implode($this->getTooltipContentArray($params)); } - print "\n"; - //var_dump($label);exit; $linkstart = ''; $linkend = ''; From 73b0a6bda17d230b882d45c6fa7962d9fcba0cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 5 Mar 2025 10:05:05 +0100 Subject: [PATCH 20/71] enhance formsetup for products --- htdocs/core/class/html.formsetup.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 31370af5c2b..b1a7491d11e 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -1274,7 +1274,7 @@ class FormSetupItem $product = new Product($this->db); $resprod = $product->fetch((int) $this->fieldValue); if ($resprod > 0) { - $out .= $product->ref; + $out .= $product->getNomUrl(1, '', 0, -1, 0, '', 1); } elseif ($resprod < 0) { $this->setErrors($product->errors); } From 3ba697892f95f03801dd8328270b799071389367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 5 Mar 2025 10:20:03 +0100 Subject: [PATCH 21/71] fix CI branch 21.0 --- htdocs/societe/list.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 3a30b52a6e5..08a4113c04c 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -11,7 +11,7 @@ * Copyright (C) 2017 Juanjo Menent * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2020 Open-Dsi - * Copyright (C) 2021-2024 Frédéric France + * Copyright (C) 2021-2025 Frédéric France * Copyright (C) 2022 Anthony Berton * Copyright (C) 2023 William Mead * Copyright (C) 2024 MDW @@ -337,8 +337,8 @@ $arrayfields['sales.representative'] = array('label' => $langs->trans("SalesRepr // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; -$object->fields = dol_sort_array($object->fields, 'position'); // @phpstan-ignore-next-line +$object->fields = dol_sort_array($object->fields, 'position'); $arrayfields = dol_sort_array($arrayfields, 'position'); '@phan-var-force array,position?:int,help?:string}> $arrayfields'; // dol_sort_array looses type for Phan From 6fe3dfb0313b5009db2891a64a52921f1166906b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 5 Mar 2025 10:29:47 +0100 Subject: [PATCH 22/71] fix CI branch 21.0 --- htdocs/website/samples/wrapper.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/website/samples/wrapper.php b/htdocs/website/samples/wrapper.php index dd669a379a7..8c53d423325 100644 --- a/htdocs/website/samples/wrapper.php +++ b/htdocs/website/samples/wrapper.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2024-2025 Frédéric France * * 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 @@ -127,8 +127,10 @@ if (GETPOSTISSET('type')) { // Security: Delete string ../ into $original_file $original_file = str_replace("../", "/", $original_file); + // Cache or not $cachestring = GETPOST("cache", 'aZ09'); // May be 1, or an int (delay in second of the cache if < 999999, or a timestamp), or a hash +$cachedelay = 0; if ($cachestring || image_format_supported($original_file) >= 0) { // Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access. $cachedelay = GETPOSTINT('cachedelay') ? GETPOSTINT('cachedelay') : ((is_numeric($cachestring) && (int) $cachestring > 1 && (int) $cachestring < 999999) ? $cachestring : '3600'); From 26f966758fd6b2dfa7034afad0156623c3c9052b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 5 Mar 2025 10:36:50 +0100 Subject: [PATCH 23/71] fix CI branch 21.0 --- htdocs/societe/class/societe.class.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 97a7adebb1b..21ef0dbf0b6 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -15,7 +15,7 @@ * Copyright (C) 2017 Rui Strecht * Copyright (C) 2018 Philippe Grand * Copyright (C) 2019-2020 Josep Lluís Amador - * Copyright (C) 2019-2024 Frédéric France + * Copyright (C) 2019-2025 Frédéric France * Copyright (C) 2020 Open-Dsi * Copyright (C) 2022 ButterflyOfFire * Copyright (C) 2023-2024 Alexandre Janniaux @@ -3075,8 +3075,7 @@ class Societe extends CommonObject } else { $label = implode($this->getTooltipContentArray($params)); } - print "\n"; - //var_dump($label);exit; + $linkstart = ''; $linkend = ''; From 6ccca59ad5d5e4d78d1ff2106607d1d9ebf3d56a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 5 Mar 2025 10:48:52 +0100 Subject: [PATCH 24/71] Update list.php --- htdocs/societe/list.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index ac259eb9eff..31a51f8621b 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -344,6 +344,7 @@ $arrayfields['sales.representative'] = array('label' => $langs->trans("SalesRepr // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; +// @phpstan-ignore-next-line $object->fields = dol_sort_array($object->fields, 'position'); $arrayfields = dol_sort_array($arrayfields, 'position'); From acf6b628227b55dc385f4a2190f0aa5175b26b5e Mon Sep 17 00:00:00 2001 From: MDW Date: Mon, 3 Mar 2025 23:12:31 +0100 Subject: [PATCH 25/71] Fix PhanTypeMismatchArgument in commonobject, commande/card, --- htdocs/commande/card.php | 100 +++++++++--------- htdocs/commande/class/commande.class.php | 8 +- htdocs/compta/facture/class/facture.class.php | 6 +- htdocs/core/class/commonobject.class.php | 57 ++++++---- htdocs/core/class/validate.class.php | 14 +-- .../class/supplier_proposal.class.php | 2 +- 6 files changed, 102 insertions(+), 85 deletions(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 913dc87d333..0bcd0040c6f 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -15,7 +15,7 @@ * Copyright (C) 2018-2025 Frédéric France * Copyright (C) 2022 Gauthier VERDOL * Copyright (C) 2023-2024 Benjamin Falière - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * Copyright (C) 2025 Lenin Rivas * * This program is free software; you can redistribute it and/or modify @@ -608,7 +608,7 @@ if (empty($reshook)) { } elseif ($action == 'setabsolutediscount' && $usercancreate) { if (GETPOST('remise_id')) { if ($object->id > 0) { - $object->insert_discount(GETPOST('remise_id')); + $object->insert_discount(GETPOSTINT('remise_id')); } else { dol_print_error($db, $object->error); } @@ -640,12 +640,12 @@ if (empty($reshook)) { // Multicurrency rate $result = $object->setMulticurrencyRate(GETPOSTFLOAT('multicurrency_tx'), GETPOSTINT('calculation_mode')); } elseif ($action == 'setavailability' && $usercancreate) { - $result = $object->availability(GETPOST('availability_id')); + $result = $object->availability(GETPOSTINT('availability_id')); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); } } elseif ($action == 'setdemandreason' && $usercancreate) { - $result = $object->demand_reason(GETPOST('demand_reason_id')); + $result = $object->demand_reason(GETPOSTINT('demand_reason_id')); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); } @@ -719,7 +719,7 @@ if (empty($reshook)) { $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc); $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc); foreach ($object->lines as $line) { - $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); + $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, (float) $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); } } elseif ($action == 'addline' && GETPOST('submitforalllines', 'alpha') && GETPOST('remiseforalllines', 'alpha') !== '' && $usercancreate) { // Define remise_percent @@ -730,7 +730,7 @@ if (empty($reshook)) { if (!empty($line->vat_src_code)) { $tvatx .= ' ('.$line->vat_src_code.')'; } - $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $remise_percent, $tvatx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); + $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, (float) $remise_percent, $tvatx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->date_start, $line->date_end, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice); } } elseif ($action == 'addline' && !GETPOST('submitforalllines', 'alpha') && $usercancreate) { // Add a new line $langs->load('errors'); @@ -870,7 +870,7 @@ if (empty($reshook)) { $prodcustprice = new ProductCustomerPrice($db); - $filter = array('t.fk_product' => $prod->id, 't.fk_soc' => $object->thirdparty->id); + $filter = array('t.fk_product' => (string) $prod->id, 't.fk_soc' => (string) $object->thirdparty->id); // If a price per customer exist $pricebycustomerexist = false; @@ -939,7 +939,7 @@ if (empty($reshook)) { $prodcustprice = new ProductCustomerPrice($db); - $filter = array('t.fk_product' => $prod->id, 't.fk_soc' => $object->thirdparty->id); + $filter = array('t.fk_product' => (string) $prod->id, 't.fk_soc' => (string) $object->thirdparty->id); $result = $prodcustprice->fetchAll('', '', 0, 0, $filter); if ($result >= 0) { @@ -1136,7 +1136,7 @@ if (empty($reshook)) { $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty); // Margin - $fournprice = price2num(GETPOST('fournprice'.$predef) ? GETPOST('fournprice'.$predef) : ''); + $fournprice = price2num(GETPOST('fournprice'.$predef) ? GETPOSTINT('fournprice'.$predef) : ''); $buyingprice = price2num(GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''); // If buying_price is '0', we must keep this value // Prepare a price equivalent for minimum price check @@ -1182,7 +1182,7 @@ if (empty($reshook)) { if (!$error) { // Insert line - $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $info_bits, 0, $price_base_type, $pu_ttc, $date_start, $date_end, $type, min($rank, count($object->lines) + 1), 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, $fk_unit, '', 0, $pu_ht_devise); + $result = $object->addline($desc, $pu_ht, (float) $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $info_bits, 0, $price_base_type, $pu_ttc, $date_start, $date_end, $type, min($rank, count($object->lines) + 1), 0, GETPOSTINT('fk_parent_line'), $fournprice, (float) $buyingprice, $label, $array_options, $fk_unit, '', 0, (float) $pu_ht_devise); if ($result > 0) { $ret = $object->fetch($object->id); // Reload to get new records @@ -1395,7 +1395,7 @@ if (empty($reshook)) { $price_base_type = 'TTC'; } - $result = $object->updateline(GETPOSTINT('lineid'), $description, $pu, $qty, $remise_percent, $vat_rate, $localtax1_rate, $localtax2_rate, $price_base_type, $info_bits, $date_start, $date_end, $type, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $special_code, $array_options, GETPOST('units'), $pu_ht_devise); + $result = $object->updateline(GETPOSTINT('lineid'), $description, (float) $pu, (float) $qty, $remise_percent, (float) $vat_rate, $localtax1_rate, $localtax2_rate, $price_base_type, $info_bits, $date_start, $date_end, $type, GETPOSTINT('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $special_code, $array_options, GETPOSTINT('units'), (float) $pu_ht_devise); if ($result >= 0) { if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) { @@ -1625,7 +1625,7 @@ if (empty($reshook)) { } if ($action == 'update_extras' && $usercancreate) { - $object->oldcopy = dol_clone($object, 2); + $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty $attribute_name = GETPOST('attribute', 'restricthtml'); // Fill array 'array_options' with data from update form @@ -1743,7 +1743,7 @@ if (empty($reshook)) { if (!$error && getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB') && $usercancreate) { if ($action == 'addcontact' && $usercancreate) { if ($object->id > 0) { - $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid')); + $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid')); $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type')); $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09')); } @@ -2070,13 +2070,13 @@ if ($action == 'create' && $usercancreate) { // Terms of payment print '
'; // Payment mode print ''; // Bank Account @@ -2125,7 +2125,7 @@ if ($action == 'create' && $usercancreate) { // Incoterms if (isModEnabled('incoterm')) { print ''; - print ''; + print ''; print ''; print ''; print ''; } @@ -2194,7 +2194,7 @@ if ($action == 'create' && $usercancreate) { print ''; print ''; @@ -2205,7 +2205,7 @@ if ($action == 'create' && $usercancreate) { print ''; print ''; @@ -2603,8 +2603,8 @@ if ($action == 'create' && $usercancreate) { $morehtmlref = '
'; // Ref customer - $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string', '', 0, 1); - $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $usercancreate, 'string'.(isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1); + $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, (int) $usercancreate, 'string', '', 0, 1); + $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, (int) $usercancreate, 'string'.(isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1); // Thirdparty $morehtmlref .= '
'.$soc->getNomUrl(1, 'customer'); if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) { @@ -2619,7 +2619,7 @@ if ($action == 'create' && $usercancreate) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); @@ -2689,7 +2689,7 @@ if ($action == 'create' && $usercancreate) { // Date print '
'; @@ -2746,12 +2746,12 @@ if ($action == 'create' && $usercancreate) { if (isModEnabled('shipping')) { print ''; print ''; @@ -2764,7 +2764,7 @@ if ($action == 'create' && $usercancreate) { $formproduct = new FormProduct($db); print ''; // Terms of payment print ''; @@ -2804,12 +2804,12 @@ if ($action == 'create' && $usercancreate) { // Mode of payment print ''; @@ -2849,7 +2849,7 @@ if ($action == 'create' && $usercancreate) { if (isModEnabled('incoterm')) { print ''; print ''; print ''; @@ -2896,7 +2896,7 @@ if ($action == 'create' && $usercancreate) { print ''; $c = new Categorie($db); $cats = $c->containing($object->id, Categorie::TYPE_ORDER); - $arrayselected=[]; + $arrayselected = []; foreach ($cats as $cat) { $arrayselected[] = $cat->id; } @@ -3101,9 +3101,9 @@ if ($action == 'create' && $usercancreate) { // Valid if ($object->statut == Commande::STATUS_DRAFT && ($object->total_ttc >= 0 || getDolGlobalString('ORDER_ENABLE_NEGATIVE')) && $usercanvalidate) { if ($numlines > 0) { - print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"].'?action=validate&token='.newToken().'&id='.$object->id, $object->id, 1); + print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"].'?action=validate&token='.newToken().'&id='.$object->id, (string) $object->id, 1); } else { - print dolGetButtonAction($langs->trans("ErrorObjectMustHaveLinesToBeValidated", $object->ref), $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"].'?action=validate&token='.newToken().'&id='.$object->id, $object->id, 0); + print dolGetButtonAction($langs->trans("ErrorObjectMustHaveLinesToBeValidated", $object->ref), $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"].'?action=validate&token='.newToken().'&id='.$object->id, (string) $object->id, 0); } } // Edit @@ -3213,9 +3213,9 @@ if ($action == 'create' && $usercancreate) { ]; if ($numlines > 0) { - print dolGetButtonAction('', $langs->trans("Create"), 'default', $arrayforbutaction, $object->id, 1, $actionButtonsParameters); + print dolGetButtonAction('', $langs->trans("Create"), 'default', $arrayforbutaction, (string) $object->id, 1, $actionButtonsParameters); } else { - print dolGetButtonAction($langs->trans("ErrorObjectMustHaveLinesToBeValidated", $object->ref), $langs->trans("Create"), 'default', $arrayforbutaction, $object->id, 0, $actionButtonsParameters); + print dolGetButtonAction($langs->trans("ErrorObjectMustHaveLinesToBeValidated", $object->ref), $langs->trans("Create"), 'default', $arrayforbutaction, (string) $object->id, 0, $actionButtonsParameters); } // Set to shipped @@ -3273,7 +3273,7 @@ if ($action == 'create' && $usercancreate) { $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; $genallowed = $usercanread; $delallowed = $usercancreate; - print $formfile->showdocuments('commande', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang, '', $object); + print $formfile->showdocuments('commande', $objref, $filedir, $urlsource, $genallowed, (int) $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang, '', $object); // Show links to link elements diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 05c18321cf7..6d079d30445 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1535,19 +1535,19 @@ class Commande extends CommonOrder * @param float $pu_ttc Prix unitaire TTC * @param int|string $date_start Start date of the line - Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) * @param int|string $date_end End date of the line - Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) - * @param int $type Type of line (0=product, 1=service). Not used if fk_product is defined, the type of product is used. + * @param int<0,1> $type Type of line (0=product, 1=service). Not used if fk_product is defined, the type of product is used. * @param int $rang Position of line * @param int $special_code Special code (also used by externals modules!) * @param int $fk_parent_line Parent line * @param int $fk_fournprice Id supplier price - * @param int $pa_ht Buying price (without tax) + * @param float $pa_ht Buying price (without tax) * @param string $label Label - * @param array $array_options extrafields array. Example array('options_codeforfield1'=>'valueforfield1', 'options_codeforfield2'=>'valueforfield2', ...) + * @param array $array_options Extrafields array. Example array('options_codeforfield1'=>'valueforfield1', 'options_codeforfield2'=>'valueforfield2', ...) * @param ?int $fk_unit Code of the unit to use. Null to use the default one * @param string $origin Depend on global conf MAIN_CREATEFROM_KEEP_LINE_ORIGIN_INFORMATION can be 'orderdet', 'propaldet'..., else 'order','propal,'.... * @param int $origin_id Depend on global conf MAIN_CREATEFROM_KEEP_LINE_ORIGIN_INFORMATION can be Id of origin object (aka line id), else object id * @param float $pu_ht_devise Unit price in currency - * @param string $ref_ext line external reference + * @param string $ref_ext Line external reference * @param int $noupdateafterinsertline No update after insert of line * @return int >0 if OK, <0 if KO * diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 1ff63131a71..c1caa3d4ef3 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -2536,10 +2536,10 @@ class Facture extends CommonInvoice if (isset($this->retained_warranty)) { $this->retained_warranty = (float) $this->retained_warranty; } - if (!isset($this->user_creation_id) && isset($this->fk_user_author) ) { + if (!isset($this->user_creation_id) && isset($this->fk_user_author)) { $this->user_creation_id = $this->fk_user_author; } - if (!isset($this->user_validation_id) && isset($this->fk_user_valid) ) { + if (!isset($this->user_validation_id) && isset($this->fk_user_valid)) { $this->user_validation_id = $this->fk_user_valid; } @@ -4173,7 +4173,7 @@ class Facture extends CommonInvoice * @param string $label Label of the line (deprecated, do not use) * @param int $special_code Special code (also used by externals modules!) * @param array $array_options extrafields array - * @param int $situation_percent Situation advance percentage + * @param float $situation_percent Situation advance percentage * @param ?int $fk_unit Code of the unit to use. Null to use the default one * @param float $pu_ht_devise Unit price in currency * @param int<0,1> $notrigger disable line update trigger diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 354062cdd59..81f282a76d7 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2906,6 +2906,7 @@ abstract class CommonObject $line->product_type, $line->array_options, $line->ref_fourn, + (int) $line->fk_unit, $line->multicurrency_subprice ); break; @@ -3013,7 +3014,7 @@ abstract class CommonObject $sql = 'UPDATE '.$this->db->prefix().$this->table_element; $sql .= " SET ".$fieldname." = ".(($id > 0 || $id == '0') ? ((int) $id) : 'NULL'); if (in_array($this->table_element, array('propal', 'commande', 'societe'))) { - $sql .= " , deposit_percent = " . (empty($deposit_percent) ? 'NULL' : "'".$this->db->escape($deposit_percent)."'"); + $sql .= " , deposit_percent = " . (empty($deposit_percent) ? 'NULL' : "'".$this->db->escape((string) $deposit_percent)."'"); } $sql .= ' WHERE rowid='.((int) $this->id); @@ -5344,7 +5345,7 @@ abstract class CommonObject $reshook = $hookmanager->executeHooks('printObjectSubLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks } } - if (empty($reshook)) { + if (empty($reshook) && $buyer !== null) { $this->printObjectLine($action, $line, '', $num, $i, $dateSelector, $seller, $buyer, $selected, $extrafields, $defaulttpldir); } @@ -5394,6 +5395,7 @@ abstract class CommonObject // Define output language and label if (getDolGlobalInt('MAIN_MULTILANGS')) { + // @phan-suppress-next-line PhanUndeclaredProperty if (property_exists($this, 'socid') && !empty($this->socid) && !is_object($this->thirdparty)) { dol_print_error(null, 'Error: Method printObjectLine was called on an object and object->fetch_thirdparty was not done before'); return; @@ -5719,10 +5721,10 @@ abstract class CommonObject $sql .= ") VALUES ("; $sql .= ((int) $resource_id); $sql .= ", '".$this->db->escape($resource_type)."'"; - $sql .= ", '".$this->db->escape($this->id)."'"; + $sql .= ", '".$this->db->escape((string) $this->id)."'"; $sql .= ", '".$this->db->escape($this->element)."'"; - $sql .= ", '".$this->db->escape($busy)."'"; - $sql .= ", '".$this->db->escape($mandatory)."'"; + $sql .= ", '".$this->db->escape((string) $busy)."'"; + $sql .= ", '".$this->db->escape((string) $mandatory)."'"; $sql .= ")"; dol_syslog(get_class($this)."::add_element_resource", LOG_DEBUG); @@ -5959,10 +5961,23 @@ abstract class CommonObject $this->model_pdf = $saved_model; if ($obj instanceof ModelePDFMember) { - $resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, 'member', 1, 'tmp_cards'); + if ($this instanceof Adherent) { + $resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, 'member', 1, 'tmp_cards'); + } else { + $resultwritefile = -1; + dol_syslog("Error generating document - Provided ".get_class($this)." to ".get_class($obj)."::write_file()", LOG_ERR); + } + } elseif ($obj instanceof ModeleDon) { + // Only 3 arguments + if ($this instanceof Don) { + $resultwritefile = $obj->write_file($this, $outputlangs /*, $currency */); + } else { + $resultwritefile = -1; + dol_syslog("Error generating document - Provided ".get_class($this)." to Don::write_file()", LOG_ERR); + } } else { // TODO: Try to set type above again - '@phan-var-force ModeleBarCode|ModeleDon|ModeleExports|ModeleImports|ModelePDFAsset|ModelePDFContract|ModelePDFDeliveryOrder|ModelePDFEvaluation|ModelePDFFactures|ModelePDFFicheinter|ModelePDFMo|ModelePDFMovement|ModelePDFProduct|ModelePDFProjects|ModelePDFPropales|ModelePDFRecruitmentJobPosition|ModelePDFStock|ModelePDFStockTransfer|ModelePDFSupplierProposal|ModelePDFSuppliersInvoices|ModelePDFSuppliersOrders|ModelePDFSuppliersPayments|ModelePDFTask|ModelePDFTicket|ModelePDFUser|ModelePDFUserGroup|ModelePdfExpedition|ModelePdfReception|ModeleThirdPartyDoc $obj'; + '@phan-var-force ModeleBarCode|ModeleExports|ModeleImports|ModelePDFAsset|ModelePDFContract|ModelePDFDeliveryOrder|ModelePDFEvaluation|ModelePDFFactures|ModelePDFFicheinter|ModelePDFMo|ModelePDFMovement|ModelePDFProduct|ModelePDFProjects|ModelePDFPropales|ModelePDFRecruitmentJobPosition|ModelePDFStock|ModelePDFStockTransfer|ModelePDFSupplierProposal|ModelePDFSuppliersInvoices|ModelePDFSuppliersOrders|ModelePDFSuppliersPayments|ModelePDFTask|ModelePDFTicket|ModelePDFUser|ModelePDFUserGroup|ModelePdfExpedition|ModelePdfReception|ModeleThirdPartyDoc $obj'; $resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, $hidedetails, $hidedesc, $hideref, $moreparams); } // After call of write_file $obj->result['fullpath'] is set with generated file. It will be used to update the ECM database index. @@ -8304,7 +8319,8 @@ abstract class CommonObject //$objectfield = $valparent; $objectfield = $val; // Is better than using old method $valparent - $out = $form->selectForForms($param_list_array[0], $keyprefix.$key.$keysuffix, $value, $showempty, '', '', $morecss, $moreparam, 0, (empty($val['disabled']) ? 0 : 1), '', $objectfield); + // @phan-suppress-next-line PhanTypeMismatchArgumentNullable + $out = $form->selectForForms($param_list_array[0], $keyprefix.$key.$keysuffix, (int) $value, $showempty, '', '', $morecss, $moreparam, 0, (empty($val['disabled']) ? 0 : 1), '', $objectfield); if (!empty($param_list_array[2])) { // If the entry into $fields is set, we must add a create button if ((!GETPOSTISSET('backtopage') || strpos(GETPOST('backtopage'), $_SERVER['PHP_SELF']) === 0) // // To avoid to open several times the 'Plus' button (we accept only one level) @@ -8544,15 +8560,15 @@ abstract class CommonObject $value = yn($value ? 1 : 0); } } elseif ($type == 'mail' || $type == 'email') { - $value = dol_print_email($value, 0, 0, 0, 64, 1, 1); + $value = dol_print_email((string) $value, 0, 0, 0, 64, 1, 1); } elseif ($type == 'url') { - $value = dol_print_url($value, '_blank', 32, 1); + $value = dol_print_url((string) $value, '_blank', 32, 1); } elseif ($type == 'phone') { - $value = dol_print_phone($value, '', 0, 0, '', ' ', 'phone'); + $value = dol_print_phone((string) $value, '', 0, 0, '', ' ', 'phone'); } elseif ($type == 'ip') { - $value = dol_print_ip($value, 0); + $value = dol_print_ip((string) $value, 0); } elseif ($type == 'stars') { - $value = ''; + $value = ''; $value .= '
'; $i = 1; while ($i <= $size) { @@ -8653,7 +8669,7 @@ abstract class CommonObject } elseif ($selectkey == 'rowid') { $sql .= " WHERE ".$selectkey." = ".((int) $value); } else { - $sql .= " WHERE ".$selectkey." = '".$this->db->escape($value)."'"; + $sql .= " WHERE ".$selectkey." = '".$this->db->escape((string) $value)."'"; } //$sql.= ' AND entity = '.$conf->entity; @@ -8858,7 +8874,7 @@ abstract class CommonObject '@phan-var-force CommonObject $object'; if ($object->element === 'product') { // Special case for product because default valut of fetch are wrong '@phan-var-force Product $object'; - $result = $object->fetch($value, '', '', '', 0, 1, 1); + $result = $object->fetch((int) $value, '', '', '', 0, 1, 1); } else { $result = $object->fetch($value); } @@ -8911,7 +8927,7 @@ abstract class CommonObject if (!empty($value) && preg_match('/^text/', (string) $type) && !preg_match('/search_/', $keyprefix) && !empty($param['options'])) { $value = str_replace(',', "\n", $value); } - $value = dol_htmlentitiesbr($value); + $value = dol_htmlentitiesbr((string) $value); } //print $type.'-'.$size.'-'.$value; @@ -9009,7 +9025,7 @@ abstract class CommonObject // Convert var to be able to share same code than showOutputField of extrafields if (preg_match('/varchar\((\d+)\)/', $type, $reg)) { $type = 'varchar'; // convert varchar(xx) int varchar - $maxSize = $reg[1]; + $maxSize = (int) $reg[1]; } elseif (preg_match('/varchar/', $type)) { $type = 'varchar'; // convert varchar(xx) int varchar } @@ -9156,11 +9172,11 @@ abstract class CommonObject $InfoFieldList = explode(":", $param_list[0]); $classname = $InfoFieldList[0]; $classpath = $InfoFieldList[1]; - if (!$validate->isFetchable($fieldValue, $classname, $classpath)) { + if (!$validate->isFetchable((int) $fieldValue, $classname, $classpath)) { $lastIsFetchableError = $validate->error; // from V19 of Dolibarr, In some cases link use element instead of class, example project_task - if ($validate->isFetchableElement($fieldValue, $classname)) { + if ($validate->isFetchableElement((int) $fieldValue, $classname)) { return true; } @@ -9481,7 +9497,7 @@ abstract class CommonObject $out .= getPictoForType($extrafields->attributes[$this->table_element]['type'][$key], ($extrafields->attributes[$this->table_element]['type'][$key] == 'text' ? 'tdtop' : '')); } //$out .= ''; - $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', 0, $this, $this->table_element); + $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', '', $this, $this->table_element); break; case "edit": $listoftypestoshowpicto = explode(',', getDolGlobalString('MAIN_TYPES_TO_SHOW_PICTO', 'email,phone,ip,password')); @@ -10721,6 +10737,7 @@ abstract class CommonObject if (array_key_exists('user_modification_id', $fieldvalues) && !($fieldvalues['user_modification_id'] > 0)) { $fieldvalues['user_modification_id'] = $user->id; } + // @phan-suppress-next-line PhanUndeclaredProperty if (array_key_exists('pass_crypted', $fieldvalues) && property_exists($this, 'pass') && !empty($this->pass)) { // @phan-suppress-next-line PhanUndeclaredProperty $tmparray = dol_hash($this->pass, '0', 0, 1); diff --git a/htdocs/core/class/validate.class.php b/htdocs/core/class/validate.class.php index b0c986797a5..7854b3ee672 100644 --- a/htdocs/core/class/validate.class.php +++ b/htdocs/core/class/validate.class.php @@ -1,6 +1,6 @@ - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 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 @@ -34,7 +34,7 @@ class Validate public $db; /** - * @var Translate $outputLang + * @var Translate */ public $outputLang; @@ -247,8 +247,8 @@ class Validate /** * Check for boolean validity * - * @param boolean $bool Boolean to validate - * @return boolean Validity is ok or not + * @param mixed $bool Value to validate, may not be bool + * @return bool Validity is ok or not */ public function isBool($bool) { @@ -342,9 +342,9 @@ class Validate * Check for all values in db for an element * @see self::isFetchable() * - * @param integer $id of element - * @param string $element_type the element type - * @return boolean Validity is ok or not + * @param int $id Element Id + * @param string $element_type The element type + * @return bool Validity is ok or not * @throws Exception */ public function isFetchableElement($id, $element_type) diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 2b0f65ecfb7..da189c3dbc0 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -435,7 +435,7 @@ class SupplierProposal extends CommonObject * @param int $pa_ht Buying price without tax * @param string $label ??? * @param array $array_options extrafields array - * @param string $ref_supplier Supplier price reference + * @param string $ref_supplier Supplier price reference * @param int $fk_unit Id of the unit to use. * @param string $origin 'order', 'supplier_proposal', ... * @param int $origin_id Id of origin line From b91f457afb640557b21688ad49aedbc67bbb1be8 Mon Sep 17 00:00:00 2001 From: MDW Date: Mon, 3 Mar 2025 23:36:07 +0100 Subject: [PATCH 26/71] Update phan baseline --- dev/tools/phan/baseline.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dev/tools/phan/baseline.txt b/dev/tools/phan/baseline.txt index 95c289a6295..d69d146b591 100644 --- a/dev/tools/phan/baseline.txt +++ b/dev/tools/phan/baseline.txt @@ -181,7 +181,7 @@ return [ 'htdocs/comm/remise.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/remx.php' => ['PhanTypeMismatchArgument'], 'htdocs/commande/agenda.php' => ['PhanTypeMismatchArgument'], - 'htdocs/commande/card.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty'], + 'htdocs/commande/card.php' => ['PhanTypeMismatchArgument'], 'htdocs/commande/class/api_orders.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/commande/class/commande.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/commande/class/orderline.class.php' => ['PhanTypeMismatchArgument'], @@ -308,7 +308,7 @@ return [ 'htdocs/core/class/cgenericdic.class.php' => ['PhanUndeclaredProperty'], 'htdocs/core/class/commondocgenerator.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/core/class/commoninvoice.class.php' => ['PhanTypeMismatchArgument'], - 'htdocs/core/class/commonobject.class.php' => ['PhanParamTooMany', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchArgumentProbablyReal', 'PhanUndeclaredProperty'], + 'htdocs/core/class/commonobject.class.php' => ['PhanParamTooMany', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentProbablyReal', 'PhanUndeclaredProperty'], 'htdocs/core/class/commonpeople.class.php' => ['PhanUndeclaredProperty'], 'htdocs/core/class/commonsocialnetworks.class.php' => ['PhanUndeclaredProperty'], 'htdocs/core/class/commonstickergenerator.class.php' => ['PhanTypeMismatchArgument'], @@ -466,7 +466,6 @@ return [ 'htdocs/eventorganization/core/actions_massactions_mail.inc.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'], 'htdocs/expedition/ajax/searchfrombarcode.php' => ['PhanTypeMismatchArgument'], 'htdocs/expedition/card.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], - 'htdocs/expedition/class/api_shipments.class.php' => ['PhanTypeMismatchProperty'], 'htdocs/expedition/class/expedition.class.php' => ['PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/expedition/class/expeditionlinebatch.class.php' => ['PhanTypeMismatchArgumentNullable'], 'htdocs/expedition/list.php' => ['PhanTypeMismatchArgument'], From 4096d0ee2fb414cb539dcabe35fda91542d4d720 Mon Sep 17 00:00:00 2001 From: MDW Date: Tue, 4 Mar 2025 18:02:29 +0100 Subject: [PATCH 27/71] Qual: Fix phan notices for commande --- dev/tools/phan/baseline.txt | 15 +-- htdocs/commande/agenda.php | 3 +- htdocs/commande/card.php | 2 +- htdocs/commande/class/commande.class.php | 10 +- htdocs/commande/class/orderline.class.php | 6 +- htdocs/commande/contact.php | 5 +- htdocs/commande/document.php | 3 +- htdocs/commande/list.php | 97 +++++++++--------- htdocs/commande/list_det.php | 99 +++++++++---------- htdocs/commande/note.php | 3 +- htdocs/commande/stats/index.php | 6 +- htdocs/core/ajax/saveinplace.php | 4 +- .../modules/commande/mod_commande_saphir.php | 4 +- 13 files changed, 126 insertions(+), 131 deletions(-) diff --git a/dev/tools/phan/baseline.txt b/dev/tools/phan/baseline.txt index d69d146b591..460a8ca2505 100644 --- a/dev/tools/phan/baseline.txt +++ b/dev/tools/phan/baseline.txt @@ -180,18 +180,12 @@ return [ 'htdocs/comm/propal/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/comm/remise.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/remx.php' => ['PhanTypeMismatchArgument'], - 'htdocs/commande/agenda.php' => ['PhanTypeMismatchArgument'], 'htdocs/commande/card.php' => ['PhanTypeMismatchArgument'], 'htdocs/commande/class/api_orders.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], - 'htdocs/commande/class/commande.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], - 'htdocs/commande/class/orderline.class.php' => ['PhanTypeMismatchArgument'], - 'htdocs/commande/contact.php' => ['PhanTypeMismatchArgument'], + 'htdocs/commande/class/commande.class.php' => ['PhanUndeclaredProperty'], 'htdocs/commande/customer.php' => ['PhanUndeclaredGlobalVariable'], - 'htdocs/commande/document.php' => ['PhanTypeMismatchArgument'], - 'htdocs/commande/list.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], - 'htdocs/commande/list_det.php' => ['PhanTypeInvalidDimOffset', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], - 'htdocs/commande/note.php' => ['PhanTypeMismatchArgument'], - 'htdocs/commande/stats/index.php' => ['PhanTypeMismatchArgument'], + 'htdocs/commande/list.php' => ['PhanUndeclaredProperty'], + 'htdocs/commande/list_det.php' => ['PhanTypeInvalidDimOffset'], 'htdocs/commande/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/compta/accounting-files.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/bank/account_statement_document.php' => ['PhanUndeclaredGlobalVariable'], @@ -300,7 +294,7 @@ return [ 'htdocs/core/ajax/ajaxstatusprospect.php' => ['PhanTypeMismatchArgument'], 'htdocs/core/ajax/contacts.php' => ['PhanTypeMismatchArgument'], 'htdocs/core/ajax/loadinplace.php' => ['PhanTypeMismatchArgument'], - 'htdocs/core/ajax/saveinplace.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], + 'htdocs/core/ajax/saveinplace.php' => ['PhanTypeMismatchArgument'], 'htdocs/core/ajax/selectobject.php' => ['PhanTypeMismatchArgumentNullable'], 'htdocs/core/class/CMailFile.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/core/class/canvas.class.php' => ['PhanParamTooMany', 'PhanUndeclaredMethod'], @@ -370,7 +364,6 @@ return [ 'htdocs/core/modules/cheque/modules_chequereceipts.php' => ['PhanTypeMismatchArgument'], 'htdocs/core/modules/commande/doc/pdf_einstein.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'], 'htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'], - 'htdocs/core/modules/commande/mod_commande_saphir.php' => ['PhanTypeMismatchArgumentNullable'], 'htdocs/core/modules/contract/doc/pdf_strato.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/core/modules/delivery/doc/pdf_storm.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/core/modules/delivery/doc/pdf_typhon.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], diff --git a/htdocs/commande/agenda.php b/htdocs/commande/agenda.php index aa4a1ff44ff..4d238daf252 100644 --- a/htdocs/commande/agenda.php +++ b/htdocs/commande/agenda.php @@ -1,6 +1,7 @@ * Copyright (C) 2024 Frédéric France + * Copyright (C) 2025 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 @@ -166,7 +167,7 @@ if ($object->id > 0) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 0bcd0040c6f..82569c9031a 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1136,7 +1136,7 @@ if (empty($reshook)) { $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty); // Margin - $fournprice = price2num(GETPOST('fournprice'.$predef) ? GETPOSTINT('fournprice'.$predef) : ''); + $fournprice = price2num(GETPOST('fournprice'.$predef) ? GETPOSTINT('fournprice'.$predef) : 0); $buyingprice = price2num(GETPOST('buying_price'.$predef) != '' ? GETPOST('buying_price'.$predef) : ''); // If buying_price is '0', we must keep this value // Prepare a price equivalent for minimum price check diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 6d079d30445..75e86c1ca90 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1019,14 +1019,14 @@ class Commande extends CommonOrder $sql .= " VALUES ('(PROV)', ".((int) $this->socid).", '".$this->db->idate($now)."', ".((int) $user->id); $sql .= ", ".($this->fk_project > 0 ? ((int) $this->fk_project) : "null"); $sql .= ", '".$this->db->idate($date)."'"; - $sql .= ", ".($this->source >= 0 && $this->source != '' ? $this->db->escape($this->source) : 'null'); + $sql .= ", ".($this->source >= 0 && $this->source != '' ? $this->db->escape((string) $this->source) : 'null'); $sql .= ", '".$this->db->escape($this->note_private)."'"; $sql .= ", '".$this->db->escape($this->note_public)."'"; $sql .= ", ".($this->ref_ext ? "'".$this->db->escape($this->ref_ext)."'" : "null"); $sql .= ", ".($this->ref_client ? "'".$this->db->escape($this->ref_client)."'" : "null"); $sql .= ", '".$this->db->escape($this->model_pdf)."'"; $sql .= ", ".($this->cond_reglement_id > 0 ? ((int) $this->cond_reglement_id) : "null"); - $sql .= ", ".(!empty($this->deposit_percent) ? "'".$this->db->escape($this->deposit_percent)."'" : "null"); + $sql .= ", ".(!empty($this->deposit_percent) ? "'".$this->db->escape((string) $this->deposit_percent)."'" : "null"); $sql .= ", ".($this->mode_reglement_id > 0 ? ((int) $this->mode_reglement_id) : "null"); $sql .= ", ".($this->fk_account > 0 ? ((int) $this->fk_account) : 'NULL'); $sql .= ", ".($this->availability_id > 0 ? ((int) $this->availability_id) : "null"); @@ -1114,7 +1114,7 @@ class Commande extends CommonOrder $line->label, $line->array_options, $line->fk_unit, - $origintype, + (string) $origintype, $originid, 0, $line->ref_ext, @@ -1680,7 +1680,7 @@ class Commande extends CommonOrder $txtva = preg_replace('/\s*\(.*\)/', '', $txtva); // Remove code into vatrate. } - $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise); + $tabprice = calcul_price_total($qty, (float) $pu, $remise_percent, $txtva, (float) $txlocaltax1, (float) $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, (float) $pu_ht_devise); /*var_dump($txlocaltax1); var_dump($txlocaltax2); @@ -3140,7 +3140,7 @@ class Commande extends CommonOrder $txtva = preg_replace('/\s*\(.*\)/', '', $txtva); // Remove code into vatrate. } - $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise); + $tabprice = calcul_price_total($qty, (float) $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx, (float) $pu_ht_devise); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; diff --git a/htdocs/commande/class/orderline.class.php b/htdocs/commande/class/orderline.class.php index 618bbcccf74..a50f0e0caf5 100644 --- a/htdocs/commande/class/orderline.class.php +++ b/htdocs/commande/class/orderline.class.php @@ -13,7 +13,7 @@ * Copyright (C) 2016-2022 Ferran Marcet * Copyright (C) 2021-2024 Frédéric France * Copyright (C) 2022 Gauthier VERDOL - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 William Mead * * This program is free software; you can redistribute it and/or modify @@ -425,7 +425,7 @@ class OrderLine extends CommonOrderLine $sql .= ' fk_multicurrency, multicurrency_code, multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc'; $sql .= ')'; $sql .= " VALUES (".$this->fk_commande.","; - $sql .= " ".($this->fk_parent_line > 0 ? "'".$this->db->escape($this->fk_parent_line)."'" : "null").","; + $sql .= " ".($this->fk_parent_line > 0 ? "'".$this->db->escape((string) $this->fk_parent_line)."'" : "null").","; $sql .= " ".(!empty($this->label) ? "'".$this->db->escape($this->label)."'" : "null").","; $sql .= " '".$this->db->escape($this->desc)."',"; $sql .= " '".price2num($this->qty)."',"; @@ -437,7 +437,7 @@ class OrderLine extends CommonOrderLine $sql .= " '".$this->db->escape($this->localtax1_type)."',"; $sql .= " '".$this->db->escape($this->localtax2_type)."',"; $sql .= ' '.((!empty($this->fk_product) && $this->fk_product > 0) ? $this->fk_product : "null").','; - $sql .= " '".$this->db->escape($this->product_type)."',"; + $sql .= " '".$this->db->escape((string) $this->product_type)."',"; $sql .= " '".price2num($this->remise_percent)."',"; $sql .= " ".(price2num($this->subprice) !== '' ? price2num($this->subprice) : "null").","; $sql .= " ".($this->price != '' ? "'".price2num($this->price)."'" : "null").","; diff --git a/htdocs/commande/contact.php b/htdocs/commande/contact.php index 0f105e235cd..0c7a161e6ef 100644 --- a/htdocs/commande/contact.php +++ b/htdocs/commande/contact.php @@ -4,6 +4,7 @@ * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2011-2022 Philippe Grand * Copyright (C) 2021-2024 Frédéric France + * Copyright (C) 2025 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 @@ -66,7 +67,7 @@ $object = new Commande($db); * Actions */ -$parameters = array('id'=>$id); +$parameters = array('id' => $id); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -161,7 +162,7 @@ if ($id > 0 || !empty($ref)) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); diff --git a/htdocs/commande/document.php b/htdocs/commande/document.php index 82fb2fdbeb5..384b99daa39 100644 --- a/htdocs/commande/document.php +++ b/htdocs/commande/document.php @@ -6,6 +6,7 @@ * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2017 Ferran Marcet * Copyright (C) 2024 Frédéric France + * Copyright (C) 2025 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 @@ -154,7 +155,7 @@ if ($id > 0 || !empty($ref)) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 10db3c8d9b1..806af501773 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -12,7 +12,7 @@ * Copyright (C) 2016-2023 Ferran Marcet * Copyright (C) 2018-2023 Charlene Benke * Copyright (C) 2021-2024 Anthony Berton - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 Noé Cendrier * Copyright (C) 2024 Benjamin Falière * Copyright (C) 2024 Alexandre Spangaro @@ -200,49 +200,49 @@ if (empty($user->socid)) { $checkedtypetiers = 0; $arrayfields = array( - 'c.rowid' => array('label' => "ID", 'checked' => 1, 'enabled' => getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID'), 'position' => 1), - 'c.ref' => array('label' => "Ref", 'checked' => 1, 'position' => 5, 'searchall' => 1), - 'c.ref_ext' => array('label' => "RefExt", 'checked' => 1, 'position' => 5, 'visible' => 0, 'searchall' => 1), - 'c.ref_client' => array('label' => "RefCustomerOrder", 'checked' => -1, 'position' => 10, 'searchall' => 1), - 'p.ref' => array('label' => "ProjectRef", 'checked' => -1, 'enabled' => (!isModEnabled('project') ? 0 : 1), 'position' => 20), - 'p.title' => array('label' => "ProjectLabel", 'checked' => 0, 'enabled' => (!isModEnabled('project') ? 0 : 1), 'position' => 25), - 's.nom' => array('label' => "ThirdParty", 'checked' => 1, 'position' => 30, 'searchall' => 1), - 's.name_alias' => array('label' => "AliasNameShort", 'checked' => -1, 'position' => 31, 'searchall' => 1), - 's2.nom' => array('label' => 'ParentCompany', 'position' => 32, 'checked' => 0), - 's.town' => array('label' => "Town", 'checked' => -1, 'position' => 35, 'searchall' => 1), - 's.zip' => array('label' => "Zip", 'checked' => -1, 'position' => 40, 'searchall' => 1), - 'state.nom' => array('label' => "StateShort", 'checked' => 0, 'position' => 45), - 'country.code_iso' => array('label' => "Country", 'checked' => 0, 'position' => 50), - 'typent.code' => array('label' => "ThirdPartyType", 'checked' => $checkedtypetiers, 'position' => 55), - 'c.date_commande' => array('label' => "OrderDateShort", 'checked' => 1, 'position' => 60, 'csslist' => 'nowraponall'), - 'c.delivery_date' => array('label' => "DateDeliveryPlanned", 'checked' => 1, 'enabled' => !getDolGlobalString('ORDER_DISABLE_DELIVERY_DATE'), 'position' => 65, 'csslist' => 'nowraponall'), - 'c.fk_shipping_method' => array('label' => "SendingMethod", 'checked' => -1, 'position' => 66 , 'enabled' => isModEnabled("shipping")), - 'c.fk_cond_reglement' => array('label' => "PaymentConditionsShort", 'checked' => -1, 'position' => 67), - 'c.fk_mode_reglement' => array('label' => "PaymentMode", 'checked' => -1, 'position' => 68), - 'c.fk_input_reason' => array('label' => "Origin", 'checked' => -1, 'position' => 69), - 'c.total_ht' => array('label' => "AmountHT", 'checked' => 1, 'position' => 75), - 'c.total_vat' => array('label' => "AmountVAT", 'checked' => 0, 'position' => 80), - 'c.total_ttc' => array('label' => "AmountTTC", 'checked' => 0, 'position' => 85), - 'c.multicurrency_code' => array('label' => 'Currency', 'checked' => 0, 'enabled' => (!isModEnabled("multicurrency") ? 0 : 1), 'position' => 90), - 'c.multicurrency_tx' => array('label' => 'CurrencyRate', 'checked' => 0, 'enabled' => (!isModEnabled("multicurrency") ? 0 : 1), 'position' => 95), - 'c.multicurrency_total_ht' => array('label' => 'MulticurrencyAmountHT', 'checked' => 0, 'enabled' => (!isModEnabled("multicurrency") ? 0 : 1), 'position' => 100), - 'c.multicurrency_total_vat' => array('label' => 'MulticurrencyAmountVAT', 'checked' => 0, 'enabled' => (!isModEnabled("multicurrency") ? 0 : 1), 'position' => 105), - 'c.multicurrency_total_ttc' => array('label' => 'MulticurrencyAmountTTC', 'checked' => 0, 'enabled' => (!isModEnabled("multicurrency") ? 0 : 1), 'position' => 110), - 'u.login' => array('label' => "Author", 'checked' => -1, 'position' => 115), - 'sale_representative' => array('label' => "SaleRepresentativesOfThirdParty", 'checked' => 0, 'position' => 116), - 'total_pa' => array('label' => (getDolGlobalString('MARGIN_TYPE') == '1' ? 'BuyingPrice' : 'CostPrice'), 'checked' => 0, 'position' => 300, 'enabled' => (!isModEnabled('margin') || !$user->hasRight("margins", "liretous") ? 0 : 1)), - 'total_margin' => array('label' => 'Margin', 'checked' => 0, 'position' => 301, 'enabled' => (!isModEnabled('margin') || !$user->hasRight("margins", "liretous") ? 0 : 1)), - 'total_margin_rate' => array('label' => 'MarginRate', 'checked' => 0, 'position' => 302, 'enabled' => (!isModEnabled('margin') || !$user->hasRight("margins", "liretous") || !getDolGlobalString('DISPLAY_MARGIN_RATES') ? 0 : 1)), - 'total_mark_rate' => array('label' => 'MarkRate', 'checked' => 0, 'position' => 303, 'enabled' => (!isModEnabled('margin') || !$user->hasRight("margins", "liretous") || !getDolGlobalString('DISPLAY_MARK_RATES') ? 0 : 1)), - 'c.datec' => array('label' => "DateCreation", 'checked' => 0, 'position' => 120), - 'c.tms' => array('label' => "DateModificationShort", 'checked' => 0, 'position' => 125), - 'c.date_cloture' => array('label' => "DateClosing", 'checked' => 0, 'position' => 130), - 'c.note_public' => array('label' => 'NotePublic', 'checked' => 0, 'enabled' => (!getDolGlobalInt('MAIN_LIST_HIDE_PUBLIC_NOTES')), 'position' => 135, 'searchall' => 1), - 'c.note_private' => array('label' => 'NotePrivate', 'checked' => 0, 'enabled' => (!getDolGlobalInt('MAIN_LIST_HIDE_PRIVATE_NOTES')), 'position' => 140), - 'shippable' => array('label' => "Shippable", 'checked' => 1,'enabled' => (isModEnabled("shipping")), 'position' => 990), - 'c.facture' => array('label' => "Billed", 'checked' => 1, 'enabled' => (!getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')), 'position' => 995), - 'c.import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 999), - 'c.fk_statut' => array('label' => "Status", 'checked' => 1, 'position' => 1000) + 'c.rowid' => array('label' => "ID", 'checked' => '1', 'enabled' => (string) getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID'), 'position' => 1), + 'c.ref' => array('label' => "Ref", 'checked' => '1', 'position' => 5, 'searchall' => 1), + 'c.ref_ext' => array('label' => "RefExt", 'checked' => '1', 'position' => 5, 'visible' => 0, 'searchall' => 1), + 'c.ref_client' => array('label' => "RefCustomerOrder", 'checked' => '-1', 'position' => 10, 'searchall' => 1), + 'p.ref' => array('label' => "ProjectRef", 'checked' => '-1', 'enabled' => (!isModEnabled('project') ? '0' : '1'), 'position' => 20), + 'p.title' => array('label' => "ProjectLabel", 'checked' => '0', 'enabled' => (!isModEnabled('project') ? '0' : '1'), 'position' => 25), + 's.nom' => array('label' => "ThirdParty", 'checked' => '1', 'position' => 30, 'searchall' => 1), + 's.name_alias' => array('label' => "AliasNameShort", 'checked' => '-1', 'position' => 31, 'searchall' => 1), + 's2.nom' => array('label' => 'ParentCompany', 'position' => 32, 'checked' => '0'), + 's.town' => array('label' => "Town", 'checked' => '-1', 'position' => 35, 'searchall' => 1), + 's.zip' => array('label' => "Zip", 'checked' => '-1', 'position' => 40, 'searchall' => 1), + 'state.nom' => array('label' => "StateShort", 'checked' => '0', 'position' => 45), + 'country.code_iso' => array('label' => "Country", 'checked' => '0', 'position' => 50), + 'typent.code' => array('label' => "ThirdPartyType", 'checked' => (string) $checkedtypetiers, 'position' => 55), + 'c.date_commande' => array('label' => "OrderDateShort", 'checked' => '1', 'position' => 60, 'csslist' => 'nowraponall'), + 'c.delivery_date' => array('label' => "DateDeliveryPlanned", 'checked' => '1', 'enabled' => (string) (int) !getDolGlobalString('ORDER_DISABLE_DELIVERY_DATE'), 'position' => 65, 'csslist' => 'nowraponall'), + 'c.fk_shipping_method' => array('label' => "SendingMethod", 'checked' => '-1', 'position' => 66 , 'enabled' => (string) (int) isModEnabled("shipping")), + 'c.fk_cond_reglement' => array('label' => "PaymentConditionsShort", 'checked' => '-1', 'position' => 67), + 'c.fk_mode_reglement' => array('label' => "PaymentMode", 'checked' => '-1', 'position' => 68), + 'c.fk_input_reason' => array('label' => "Origin", 'checked' => '-1', 'position' => 69), + 'c.total_ht' => array('label' => "AmountHT", 'checked' => '1', 'position' => 75), + 'c.total_vat' => array('label' => "AmountVAT", 'checked' => '0', 'position' => 80), + 'c.total_ttc' => array('label' => "AmountTTC", 'checked' => '0', 'position' => 85), + 'c.multicurrency_code' => array('label' => 'Currency', 'checked' => '0', 'enabled' => (!isModEnabled("multicurrency") ? '0' : '1'), 'position' => 90), + 'c.multicurrency_tx' => array('label' => 'CurrencyRate', 'checked' => '0', 'enabled' => (!isModEnabled("multicurrency") ? '0' : '1'), 'position' => 95), + 'c.multicurrency_total_ht' => array('label' => 'MulticurrencyAmountHT', 'checked' => '0', 'enabled' => (!isModEnabled("multicurrency") ? '0' : '1'), 'position' => 100), + 'c.multicurrency_total_vat' => array('label' => 'MulticurrencyAmountVAT', 'checked' => '0', 'enabled' => (!isModEnabled("multicurrency") ? '0' : '1'), 'position' => 105), + 'c.multicurrency_total_ttc' => array('label' => 'MulticurrencyAmountTTC', 'checked' => '0', 'enabled' => (!isModEnabled("multicurrency") ? '0' : '1'), 'position' => 110), + 'u.login' => array('label' => "Author", 'checked' => '-1', 'position' => 115), + 'sale_representative' => array('label' => "SaleRepresentativesOfThirdParty", 'checked' => '0', 'position' => 116), + 'total_pa' => array('label' => (getDolGlobalString('MARGIN_TYPE') == '1' ? 'BuyingPrice' : 'CostPrice'), 'checked' => '0', 'position' => 300, 'enabled' => (string) (int) (!isModEnabled('margin') || !$user->hasRight("margins", "liretous") ? 0 : 1)), + 'total_margin' => array('label' => 'Margin', 'checked' => '0', 'position' => 301, 'enabled' => (string) (int) (!isModEnabled('margin') || !$user->hasRight("margins", "liretous") ? 0 : 1)), + 'total_margin_rate' => array('label' => 'MarginRate', 'checked' => '0', 'position' => 302, 'enabled' => (string) (int) (!isModEnabled('margin') || !$user->hasRight("margins", "liretous") || !getDolGlobalString('DISPLAY_MARGIN_RATES') ? 0 : 1)), + 'total_mark_rate' => array('label' => 'MarkRate', 'checked' => '0', 'position' => 303, 'enabled' => (string) (int) (!isModEnabled('margin') || !$user->hasRight("margins", "liretous") || !getDolGlobalString('DISPLAY_MARK_RATES') ? 0 : 1)), + 'c.datec' => array('label' => "DateCreation", 'checked' => '0', 'position' => 120), + 'c.tms' => array('label' => "DateModificationShort", 'checked' => '0', 'position' => 125), + 'c.date_cloture' => array('label' => "DateClosing", 'checked' => '0', 'position' => 130), + 'c.note_public' => array('label' => 'NotePublic', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalInt('MAIN_LIST_HIDE_PUBLIC_NOTES')), 'position' => 135, 'searchall' => 1), + 'c.note_private' => array('label' => 'NotePrivate', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalInt('MAIN_LIST_HIDE_PRIVATE_NOTES')), 'position' => 140), + 'shippable' => array('label' => "Shippable", 'checked' => '1','enabled' => (string) (int) (isModEnabled("shipping")), 'position' => 990), + 'c.facture' => array('label' => "Billed", 'checked' => '1', 'enabled' => (string) (int) (!getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')), 'position' => 995), + 'c.import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => '1', 'visible' => -2, 'position' => 999), + 'c.fk_statut' => array('label' => "Status", 'checked' => '1', 'position' => 1000) ); $parameters = array('fieldstosearchall' => $fieldstosearchall); @@ -259,7 +259,6 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; $object->fields = dol_sort_array($object->fields, 'position'); //$arrayfields['anotherfield'] = array('type'=>'integer', 'label'=>'AnotherField', 'checked'=>1, 'enabled'=>1, 'position'=>90, 'csslist'=>'right'); $arrayfields = dol_sort_array($arrayfields, 'position'); -'@phan-var-force array,position?:int,help?:string}> $arrayfields'; // dol_sort_array looses type for Phan // Security check @@ -1575,7 +1574,7 @@ if ($user->hasRight("user", "user", "lire")) { if ($user->hasRight("user", "user", "lire")) { $moreforfilter .= '
'; $tmptitle = $langs->trans('LinkedToSpecificUsers'); - $moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_user, 'search_user', $tmptitle, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth250 widthcentpercentminusx'); + $moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_user, 'search_user', $tmptitle, null, 0, '', '', '0', 0, 0, '', 0, '', 'maxwidth250 widthcentpercentminusx'); $moreforfilter .= '
'; } @@ -1585,7 +1584,7 @@ if (isModEnabled('category') && $user->hasRight("categorie", "lire") && ($user-> $moreforfilter .= '
'; $tmptitle = $langs->trans('IncludingProductWithTag'); $cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, '', 'parent', 0, array(), 1); - $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"').$form->selectarray('search_product_category', $cate_arbo, $search_product_category, $tmptitle, 0, 0, '', 0, 0, 0, 0, 'maxwidth300 widthcentpercentminusx', 1); + $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"').$form->selectarray('search_product_category', $cate_arbo, $search_product_category, $tmptitle, 0, 0, '', 0, 0, 0, '', 'maxwidth300 widthcentpercentminusx', 1); $moreforfilter .= '
'; } // If Categories are enabled & user has rights to see @@ -1685,7 +1684,7 @@ if (!empty($arrayfields['p.title']['checked'])) { // Thirpdarty if (!empty($arrayfields['s.nom']['checked'])) { print '
'; } // Alias @@ -1756,7 +1755,7 @@ if (!empty($arrayfields['c.fk_shipping_method']['checked'])) { // Payment term if (!empty($arrayfields['c.fk_cond_reglement']['checked'])) { print ''; } // Payment mode diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index f1e0d517f73..f5a41ddae21 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -12,7 +12,7 @@ * Copyright (C) 2016-2021 Ferran Marcet * Copyright (C) 2018-2023 Charlene Benke * Copyright (C) 2021-2023 Anthony Berton - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 Alexandre Spangaro * * This program is free software; you can redistribute it and/or modify @@ -191,51 +191,51 @@ if (empty($user->socid)) { $checkedtypetiers = 0; $arrayfields = array( // Détail commande - 'rowid' => array('label' => 'TechnicalID', 'checked' => 1, 'position' => 1, 'enabled' => (getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') ? 1 : 0)), - 'pr.ref' => array('label' => 'ProductRef', 'checked' => 1, 'position' => 1), - 'pr.desc' => array('label' => 'ProductDescription', 'checked' => -1, 'position' => 1), - 'cdet.qty' => array('label' => 'QtyOrdered', 'checked' => 1, 'position' => 1), - 'c.ref' => array('label' => "Ref", 'checked' => 1, 'position' => 5), - 'c.ref_client' => array('label' => "RefCustomerOrder", 'checked' => -1, 'position' => 10), - 'p.ref' => array('label' => "ProjectRef", 'checked' => -1, 'enabled' => (empty($conf->project->enabled) ? 0 : 1), 'position' => 20), - 'p.title' => array('label' => "ProjectLabel", 'checked' => 0, 'enabled' => (empty($conf->project->enabled) ? 0 : 1), 'position' => 25), - 's.nom' => array('label' => "ThirdParty", 'checked' => 1, 'position' => 30), - 's.name_alias' => array('label' => "AliasNameShort", 'checked' => -1, 'position' => 31), - 's.town' => array('label' => "Town", 'checked' => -1, 'position' => 35), - 's.zip' => array('label' => "Zip", 'checked' => -1, 'position' => 40), - 'state.nom' => array('label' => "StateShort", 'checked' => 0, 'position' => 45), - 'country.code_iso' => array('label' => "Country", 'checked' => 0, 'position' => 50), - 'typent.code' => array('label' => "ThirdPartyType", 'checked' => $checkedtypetiers, 'position' => 55), - 'c.date_commande' => array('label' => "OrderDateShort", 'checked' => 1, 'position' => 60), - 'c.delivery_date' => array('label' => "DateDeliveryPlanned", 'checked' => 1, 'enabled' => !getDolGlobalString('ORDER_DISABLE_DELIVERY_DATE'), 'position' => 65), - 'c.fk_shipping_method' => array('label' => "SendingMethod", 'checked' => -1, 'position' => 66 , 'enabled' => isModEnabled('shipping')), - 'c.fk_cond_reglement' => array('label' => "PaymentConditionsShort", 'checked' => -1, 'position' => 67), - 'c.fk_mode_reglement' => array('label' => "PaymentMode", 'checked' => -1, 'position' => 68), - 'c.fk_input_reason' => array('label' => "Channel", 'checked' => -1, 'position' => 69), - 'cdet.total_ht' => array('label' => "AmountHT", 'checked' => 1, 'position' => 75), - 'c.total_vat' => array('label' => "AmountVAT", 'checked' => 0, 'position' => 80), - 'cdet.total_ttc' => array('label' => "AmountTTC", 'checked' => 0, 'position' => 85), - 'c.multicurrency_code' => array('label' => 'Currency', 'checked' => 0, 'enabled' => (empty($conf->multicurrency->enabled) ? 0 : 1), 'position' => 90), - 'c.multicurrency_tx' => array('label' => 'CurrencyRate', 'checked' => 0, 'enabled' => (empty($conf->multicurrency->enabled) ? 0 : 1), 'position' => 95), - 'c.multicurrency_total_ht' => array('label' => 'MulticurrencyAmountHT', 'checked' => 0, 'enabled' => (empty($conf->multicurrency->enabled) ? 0 : 1), 'position' => 100), - 'c.multicurrency_total_vat' => array('label' => 'MulticurrencyAmountVAT', 'checked' => 0, 'enabled' => (empty($conf->multicurrency->enabled) ? 0 : 1), 'position' => 105), - 'c.multicurrency_total_ttc' => array('label' => 'MulticurrencyAmountTTC', 'checked' => 0, 'enabled' => (empty($conf->multicurrency->enabled) ? 0 : 1), 'position' => 110), - 'c.fk_warehouse' => array('label' => 'Warehouse', 'checked' => 0, 'enabled' => (!isModEnabled('stock') && !getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER') ? 0 : 1), 'position' => 110), - 'u.login' => array('label' => "Author", 'checked' => 1, 'position' => 115), - 'sale_representative' => array('label' => "SaleRepresentativesOfThirdParty", 'checked' => 0, 'position' => 116), - 'total_pa' => array('label' => (getDolGlobalString('MARGIN_TYPE') == '1' ? 'BuyingPrice' : 'CostPrice'), 'checked' => 0, 'position' => 300, 'enabled' => (!isModEnabled('margin') || !$user->hasRight('margins', 'liretous') ? 0 : 1)), - 'total_margin' => array('label' => 'Margin', 'checked' => 0, 'position' => 301, 'enabled' => (!isModEnabled('margin') || !$user->hasRight('margins', 'liretous') ? 0 : 1)), - 'total_margin_rate' => array('label' => 'MarginRate', 'checked' => 0, 'position' => 302, 'enabled' => (!isModEnabled('margin') || !$user->hasRight('margins', 'liretous') || !getDolGlobalString('DISPLAY_MARGIN_RATES') ? 0 : 1)), - 'total_mark_rate' => array('label' => 'MarkRate', 'checked' => 0, 'position' => 303, 'enabled' => (!isModEnabled('margin') || !$user->hasRight('margins', 'liretous') || !getDolGlobalString('DISPLAY_MARK_RATES') ? 0 : 1)), - 'c.datec' => array('label' => "DateCreation", 'checked' => 0, 'position' => 120), - 'c.tms' => array('label' => "DateModificationShort", 'checked' => 0, 'position' => 125), - 'c.date_cloture' => array('label' => "DateClosing", 'checked' => 0, 'position' => 130), - 'c.note_public' => array('label' => 'NotePublic', 'checked' => 0, 'enabled' => (!getDolGlobalString('MAIN_LIST_ALLOW_PUBLIC_NOTES')), 'position' => 135), - 'c.note_private' => array('label' => 'NotePrivate', 'checked' => 0, 'enabled' => (!getDolGlobalString('MAIN_LIST_ALLOW_PRIVATE_NOTES')), 'position' => 140), - 'shippable' => array('label' => "Shippable", 'checked' => 1,'enabled' => (isModEnabled('shipping')), 'position' => 990), - 'c.facture' => array('label' => "Billed", 'checked' => 1, 'enabled' => (!getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')), 'position' => 995), - 'c.import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 999), - 'c.fk_statut' => array('label' => "Status", 'checked' => 1, 'position' => 1000) + 'rowid' => array('label' => 'TechnicalID', 'checked' => '1', 'position' => 1, 'enabled' => (getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') ? '1' : '0')), + 'pr.ref' => array('label' => 'ProductRef', 'checked' => '1', 'position' => 1), + 'pr.desc' => array('label' => 'ProductDescription', 'checked' => '-1', 'position' => 1), + 'cdet.qty' => array('label' => 'QtyOrdered', 'checked' => '1', 'position' => 1), + 'c.ref' => array('label' => "Ref", 'checked' => '1', 'position' => 5), + 'c.ref_client' => array('label' => "RefCustomerOrder", 'checked' => '-1', 'position' => 10), + 'p.ref' => array('label' => "ProjectRef", 'checked' => '-1', 'enabled' => (empty($conf->project->enabled) ? '0' : '1'), 'position' => 20), + 'p.title' => array('label' => "ProjectLabel", 'checked' => '0', 'enabled' => (empty($conf->project->enabled) ? '0' : '1'), 'position' => 25), + 's.nom' => array('label' => "ThirdParty", 'checked' => '1', 'position' => 30), + 's.name_alias' => array('label' => "AliasNameShort", 'checked' => '-1', 'position' => 31), + 's.town' => array('label' => "Town", 'checked' => '-1', 'position' => 35), + 's.zip' => array('label' => "Zip", 'checked' => '-1', 'position' => 40), + 'state.nom' => array('label' => "StateShort", 'checked' => '0', 'position' => 45), + 'country.code_iso' => array('label' => "Country", 'checked' => '0', 'position' => 50), + 'typent.code' => array('label' => "ThirdPartyType", 'checked' => (string) $checkedtypetiers, 'position' => 55), + 'c.date_commande' => array('label' => "OrderDateShort", 'checked' => '1', 'position' => 60), + 'c.delivery_date' => array('label' => "DateDeliveryPlanned", 'checked' => '1', 'enabled' => (string) (int) !getDolGlobalString('ORDER_DISABLE_DELIVERY_DATE'), 'position' => 65), + 'c.fk_shipping_method' => array('label' => "SendingMethod", 'checked' => '-1', 'position' => 66 , 'enabled' => (string) (int) isModEnabled('shipping')), + 'c.fk_cond_reglement' => array('label' => "PaymentConditionsShort", 'checked' => '-1', 'position' => 67), + 'c.fk_mode_reglement' => array('label' => "PaymentMode", 'checked' => '-1', 'position' => 68), + 'c.fk_input_reason' => array('label' => "Channel", 'checked' => '-1', 'position' => 69), + 'cdet.total_ht' => array('label' => "AmountHT", 'checked' => '1', 'position' => 75), + 'c.total_vat' => array('label' => "AmountVAT", 'checked' => '0', 'position' => 80), + 'cdet.total_ttc' => array('label' => "AmountTTC", 'checked' => '0', 'position' => 85), + 'c.multicurrency_code' => array('label' => 'Currency', 'checked' => '0', 'enabled' => (empty($conf->multicurrency->enabled) ? '0' : '1'), 'position' => 90), + 'c.multicurrency_tx' => array('label' => 'CurrencyRate', 'checked' => '0', 'enabled' => (empty($conf->multicurrency->enabled) ? '0' : '1'), 'position' => 95), + 'c.multicurrency_total_ht' => array('label' => 'MulticurrencyAmountHT', 'checked' => '0', 'enabled' => (empty($conf->multicurrency->enabled) ? '0' : '1'), 'position' => 100), + 'c.multicurrency_total_vat' => array('label' => 'MulticurrencyAmountVAT', 'checked' => '0', 'enabled' => (empty($conf->multicurrency->enabled) ? '0' : '1'), 'position' => 105), + 'c.multicurrency_total_ttc' => array('label' => 'MulticurrencyAmountTTC', 'checked' => '0', 'enabled' => (empty($conf->multicurrency->enabled) ? '0' : '1'), 'position' => 110), + 'c.fk_warehouse' => array('label' => 'Warehouse', 'checked' => '0', 'enabled' => (string) (int) (!isModEnabled('stock') && !getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER') ? '0' : '1'), 'position' => 110), + 'u.login' => array('label' => "Author", 'checked' => '1', 'position' => 115), + 'sale_representative' => array('label' => "SaleRepresentativesOfThirdParty", 'checked' => '0', 'position' => 116), + 'total_pa' => array('label' => (getDolGlobalString('MARGIN_TYPE') == '1' ? 'BuyingPrice' : 'CostPrice'), 'checked' => '0', 'position' => 300, 'enabled' => (string) (int) (!isModEnabled('margin') || !$user->hasRight('margins', 'liretous') ? '0' : '1')), + 'total_margin' => array('label' => 'Margin', 'checked' => '0', 'position' => 301, 'enabled' => (string) (int) (!isModEnabled('margin') || !$user->hasRight('margins', 'liretous') ? '0' : '1')), + 'total_margin_rate' => array('label' => 'MarginRate', 'checked' => '0', 'position' => 302, 'enabled' => (string) (int) (!isModEnabled('margin') || !$user->hasRight('margins', 'liretous') || !getDolGlobalString('DISPLAY_MARGIN_RATES') ? '0' : '1')), + 'total_mark_rate' => array('label' => 'MarkRate', 'checked' => '0', 'position' => 303, 'enabled' => (string) (int) (!isModEnabled('margin') || !$user->hasRight('margins', 'liretous') || !getDolGlobalString('DISPLAY_MARK_RATES') ? '0' : '1')), + 'c.datec' => array('label' => "DateCreation", 'checked' => '0', 'position' => 120), + 'c.tms' => array('label' => "DateModificationShort", 'checked' => '0', 'position' => 125), + 'c.date_cloture' => array('label' => "DateClosing", 'checked' => '0', 'position' => 130), + 'c.note_public' => array('label' => 'NotePublic', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_ALLOW_PUBLIC_NOTES')), 'position' => 135), + 'c.note_private' => array('label' => 'NotePrivate', 'checked' => '0', 'enabled' => (string) (int) (!getDolGlobalString('MAIN_LIST_ALLOW_PRIVATE_NOTES')), 'position' => 140), + 'shippable' => array('label' => "Shippable", 'checked' => '1','enabled' => (string) (int) (isModEnabled('shipping')), 'position' => 990), + 'c.facture' => array('label' => "Billed", 'checked' => '1', 'enabled' => (string) (int) (!getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')), 'position' => 995), + 'c.import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => '1', 'visible' => -2, 'position' => 999), + 'c.fk_statut' => array('label' => "Status", 'checked' => '1', 'position' => 1000) ); // Extra fields @@ -243,7 +243,6 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; $object->fields = dol_sort_array($object->fields, 'position'); $arrayfields = dol_sort_array($arrayfields, 'position'); -'@phan-var-force array,position?:int,help?:string}> $arrayfields'; // dol_sort_array looses type for Phan if (!$user->hasRight('societe', 'client', 'voir')) { $search_sale = $user->id; @@ -946,7 +945,7 @@ if ($resql) { if ($user->hasRight('user', 'user', 'lire')) { $moreforfilter .= '
'; $tmptitle = $langs->trans('LinkedToSpecificUsers'); - $moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_user, 'search_user', $tmptitle, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth250 widthcentpercentminusx'); + $moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_user, 'search_user', $tmptitle, null, 0, '', '', '0', 0, 0, '', 0, '', 'maxwidth250 widthcentpercentminusx'); $moreforfilter .= '
'; } // Filter on categories @@ -1057,7 +1056,7 @@ if ($resql) { // Thirpdarty if (!empty($arrayfields['s.nom']['checked'])) { print '
'; } // Alias @@ -1782,7 +1781,7 @@ if ($resql) { } // Plannned date of delivery if (!empty($arrayfields['c.delivery_date']['checked'])) { - print ''; if (!$i) { diff --git a/htdocs/commande/note.php b/htdocs/commande/note.php index 572e741348f..1423d7fc06a 100644 --- a/htdocs/commande/note.php +++ b/htdocs/commande/note.php @@ -5,6 +5,7 @@ * Copyright (C) 2013 Florian Henry * Copyright (C) 2017 Ferran Marcet * Copyright (C) 2024 Frédéric France + * Copyright (C) 2025 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 @@ -123,7 +124,7 @@ if ($id > 0 || !empty($ref)) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index cc2aac53b02..a8dc9589ab9 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -5,7 +5,7 @@ * Copyright (C) 2012 Marcos García * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2020 Maxime DEMAREST - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -272,7 +272,7 @@ if (!$mesg) { $px3->SetLegend($legend); $px3->SetYLabel($langs->trans("AmountAverage")); $px3->SetMaxValue($px3->GetCeilMaxValue()); - $px3->SetMinValue($px3->GetFloorMinValue()); + $px3->SetMinValue((int) $px3->GetFloorMinValue()); $px3->SetWidth($WIDTH); $px3->SetHeight($HEIGHT); $px3->SetShading(3); @@ -363,7 +363,7 @@ print ''; // User print ''; } } else { - print ''; + print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print 'id.'" class="oddeven status'.$objectstatic->status.' '.((getDolGlobalInt('MAIN_FINISHED_LINES_OPACITY') == 1 && $obj->status > 1) ? 'opacitymedium' : '').'">'; + print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 10db3c8d9b1..87261c7f61b 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -2210,6 +2210,7 @@ while ($i < $imaxinloop) { $generic_commande->id = $obj->rowid; $generic_commande->ref = $obj->ref; + $generic_commande->status = $obj->fk_statut; $generic_commande->statut = $obj->fk_statut; $generic_commande->billed = $obj->billed; $generic_commande->date = $db->jdate($obj->date_commande); @@ -2258,7 +2259,7 @@ while ($i < $imaxinloop) { } else { // Show line of result $j = 0; - print ''; + print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 455c1a358b9..1ef606d0160 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -2169,7 +2169,7 @@ if ($num > 0) { } else { // Show line of result $j = 0; - print ' $request_data * @phpstan-param ?array $request_data * @return Object Updated object + * @phan-return Categorie + * @phpstan-return Categorie */ public function put($id, $request_data = null) { @@ -306,6 +312,8 @@ class Categories extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @return array Array of category objects + * @phan-return Categorie[] + * @phpstan-return Categorie[] * * @throws RestException * @@ -360,6 +368,8 @@ class Categories extends DolibarrApi * @param int $object_id ID of object * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * @throws RestException * * @url POST {id}/objects/{type}/{object_id} @@ -441,6 +451,8 @@ class Categories extends DolibarrApi * @param string $object_ref Reference of object * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * @throws RestException * * @url POST {id}/objects/{type}/ref/{object_ref} @@ -522,6 +534,8 @@ class Categories extends DolibarrApi * @param int $object_id ID of the object * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * @throws RestException * * @url DELETE {id}/objects/{type}/{object_id} @@ -601,6 +615,8 @@ class Categories extends DolibarrApi * @param string $object_ref Reference of the object * * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * @throws RestException * * @url DELETE {id}/objects/{type}/ref/{object_ref} diff --git a/htdocs/comm/action/class/api_agendaevents.class.php b/htdocs/comm/action/class/api_agendaevents.class.php index 3f9b20893e8..c89e7b6cb20 100644 --- a/htdocs/comm/action/class/api_agendaevents.class.php +++ b/htdocs/comm/action/class/api_agendaevents.class.php @@ -37,7 +37,7 @@ class AgendaEvents extends DolibarrApi ); /** - * @var ActionComm {@type ActionComm} + * @var ActionComm {@type ActionActionCom} */ public $actioncomm; @@ -104,6 +104,8 @@ class AgendaEvents extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of order objects + * @phan-return ActionComm[]|array{data:ActionComm[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return ActionComm[]|array{data:ActionComm[],pagination:array{total:int,page:int,page_count:int,limit:int}} */ public function index($sortfield = "t.id", $sortorder = 'ASC', $limit = 100, $page = 0, $user_ids = '', $sqlfilters = '', $properties = '', $pagination_data = false) { @@ -197,7 +199,7 @@ class AgendaEvents extends DolibarrApi $obj_ret['pagination'] = [ 'total' => (int) $total, 'page' => $page, //count starts from 0 - 'page_count' => ceil((int) $total / $limit), + 'page_count' => (int) ceil((int) $total / $limit), 'limit' => $limit ]; } @@ -272,7 +274,7 @@ class AgendaEvents extends DolibarrApi if ($result) { $this->actioncomm->fetch_optionals(); $this->actioncomm->fetch_userassigned(); - $this->actioncomm->oldcopy = clone $this->actioncomm; + $this->actioncomm->oldcopy = clone $this->actioncomm; // @phan-suppress-current-line PhanTypeMismatchProperty } if (!$result) { throw new RestException(404, 'actioncomm not found'); @@ -326,7 +328,7 @@ class AgendaEvents extends DolibarrApi if ($result) { $this->actioncomm->fetch_optionals(); $this->actioncomm->fetch_userassigned(); - $this->actioncomm->oldcopy = clone $this->actioncomm; + $this->actioncomm->oldcopy = clone $this->actioncomm; // @phan-suppress-current-line PhanTypeMismatchProperty } if (!DolibarrApiAccess::$user->hasRight('agenda', 'allactions', 'delete') && DolibarrApiAccess::$user->id != $this->actioncomm->userownerid) { diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index 54a017d39b7..1cb3d491737 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -35,7 +35,7 @@ require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; class Proposals extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'socid' @@ -162,6 +162,8 @@ class Proposals extends DolibarrApi * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @param int $loadlinkedobjects Load also linked object * @return array Array of order objects + * @phan-return Propal[]|array{data:Propal[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Propal[]|array{data:Propal[],pagination:array{total:int,page:int,page_count:int,limit:int}} */ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '', $properties = '', $pagination_data = false, $loadlinkedobjects = 0) { diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index 5ebaec4be86..c4890f69f67 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; class Orders extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'socid', @@ -164,6 +164,8 @@ class Orders extends DolibarrApi * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @param int $loadlinkedobjects Load also linked object * @return array Array of order objects + * @phan-return Commande[]|array{data:Commande[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Commande[]|array{data:Commande[],pagination:array{total:int,page:int,page_count:int,limit:int}} * * @throws RestException 404 Not found * @throws RestException 503 Error diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 4da9526ebb2..9a214e95a18 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -34,7 +34,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php'; class Invoices extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'socid', @@ -184,6 +184,8 @@ class Invoices extends DolibarrApi * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0 * @param int $loadlinkedobjects Load also linked object * @return array Array of invoice objects + * @phan-return Facture[]|array{data:Facture[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Facture[]|array{data:Facture[],pagination:array{total:int,page:int,page_count:int,limit:int}} * * @throws RestException 404 Not found * @throws RestException 503 Error diff --git a/htdocs/contrat/class/api_contracts.class.php b/htdocs/contrat/class/api_contracts.class.php index 55771f352bf..d53f60c940b 100644 --- a/htdocs/contrat/class/api_contracts.class.php +++ b/htdocs/contrat/class/api_contracts.class.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; class Contracts extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'socid', @@ -97,6 +97,8 @@ class Contracts extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of order objects + * @phan-return Contrat[]|array{data:Contrat[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Contrat[]|array{data:Contrat[],pagination:array{total:int,page:int,page_count:int,limit:int}} * * @throws RestException 404 Not found * @throws RestException 503 Error diff --git a/htdocs/don/class/api_donations.class.php b/htdocs/don/class/api_donations.class.php index 4570fda0bf5..6b7ad5b0444 100644 --- a/htdocs/don/class/api_donations.class.php +++ b/htdocs/don/class/api_donations.class.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; class Donations extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'amount' @@ -96,6 +96,8 @@ class Donations extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of order objects + * @phan-return Don[]|array{data:Don[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Don[]|array{data:Don[],pagination:array{total:int,page:int,page_count:int,limit:int}} * * @throws RestException */ diff --git a/htdocs/fourn/class/api_supplier_invoices.class.php b/htdocs/fourn/class/api_supplier_invoices.class.php index 4dbb43115be..49fc7e4ce8f 100644 --- a/htdocs/fourn/class/api_supplier_invoices.class.php +++ b/htdocs/fourn/class/api_supplier_invoices.class.php @@ -103,6 +103,8 @@ class SupplierInvoices extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of invoice objects + * @phan-return FactureFournisseur[]|array{data:FactureFournisseur[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return FactureFournisseur[]|array{data:FactureFournisseur[],pagination:array{total:int,page:int,page_count:int,limit:int}} * * @throws RestException */ diff --git a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php index a46e075634b..2b4fc1d20c5 100644 --- a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php +++ b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php @@ -130,6 +130,8 @@ class KnowledgeManagement extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of order objects + * @phan-return KnowledgeRecord[]|array{data:KnowledgeRecord[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return KnowledgeRecord[]|array{data:KnowledgeRecord[],pagination:array{total:int,page:int,page_count:int,limit:int}} * * @throws RestException * diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index ce9d7803292..17b3d31f93c 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -37,7 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination2ValuePair.cla class Products extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'ref', @@ -177,6 +177,8 @@ class Products extends DolibarrApi * @param int $includestockdata Load also information about stock (slower) * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array Array of product objects + * @phan-return Product[]|array{data:Product[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Product[]|array{data:Product[],pagination:array{total:int,page:int,page_count:int,limit:int}} */ public function index($sortfield = "t.ref", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '', $ids_only = false, $variant_filter = 0, $pagination_data = false, $includestockdata = 0, $properties = '') { diff --git a/htdocs/reception/class/api_receptions.class.php b/htdocs/reception/class/api_receptions.class.php index e536919e8aa..68cc80eaa61 100644 --- a/htdocs/reception/class/api_receptions.class.php +++ b/htdocs/reception/class/api_receptions.class.php @@ -98,8 +98,8 @@ class Receptions extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of reception objects - * @phan-return array> - * @phpstan-return array> + * @phan-return Reception[]|array{data:Reception[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Reception[]|array{data:Reception[],pagination:array{total:int,page:int,page_count:int,limit:int}} * * @throws RestException */ diff --git a/htdocs/salaries/class/api_salaries.class.php b/htdocs/salaries/class/api_salaries.class.php index a7227e4ebe6..8470768b1b1 100644 --- a/htdocs/salaries/class/api_salaries.class.php +++ b/htdocs/salaries/class/api_salaries.class.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/salaries/class/paymentsalary.class.php'; class Salaries extends DolibarrApi { /** - * @var array Mandatory fields, checked when creating an object + * @var string[] Mandatory fields, checked when creating an object */ public static $FIELDS = array( 'fk_user', @@ -41,7 +41,7 @@ class Salaries extends DolibarrApi ); /** - * array $FIELDS Mandatory fields, checked when creating an object + * string[] $FIELDS Mandatory fields, checked when creating an object */ public static $FIELDSPAYMENT = array( "paiementtype", diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index bfecfc45047..4517ed911e9 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -32,7 +32,7 @@ use Luracast\Restler\RestException; class Thirdparties extends DolibarrApi { /** - * @var array Mandatory fields, checked when we create and update the object + * @var string[] Mandatory fields, checked when we create and update the object */ public static $FIELDS = array( 'name' @@ -131,6 +131,8 @@ class Thirdparties extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of thirdparty objects + * @phan-return Societe[]|array{data:Societe[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Societe[]|array{data:Societe[],pagination:array{total:int,page:int,page_count:int,limit:int}} */ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '', $properties = '', $pagination_data = false) { diff --git a/htdocs/supplier_proposal/class/api_supplier_proposals.class.php b/htdocs/supplier_proposal/class/api_supplier_proposals.class.php index 0d607880f12..d2fa85fa69d 100644 --- a/htdocs/supplier_proposal/class/api_supplier_proposals.class.php +++ b/htdocs/supplier_proposal/class/api_supplier_proposals.class.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class class SupplierProposals extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'socid' @@ -226,6 +226,8 @@ class SupplierProposals extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of order objects + * @phan-return SupplierProposal[]|array{data:SupplierProposal[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return SupplierProposal[]|array{data:SupplierProposal[],pagination:array{total:int,page:int,page_count:int,limit:int}} */ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '', $properties = '', $pagination_data = false) { diff --git a/htdocs/ticket/class/api_tickets.class.php b/htdocs/ticket/class/api_tickets.class.php index c633ab5085e..da0eb4c4d87 100644 --- a/htdocs/ticket/class/api_tickets.class.php +++ b/htdocs/ticket/class/api_tickets.class.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php'; class Tickets extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'subject', @@ -40,7 +40,7 @@ class Tickets extends DolibarrApi ); /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS_MESSAGES = array( 'track_id', @@ -202,6 +202,8 @@ class Tickets extends DolibarrApi * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * * @return array Array of ticket objects + * @phan-return Ticket[]|array{data:Ticket[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Ticket[]|array{data:Ticket[],pagination:array{total:int,page:int,page_count:int,limit:int}} */ public function index($socid = 0, $sortfield = "t.rowid", $sortorder = "ASC", $limit = 100, $page = 0, $sqlfilters = '', $properties = '', $pagination_data = false) { diff --git a/htdocs/webhook/class/api_webhook.class.php b/htdocs/webhook/class/api_webhook.class.php index e51a73ff463..32474da267c 100644 --- a/htdocs/webhook/class/api_webhook.class.php +++ b/htdocs/webhook/class/api_webhook.class.php @@ -27,7 +27,7 @@ use Luracast\Restler\RestException; class Webhook extends DolibarrApi { /** - * @var array Mandatory fields, checked when we create and update the object + * @var string[] Mandatory fields, checked when we create and update the object */ public static $FIELDS = array( 'url', @@ -80,6 +80,8 @@ class Webhook extends DolibarrApi * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* * @return array Array of target objects + * @phan-return Target[]|array{data:Target[],pagination:array{total:int,page:int,page_count:int,limit:int}} + * @phpstan-return Target[]|array{data:Target[],pagination:array{total:int,page:int,page_count:int,limit:int}} */ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '', $properties = '', $pagination_data = false) { From f625f8de60cbef3ada9285435d59cec43db314d9 Mon Sep 17 00:00:00 2001 From: MDW Date: Mon, 3 Mar 2025 14:23:57 +0100 Subject: [PATCH 37/71] Qual: Fix api phan notices --- dev/tools/phan/baseline.txt | 39 +++------ dev/tools/phan/config.php | 2 +- dev/tools/phan/config_extended.php | 4 +- htdocs/api/class/api.class.php | 12 ++- htdocs/api/class/api_access.class.php | 2 +- .../categories/class/api_categories.class.php | 4 +- .../comm/propal/class/api_proposals.class.php | 4 + htdocs/commande/class/api_orders.class.php | 4 + .../bank/class/api_bankaccounts.class.php | 14 ++- .../facture/class/api_invoices.class.php | 8 +- htdocs/contrat/class/api_contracts.class.php | 6 +- htdocs/core/modules/modSociete.class.php | 4 +- .../class/api_supplier_invoices.class.php | 8 +- .../fourn/class/api_supplier_orders.class.php | 2 +- .../class/api_knowledgemanagement.class.php | 2 +- .../class/api_multicurrencies.class.php | 6 +- .../class/api_partnerships.class.php | 4 +- htdocs/product/class/api_products.class.php | 87 +++++++++++++------ .../stock/class/api_stockmovements.class.php | 6 +- .../stock/class/api_warehouses.class.php | 4 +- htdocs/projet/class/api_tasks.class.php | 18 +++- .../reception/class/api_receptions.class.php | 5 +- htdocs/salaries/class/api_salaries.class.php | 6 +- .../canvas/actions_card_common.class.php | 2 +- .../societe/class/api_thirdparties.class.php | 83 +++++++++++++----- htdocs/societe/class/societe.class.php | 10 +-- htdocs/webhook/class/api_webhook.class.php | 2 + htdocs/zapier/class/api_zapier.class.php | 2 +- 28 files changed, 229 insertions(+), 121 deletions(-) diff --git a/dev/tools/phan/baseline.txt b/dev/tools/phan/baseline.txt index 460a8ca2505..fd67711a514 100644 --- a/dev/tools/phan/baseline.txt +++ b/dev/tools/phan/baseline.txt @@ -9,12 +9,11 @@ */ return [ // # Issue statistics: - // PhanTypeMismatchArgument : 1230+ occurrences + // PhanTypeMismatchArgument : 1200+ occurrences // PhanUndeclaredProperty : 480+ occurrences - // PhanTypeMismatchArgumentNullable : 310+ occurrences - // PhanTypeMismatchProperty : 160+ occurrences + // PhanTypeMismatchArgumentNullable : 300+ occurrences + // PhanTypeMismatchProperty : 150+ occurrences // PhanUndeclaredGlobalVariable : 100+ occurrences - // PhanPluginUnknownArrayMethodReturnType : 60+ occurrences // PhanTypeExpectedObjectPropAccess : 25+ occurrences // PhanTypeInvalidDimOffset : 20+ occurrences // PhanTypeMismatchDimFetch : 20+ occurrences @@ -24,23 +23,22 @@ return [ // PhanTypeMismatchArgumentNullableInternal : 10+ occurrences // PhanPossiblyUndeclaredGlobalVariable : 9 occurrences // PhanUndeclaredMethod : 9 occurrences - // PhanTypeComparisonFromArray : 7 occurrences // PhanPluginDuplicateExpressionBinaryOp : 6 occurrences // PhanTypeArraySuspiciousNull : 6 occurrences + // PhanTypeComparisonFromArray : 6 occurrences // PhanParamTooMany : 4 occurrences // PhanPluginDuplicateArrayKey : 4 occurrences // PhanEmptyFQSENInClasslike : 3 occurrences // PhanInvalidFQSENInClasslike : 3 occurrences // PhanPluginSuspiciousParamPosition : 2 occurrences // PhanTypeMismatchDimAssignment : 2 occurrences + // PhanTypeMismatchReturn : 2 occurrences // PhanTypeSuspiciousStringExpression : 2 occurrences - // PhanAccessMethodProtected : 1 occurrence // PhanPluginBothLiteralsBinaryOp : 1 occurrence // PhanPluginDuplicateExpressionAssignmentOperation : 1 occurrence // PhanPluginUnknownArrayPropertyType : 1 occurrence // PhanPossiblyUndeclaredVariable : 1 occurrence // PhanTypeExpectedObjectPropAccessButGotNull : 1 occurrence - // PhanTypeMismatchReturn : 1 occurrence // Currently, file_suppressions and directory_suppressions are the only supported suppressions 'file_suppressions' => [ @@ -145,14 +143,12 @@ return [ 'htdocs/bookcal/class/availabilities.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'], 'htdocs/bookcal/class/calendar.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'], 'htdocs/bookmarks/card.php' => ['PhanTypeMismatchArgument'], - 'htdocs/categories/class/api_categories.class.php' => ['PhanAccessMethodProtected', 'PhanPluginUnknownArrayMethodReturnType'], 'htdocs/categories/class/categorie.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/categories/photos.php' => ['PhanTypeMismatchArgument'], 'htdocs/categories/viewcat.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/collab/index.php' => ['PhanUndeclaredProperty'], 'htdocs/comm/action/card.php' => ['PhanPluginBothLiteralsBinaryOp', 'PhanTypeMismatchArgument', 'PhanTypeMismatchProperty'], 'htdocs/comm/action/class/actioncomm.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], - 'htdocs/comm/action/class/api_agendaevents.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchProperty'], 'htdocs/comm/action/class/cactioncomm.class.php' => ['PhanPluginUnknownArrayPropertyType'], 'htdocs/comm/action/document.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/action/index.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchDimFetch', 'PhanTypeMismatchProperty'], @@ -169,7 +165,6 @@ return [ 'htdocs/comm/multiprix.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/propal/agenda.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/propal/card.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty'], - 'htdocs/comm/propal/class/api_proposals.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/comm/propal/class/propal.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/comm/propal/class/propaleligne.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/propal/contact.php' => ['PhanTypeMismatchArgument'], @@ -181,7 +176,7 @@ return [ 'htdocs/comm/remise.php' => ['PhanTypeMismatchArgument'], 'htdocs/comm/remx.php' => ['PhanTypeMismatchArgument'], 'htdocs/commande/card.php' => ['PhanTypeMismatchArgument'], - 'htdocs/commande/class/api_orders.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], + 'htdocs/commande/class/api_orders.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/commande/class/commande.class.php' => ['PhanUndeclaredProperty'], 'htdocs/commande/customer.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/commande/list.php' => ['PhanUndeclaredProperty'], @@ -194,7 +189,6 @@ return [ 'htdocs/compta/bank/card.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/bank/categ.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/bank/class/account.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], - 'htdocs/compta/bank/class/api_bankaccounts.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentProbablyReal'], 'htdocs/compta/bank/class/paymentvarious.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/bank/graph.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/bank/line.php' => ['PhanUndeclaredGlobalVariable'], @@ -217,7 +211,7 @@ return [ 'htdocs/compta/facture/agenda.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/facture/card-rec.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty'], 'htdocs/compta/facture/card.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'], - 'htdocs/compta/facture/class/api_invoices.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeComparisonFromArray', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentProbablyReal'], + 'htdocs/compta/facture/class/api_invoices.class.php' => ['PhanTypeMismatchArgumentProbablyReal'], 'htdocs/compta/facture/class/facture-rec.class.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'], 'htdocs/compta/facture/class/facture.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/compta/facture/class/factureligne.class.php' => ['PhanTypeMismatchArgument'], @@ -275,7 +269,6 @@ return [ 'htdocs/contact/list.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/contrat/agenda.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentProbablyReal'], 'htdocs/contrat/card.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredGlobalVariable'], - 'htdocs/contrat/class/api_contracts.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/contrat/class/contrat.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/contrat/class/contratligne.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/contrat/contact.php' => ['PhanTypeMismatchArgument'], @@ -436,7 +429,6 @@ return [ 'htdocs/delivery/class/delivery.class.php' => ['PhanUndeclaredProperty'], 'htdocs/don/admin/donation.php' => ['PhanUndeclaredMethod'], 'htdocs/don/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/don/class/api_donations.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/don/class/don.class.php' => ['PhanParamTooMany'], 'htdocs/don/document.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/don/info.php' => ['PhanUndeclaredGlobalVariable'], @@ -490,7 +482,6 @@ return [ 'htdocs/fichinter/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/filefunc.inc.php' => ['PhanPluginUndeclaredVariableIsset', 'PhanPossiblyUndeclaredGlobalVariable', 'PhanUndeclaredGlobalVariable'], 'htdocs/fourn/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/fourn/class/api_supplier_invoices.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/fourn/class/api_supplier_orders.class.php' => ['PhanTypeMismatchArgumentProbablyReal'], 'htdocs/fourn/class/fournisseur.commande.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/fourn/class/fournisseur.facture-rec.class.php' => ['PhanTypeMismatchArgument'], @@ -522,7 +513,6 @@ return [ 'htdocs/hrm/skill_card.php' => ['PhanTypeExpectedObjectPropAccess', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], 'htdocs/imports/import.php' => ['PhanTypeMismatchArgument'], 'htdocs/intracommreport/card.php' => ['PhanUndeclaredGlobalVariable'], - 'htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/knowledgemanagement/class/knowledgerecord.class.php' => ['PhanUndeclaredProperty'], 'htdocs/knowledgemanagement/knowledgerecord_card.php' => ['PhanTypeMismatchArgument'], 'htdocs/loan/class/paymentloan.class.php' => ['PhanTypeMismatchArgument'], @@ -532,17 +522,16 @@ return [ 'htdocs/mrp/class/mo.class.php' => ['PhanTypeMismatchProperty'], 'htdocs/mrp/mo_movements.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/mrp/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'], - 'htdocs/multicurrency/class/api_multicurrencies.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], + 'htdocs/multicurrency/class/api_multicurrencies.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/multicurrency/class/multicurrency.class.php' => ['PhanTypeExpectedObjectPropAccess'], 'htdocs/multicurrency/multicurrency_rate.php' => ['PhanTypeMismatchArgument'], 'htdocs/opensurvey/results.php' => ['PhanUndeclaredGlobalVariable'], - 'htdocs/partnership/class/api_partnerships.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/partnership/class/partnership.class.php' => ['PhanUndeclaredProperty'], 'htdocs/partnership/core/modules/partnership/mod_partnership_advanced.php' => ['PhanUndeclaredProperty'], 'htdocs/partnership/partnership_card.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/partnership/partnership_list.php' => ['PhanUndeclaredProperty'], 'htdocs/product/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/product/class/api_products.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument', 'PhanUndeclaredProperty'], + 'htdocs/product/class/api_products.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchReturn', 'PhanUndeclaredProperty'], 'htdocs/product/class/html.formproduct.class.php' => ['PhanUndeclaredProperty'], 'htdocs/product/class/productfournisseurprice.class.php' => ['PhanUndeclaredMethod', 'PhanUndeclaredProperty'], 'htdocs/product/inventory/class/inventory.class.php' => ['PhanUndeclaredProperty'], @@ -550,8 +539,6 @@ return [ 'htdocs/product/price_suppliers.php' => ['PhanTypeMismatchProperty'], 'htdocs/product/reassort.php' => ['PhanTypeExpectedObjectPropAccessButGotNull'], 'htdocs/product/stock/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/product/stock/class/api_stockmovements.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], - 'htdocs/product/stock/class/api_warehouses.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/product/stock/info.php' => ['PhanUndeclaredProperty'], 'htdocs/product/stock/list.php' => ['PhanUndeclaredProperty'], 'htdocs/product/stock/movement_card.php' => ['PhanPluginUndeclaredVariableIsset', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], @@ -567,7 +554,6 @@ return [ 'htdocs/product/stock/tpl/stocktransfer.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/projet/admin/project.php' => ['PhanTypeMismatchArgumentProbablyReal'], 'htdocs/projet/card.php' => ['PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty', 'PhanUndeclaredGlobalVariable'], - 'htdocs/projet/class/api_tasks.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument'], 'htdocs/projet/tasks.php' => ['PhanTypeMismatchArgument'], 'htdocs/projet/tasks/time.php' => ['PhanTypeInvalidDimOffset', 'PhanTypeMismatchArgument', 'PhanUndeclaredProperty'], 'htdocs/projet/tasks/tpl/linkedobjectblock.tpl.php' => ['PhanUndeclaredProperty'], @@ -582,7 +568,6 @@ return [ 'htdocs/public/recruitment/view.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/public/webportal/tpl/menu.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/reception/card.php' => ['PhanTypeMismatchProperty', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], - 'htdocs/reception/class/api_receptions.class.php' => ['PhanTypeMismatchArgumentNullable'], 'htdocs/reception/class/reception.class.php' => ['PhanUndeclaredProperty'], 'htdocs/reception/list.php' => ['PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/recruitment/class/recruitmentcandidature.class.php' => ['PhanUndeclaredProperty'], @@ -597,24 +582,21 @@ return [ 'htdocs/recruitment/recruitmentjobposition_card.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], 'htdocs/recruitment/recruitmentjobposition_document.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], 'htdocs/recruitment/recruitmentjobposition_note.php' => ['PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], - 'htdocs/salaries/class/api_salaries.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/salaries/paiement_salary.php' => ['PhanUndeclaredProperty'], 'htdocs/salaries/virement_request.php' => ['PhanUndeclaredProperty'], 'htdocs/societe/ajax/company.php' => ['PhanUndeclaredProperty'], 'htdocs/societe/card.php' => ['PhanTypeMismatchProperty'], - 'htdocs/societe/class/api_thirdparties.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchArgumentProbablyReal', 'PhanTypeMismatchProperty'], 'htdocs/societe/class/societe.class.php' => ['PhanTypeMismatchProperty'], 'htdocs/societe/paymentmodes.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchArgument'], 'htdocs/stripe/class/stripe.class.php' => ['PhanTypeExpectedObjectPropAccess'], 'htdocs/supplier_proposal/card.php' => ['PhanTypeMismatchProperty', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], - 'htdocs/supplier_proposal/class/api_supplier_proposals.class.php' => ['PhanPluginUnknownArrayMethodReturnType', 'PhanUndeclaredProperty'], + 'htdocs/supplier_proposal/class/api_supplier_proposals.class.php' => ['PhanUndeclaredProperty'], 'htdocs/supplier_proposal/class/supplier_proposal.class.php' => ['PhanUndeclaredProperty'], 'htdocs/takepos/index.php' => ['PhanPluginUndeclaredVariableIsset'], 'htdocs/takepos/invoice.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanUndeclaredGlobalVariable'], 'htdocs/takepos/split.php' => ['PhanPluginUndeclaredVariableIsset'], 'htdocs/ticket/card.php' => ['PhanUndeclaredProperty'], 'htdocs/ticket/class/actions_ticket.class.php' => ['PhanUndeclaredProperty'], - 'htdocs/ticket/class/api_tickets.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/ticket/class/cticketcategory.class.php' => ['PhanUndeclaredProperty'], 'htdocs/ticket/class/ticket.class.php' => ['PhanUndeclaredProperty'], 'htdocs/ticket/contact.php' => ['PhanTypeMismatchArgument'], @@ -623,7 +605,6 @@ return [ 'htdocs/variants/tpl/productattributevalueline_edit.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/variants/tpl/productattributevalueline_view.tpl.php' => ['PhanUndeclaredProperty'], 'htdocs/viewimage.php' => ['PhanUndeclaredMethod'], - 'htdocs/webhook/class/api_webhook.class.php' => ['PhanPluginUnknownArrayMethodReturnType'], 'htdocs/webhook/class/target.class.php' => ['PhanUndeclaredMethod'], 'htdocs/webhook/target_card.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/webportal/admin/setup.php' => ['PhanTypeMismatchArgument'], diff --git a/dev/tools/phan/config.php b/dev/tools/phan/config.php index d45a1e422c0..2b371b1d984 100644 --- a/dev/tools/phan/config.php +++ b/dev/tools/phan/config.php @@ -462,7 +462,7 @@ return [ 'PhanPluginUnknownClosureReturnType', // When we use closure (we must avoid), we do not have PHP doc // 'PhanPluginUnknownArrayMethodParamType', // All fixed - // 'PhanPluginUnknownArrayMethodReturnType', // All fixed, except in api_* + // 'PhanPluginUnknownArrayMethodReturnType', // All fixed // 'PhanUndeclaredGlobalVariable', // Helps identify variables that are not set/defined - add '@phan-var-force TYPE $varname' in tpl or includes to help type the variable // 'PhanPluginUnknownObjectMethodCall', // False positive for some class. Is enabled in config_extended only. 'PhanTypeSuspiciousNonTraversableForeach', // Reports on `foreach ($object as $key => $value)` which works without php notices, so we ignore it because this is intentional in the code. diff --git a/dev/tools/phan/config_extended.php b/dev/tools/phan/config_extended.php index fa84a395df7..c42693162df 100644 --- a/dev/tools/phan/config_extended.php +++ b/dev/tools/phan/config_extended.php @@ -87,7 +87,7 @@ $config['suppress_issue_types'] = [ 'PhanPluginNonBoolBranch', // Not essential - 31240+ occurrences 'PhanPluginNumericalComparison', // Not essential - 19870+ occurrences - 'PhanTypeMismatchArgument', // Not showing in cti.dolibarr until low count - Can detect missing array keys, invalid types, objects being passed when scalar expected - Not all reported by phpstan - <=3800 cases (was: 12300+ before) + 'PhanTypeMismatchArgument', // Not showing in cti.dolibarr until low count - Can detect missing array keys, invalid types, objects being passed when scalar expected - Not all reported by phpstan - <=1200 cases (was: 12300+ before) 'PhanPluginNonBoolInLogicalArith', // Not essential - 11040+ occurrences 'PhanPluginConstantVariableScalar', // Not essential - 5180+ occurrences 'PhanPluginDuplicateAdjacentStatement', @@ -98,7 +98,7 @@ $config['suppress_issue_types'] = [ 'PhanPluginDuplicateCatchStatementBody', // Requires PHP7.1 - 50+ occurrences // 'PhanPluginUnknownArrayMethodParamType', // All fixed - 'PhanPluginUnknownArrayMethodReturnType', // All fixed, except in api_* at this time + // 'PhanPluginUnknownArrayMethodReturnType', // All fixed 'PhanTypeSuspiciousNonTraversableForeach', // Reports on `foreach ($object as $key => $value)` which works without php notices, so we ignore it because this is intentional in the code. ]; diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index ceae1f08b0c..d707562f3b8 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -2,7 +2,7 @@ /* Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016 Laurent Destailleur * Copyright (C) 2020-2025 Frédéric France - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 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 @@ -29,12 +29,12 @@ require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; class DolibarrApi { /** - * @var DoliDB $db Database object + * @var DoliDB Database object */ protected $db; /** - * @var Restler $r Restler object + * @var Restler Restler object */ public $r; @@ -129,9 +129,13 @@ class DolibarrApi /** * Filter properties that will be returned on object * + * @phpstan-template T of Object + * * @param Object $object Object to clean - * @param String $properties Comma separated list of properties names + * @param string $properties Comma separated list of properties names * @return Object Object with cleaned properties + * @phpstan-param T $object + * @phpstan-return T */ protected function _filterObjectProperties($object, $properties) { diff --git a/htdocs/api/class/api_access.class.php b/htdocs/api/class/api_access.class.php index 304a2b690c5..c7c92f9514d 100644 --- a/htdocs/api/class/api_access.class.php +++ b/htdocs/api/class/api_access.class.php @@ -55,7 +55,7 @@ class DolibarrApiAccess implements iAuthenticate public $db; /** - * @var array role required by API method user / external / admin + * @var string[] role required by API method user / external / admin */ public static $requires = array('user', 'external', 'admin'); diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index 2e8605e205f..47b792a1121 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -312,8 +312,8 @@ class Categories extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @return array Array of category objects - * @phan-return Categorie[] - * @phpstan-return Categorie[] + * @phan-return array,visible:int,ref_ext:string,multilangs?:array}> + * @phpstan-return array,visible:int,ref_ext:string,multilangs?:array}> * * @throws RestException * diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index 1cb3d491737..419e13369ab 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -317,6 +317,8 @@ class Proposals extends DolibarrApi * @url GET {id}/lines * * @return array + * @phan-return PropaleLigne[] + * @phpstan-return PropaleLigne[] */ public function getLines($id, $sqlfilters = '') { @@ -622,6 +624,8 @@ class Proposals extends DolibarrApi * @param string $type Type of the external contact (BILLING, SHIPPING, CUSTOMER), internal contact (SALESREPFOLL) * @param string $source Source of the contact (internal, external) * @return array + * @phan-return array{success:array{code:int,message:string}} + * @phpstan-return array{success:array{code:int,message:string}} * * @url POST {id}/contact/{contactid}/{type}/{source} * diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index c4890f69f67..69f467d2b51 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -338,6 +338,8 @@ class Orders extends DolibarrApi * @url GET {id}/lines * * @return array + * @phan-return OrderLine[] + * @phpstan-return OrderLine[] */ public function getLines($id) { @@ -1037,6 +1039,8 @@ class Orders extends DolibarrApi * @url GET {id}/shipment * * @return array + * @phan-return Expedition[] + * @phpstan-return Expedition[] * * @throws RestException 401 * @throws RestException 404 diff --git a/htdocs/compta/bank/class/api_bankaccounts.class.php b/htdocs/compta/bank/class/api_bankaccounts.class.php index e86deabfe43..125150dd63c 100644 --- a/htdocs/compta/bank/class/api_bankaccounts.class.php +++ b/htdocs/compta/bank/class/api_bankaccounts.class.php @@ -62,6 +62,8 @@ class BankAccounts extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.import_key:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array List of account objects + * @phan-return Account[] + * @phpstan-return Account[] * * @throws RestException */ @@ -271,14 +273,14 @@ class BankAccounts extends DolibarrApi */ if (!$error) { - $bank_line_id_from = $accountfrom->addline($date, $typefrom, $description, -1 * (float) price2num($amount), '', '', $user, $cheque_number); + $bank_line_id_from = $accountfrom->addline((int) $date, $typefrom, $description, -1 * (float) price2num($amount), '', 0, $user, $cheque_number); } if (!($bank_line_id_from > 0)) { $error++; } if (!$error) { - $bank_line_id_to = $accountto->addline($date, $typeto, $description, price2num($amount_to), '', '', $user, $cheque_number); + $bank_line_id_to = $accountto->addline((int) $date, $typeto, $description, (float) price2num($amount_to), '', 0, $user, $cheque_number); } if (!($bank_line_id_to > 0)) { $error++; @@ -446,6 +448,8 @@ class BankAccounts extends DolibarrApi * * @param int $id ID of account * @return array Array of AccountLine objects + * @phan-return AccountLine[] + * @phpstan-return AccountLine[] * * @throws RestException * @@ -538,7 +542,7 @@ class BankAccounts extends DolibarrApi $num_releve = sanitizeVal($num_releve); $result = $account->addline( - $date, + (int) $date, $type, $label, $amount, @@ -548,7 +552,7 @@ class BankAccounts extends DolibarrApi $cheque_writer, $cheque_bank, $accountancycode, - $datev, + (int) $datev, $num_releve ); if ($result < 0) { @@ -605,6 +609,8 @@ class BankAccounts extends DolibarrApi * @param int $id ID of account * @param int $line_id ID of account line * @return array Array of links + * @phan-return array + * @phpstan-return array * * @throws RestException * diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 9a214e95a18..bc10b732054 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -448,6 +448,8 @@ class Invoices extends DolibarrApi * * @param int $id Id of invoice * @return array Array of lines + * @phan-return CommonInvoiceLine[] + * @phpstan-return CommonInvoiceLine[] * * @url GET {id}/lines */ @@ -1448,6 +1450,8 @@ class Invoices extends DolibarrApi * * @param int $id Id of invoice * @return array + * @phan-return array + * @phpstan-return array * * @url GET {id}/payments * @@ -1475,7 +1479,7 @@ class Invoices extends DolibarrApi } $result = $this->invoice->getListOfPayments(); - if ($result < 0) { + if (!is_array($result) && $result < 0) { throw new RestException(405, $this->invoice->error); } @@ -1662,7 +1666,7 @@ class Invoices extends DolibarrApi // Loop on each invoice to pay foreach ($arrayofamounts as $id => $amountarray) { - $result = $this->invoice->fetch($id); + $result = $this->invoice->fetch((int) $id); if (!$result) { $this->db->rollback(); throw new RestException(404, 'Invoice ID '.$id.' not found'); diff --git a/htdocs/contrat/class/api_contracts.class.php b/htdocs/contrat/class/api_contracts.class.php index d53f60c940b..674cb399081 100644 --- a/htdocs/contrat/class/api_contracts.class.php +++ b/htdocs/contrat/class/api_contracts.class.php @@ -244,6 +244,8 @@ class Contracts extends DolibarrApi * @url GET {id}/lines * * @return array + * @phan-return ContratLigne[] + * @phpstan-return ContratLigne[] */ public function getLines($id) { @@ -417,7 +419,7 @@ class Contracts extends DolibarrApi throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - $updateRes = $this->contract->active_line(DolibarrApiAccess::$user, $lineid, $datestart, $dateend, $comment); + $updateRes = $this->contract->active_line(DolibarrApiAccess::$user, $lineid, (int) $datestart, $dateend, $comment); if ($updateRes > 0) { $result = $this->get($id); @@ -455,7 +457,7 @@ class Contracts extends DolibarrApi throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - $updateRes = $this->contract->close_line(DolibarrApiAccess::$user, $lineid, $datestart, $comment); + $updateRes = $this->contract->close_line(DolibarrApiAccess::$user, $lineid, (int) $datestart, $comment); if ($updateRes > 0) { $result = $this->get($id); diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index 47652e94d1d..45799c1ff6e 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -6,7 +6,7 @@ * Copyright (C) 2005-2013 Regis Houssin * Copyright (C) 2012-2014 Juanjo Menent * Copyright (C) 2022 Ferran Marcet - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -983,7 +983,7 @@ class modSociete extends DolibarrModules 'sr.datec' => 'date used for creating direct debit UMR formatted as '.dol_print_date( dol_now(), '%Y-%m-%d' - ), + ), 'sr.bank' => 'bank name eg: "ING-Direct"', 'sr.code_banque' => 'account sort code (GB)/Routing number (US) eg. "8456"', 'sr.code_guichet' => "bank code for office/branch", diff --git a/htdocs/fourn/class/api_supplier_invoices.class.php b/htdocs/fourn/class/api_supplier_invoices.class.php index 49fc7e4ce8f..080805676cc 100644 --- a/htdocs/fourn/class/api_supplier_invoices.class.php +++ b/htdocs/fourn/class/api_supplier_invoices.class.php @@ -408,6 +408,8 @@ class SupplierInvoices extends DolibarrApi * @url GET {id}/payments * * @return array + * @phan-return array + * @phpstan-return array * @throws RestException 400 * @throws RestException 403 * @throws RestException 404 @@ -550,6 +552,8 @@ class SupplierInvoices extends DolibarrApi * @url GET {id}/lines * * @return array + * @phan-return CommonInvoiceLine[] + * @phpstan-return CommonInvoiceLine[] * * @throws RestException 403 * @throws RestException 404 @@ -631,7 +635,7 @@ class SupplierInvoices extends DolibarrApi $request_data->price_base_type ? $request_data->price_base_type : 'HT', $request_data->product_type, $request_data->rang, - false, + 0, $request_data->array_options, $request_data->fk_unit, $request_data->origin_id, @@ -697,7 +701,7 @@ class SupplierInvoices extends DolibarrApi $request_data->info_bits, $request_data->product_type, $request_data->remise_percent, - false, + 0, $request_data->date_start, $request_data->date_end, $request_data->array_options, diff --git a/htdocs/fourn/class/api_supplier_orders.class.php b/htdocs/fourn/class/api_supplier_orders.class.php index 06bf957bf1f..b77c5c28e7c 100644 --- a/htdocs/fourn/class/api_supplier_orders.class.php +++ b/htdocs/fourn/class/api_supplier_orders.class.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; class SupplierOrders extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'socid' diff --git a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php index 2b4fc1d20c5..1f789d19b54 100644 --- a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php +++ b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php @@ -330,7 +330,7 @@ class KnowledgeManagement extends DolibarrApi // Clean data // $this->knowledgerecord->abc = sanitizeVal($this->knowledgerecord->abc, 'alphanohtml'); - if ($this->knowledgerecord->update(DolibarrApiAccess::$user, false) > 0) { + if ($this->knowledgerecord->update(DolibarrApiAccess::$user, 0) > 0) { return $this->get($id); } else { throw new RestException(500, $this->knowledgerecord->error); diff --git a/htdocs/multicurrency/class/api_multicurrencies.class.php b/htdocs/multicurrency/class/api_multicurrencies.class.php index c9437431d10..03c1df80d15 100644 --- a/htdocs/multicurrency/class/api_multicurrencies.class.php +++ b/htdocs/multicurrency/class/api_multicurrencies.class.php @@ -51,6 +51,8 @@ class MultiCurrencies extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.product_id:=:1) and (t.date_creation:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array Array of warehouse objects + * @phan-return MultiCurrency[] + * @phpstan-return MultiCurrency[] * * @throws RestException */ @@ -234,7 +236,7 @@ class MultiCurrencies extends DolibarrApi // Add default rate if defined if (isset($request_data['rate']) && $request_data['rate'] > 0) { - if ($multicurrency->addRate($request_data['rate']) < 0) { + if ($multicurrency->addRate((float) $request_data['rate']) < 0) { throw new RestException(500, "Error adding currency rate", array_merge(array($multicurrency->error), $multicurrency->errors)); } @@ -349,7 +351,7 @@ class MultiCurrencies extends DolibarrApi } // Add rate - if ($multicurrency->addRate($request_data['rate']) < 0) { + if ($multicurrency->addRate((float) $request_data['rate']) < 0) { throw new RestException(500, "Error updating currency rate", array_merge(array($multicurrency->error), $multicurrency->errors)); } diff --git a/htdocs/partnership/class/api_partnerships.class.php b/htdocs/partnership/class/api_partnerships.class.php index 6be059f25f9..34078bf00a6 100644 --- a/htdocs/partnership/class/api_partnerships.class.php +++ b/htdocs/partnership/class/api_partnerships.class.php @@ -97,6 +97,8 @@ class Partnerships extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array Array of order objects + * @phan-return Partnership[] + * @phpstan-return Partnership[] * * @throws RestException * @@ -266,7 +268,7 @@ class Partnerships extends DolibarrApi // Clean data // $this->partnership->abc = sanitizeVal($this->partnership->abc, 'alphanohtml'); - if ($this->partnership->update(DolibarrApiAccess::$user, false) > 0) { + if ($this->partnership->update(DolibarrApiAccess::$user, 0) > 0) { return $this->get($id); } else { throw new RestException(500, $this->partnership->error); diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 17b3d31f93c..746ad2d6a24 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -566,6 +566,8 @@ class Products extends DolibarrApi * * @param int $id Id of parent product/service * @return array + * @phan-return array + * @phpstan-return array * * @throws RestException * @throws RestException 401 @@ -766,9 +768,9 @@ class Products extends DolibarrApi require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php'; $prodcustprice = new ProductCustomerPrice($this->db); $filter = array(); - $filter['t.fk_product'] = $id; + $filter['t.fk_product'] = (string) $id; if ($thirdparty_id) { - $filter['t.fk_soc'] = $thirdparty_id; + $filter['t.fk_soc'] = (string) $thirdparty_id; } $result = $prodcustprice->fetchAll('', '', 0, 0, $filter); } @@ -942,6 +944,8 @@ class Products extends DolibarrApi * @param int $supplier Use this param to filter list by supplier * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.tobuy:=:0) and (t.tosell:=:1)" * @return array Array of product objects + * @phan-return array + * @phpstan-return array * * @url GET purchase_prices */ @@ -1045,7 +1049,9 @@ class Products extends DolibarrApi * @param string $ref Ref of element * @param string $ref_ext Ref ext of element * @param string $barcode Barcode of element - * @return array|mixed Data without useless information + * @return array Data without useless information + * @phan-return ProductFournisseur[] + * @phpstan-return ProductFournisseur[] * * @url GET {id}/purchase_prices * @@ -1100,6 +1106,8 @@ class Products extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:color)" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array + * @phan-return ProductAttribute[] + * @phpstan-return ProductAttribute[] * * @throws RestException 401 * @throws RestException 404 @@ -1206,6 +1214,8 @@ class Products extends DolibarrApi * * @param string $ref Reference of Attribute * @return array + * @phan-return array{id:int,ref:string,ref_ext:string,label:string,rang:int,position:int,entity:string,is_used_by_products:int} + * @phpstan-return array{id:int,ref:string,ref_ext:string,label:string,rang:int,position:int,entity:string,is_used_by_products:int} * * @throws RestException 401 * @throws RestException 404 @@ -1231,13 +1241,13 @@ class Products extends DolibarrApi $result = $this->db->fetch_object($query); $attr = array(); - $attr['id'] = $result->rowid; - $attr['ref'] = $result->ref; - $attr['ref_ext'] = $result->ref_ext; - $attr['label'] = $result->label; - $attr['rang'] = $result->position; - $attr['position'] = $result->position; - $attr['entity'] = $result->entity; + $attr['id'] = (int) $result->rowid; + $attr['ref'] = (string) $result->ref; + $attr['ref_ext'] = (string) $result->ref_ext; + $attr['label'] = (string) $result->label; + $attr['rang'] = (int) $result->position; + $attr['position'] = (int) $result->position; + $attr['entity'] = (string) $result->entity; $sql = "SELECT COUNT(*) as nb FROM ".$this->db->prefix()."product_attribute_combination2val as pac2v"; $sql .= " JOIN ".$this->db->prefix()."product_attribute_combination as pac ON pac2v.fk_prod_combination = pac.rowid"; @@ -1256,6 +1266,8 @@ class Products extends DolibarrApi * * @param string $ref_ext External reference of Attribute * @return array + * @phan-return array{id:int,ref:string,ref_ext:string,label:string,rang:int,position:int,entity:string,is_used_by_products:int} + * @phpstan-return array{id:int,ref:string,ref_ext:string,label:string,rang:int,position:int,entity:string,is_used_by_products:int} * * @throws RestException 500 System error * @throws RestException 401 @@ -1281,13 +1293,13 @@ class Products extends DolibarrApi $result = $this->db->fetch_object($query); $attr = array(); - $attr['id'] = $result->rowid; - $attr['ref'] = $result->ref; - $attr['ref_ext'] = $result->ref_ext; - $attr['label'] = $result->label; - $attr['rang'] = $result->position; - $attr['position'] = $result->position; - $attr['entity'] = $result->entity; + $attr['id'] = (int) $result->rowid; + $attr['ref'] = (string) $result->ref; + $attr['ref_ext'] = (string) $result->ref_ext; + $attr['label'] = (string) $result->label; + $attr['rang'] = (int) $result->position; + $attr['position'] = (int) $result->position; + $attr['entity'] = (string) $result->entity; $sql = "SELECT COUNT(*) as nb FROM ".$this->db->prefix()."product_attribute_combination2val as pac2v"; $sql .= " JOIN ".$this->db->prefix()."product_attribute_combination as pac ON pac2v.fk_prod_combination = pac.rowid"; @@ -1422,6 +1434,8 @@ class Products extends DolibarrApi * * @param int $id ID of Attribute value * @return array + * @phan-return array{id:int,fk_product_attribute:int,ref:string,value:string} + * @phpstan-return array{id:int,fk_product_attribute:int,ref:string,value:string} * * @throws RestException 500 System error * @throws RestException 401 @@ -1449,8 +1463,8 @@ class Products extends DolibarrApi $result = $this->db->fetch_object($query); $attrval = array(); - $attrval['id'] = $result->rowid; - $attrval['fk_product_attribute'] = $result->fk_product_attribute; + $attrval['id'] = (int) $result->rowid; + $attrval['fk_product_attribute'] = (int) $result->fk_product_attribute; $attrval['ref'] = $result->ref; $attrval['value'] = $result->value; @@ -1463,6 +1477,8 @@ class Products extends DolibarrApi * @param int $id ID of Attribute value * @param string $ref Ref of Attribute value * @return array + * @phan-return array{id:int,fk_product_attribute:int,ref:string,value:string} + * @phpstan-return array{id:int,fk_product_attribute:int,ref:string,value:string} * * @throws RestException 500 System error * @throws RestException 401 @@ -1493,11 +1509,10 @@ class Products extends DolibarrApi $result = $this->db->fetch_object($query); $attrval = array(); - $attrval['id'] = $result->rowid; - $attrval['fk_product_attribute'] = $result->fk_product_attribute; + $attrval['id'] = (int) $result->rowid; + $attrval['fk_product_attribute'] = (int) $result->fk_product_attribute; $attrval['ref'] = $result->ref; $attrval['value'] = $result->value; - return $attrval; } @@ -1549,6 +1564,8 @@ class Products extends DolibarrApi * * @param int $id ID of an Attribute * @return array + * @phan-return ProductAttributeValue[] + * @phpstan-return ProductAttributeValue[] * * @throws RestException 401 * @throws RestException 500 System error @@ -1581,6 +1598,8 @@ class Products extends DolibarrApi * * @param string $ref Ref of an Attribute * @return array + * @phan-return ProductAttributeValue[] + * @phpstan-return ProductAttributeValue[] * * @throws RestException 401 * @@ -1736,6 +1755,8 @@ class Products extends DolibarrApi * @param int $id ID of Product * @param int $includestock Default value 0. If parameter is set to 1 the response will contain stock data of each variant * @return array + * @phan-return ProductCombination[] + * @phpstan-return ProductCombination[] * * @throws RestException 500 System error * @throws RestException 401 @@ -1759,7 +1780,7 @@ class Products extends DolibarrApi if (!empty($includestock) && DolibarrApiAccess::$user->hasRight('stock', 'lire')) { $productModel = new Product($this->db); $productModel->fetch((int) $combination->fk_product_child); - $productModel->load_stock($includestock); + $productModel->load_stock((string) $includestock); $combinations[$key]->stock_warehouse = $this->_cleanObjectDatas($productModel)->stock_warehouse; } } @@ -1772,6 +1793,8 @@ class Products extends DolibarrApi * * @param string $ref Ref of Product * @return array + * @phan-return ProductCombination[] + * @phpstan-return ProductCombination[] * * @throws RestException 500 System error * @throws RestException 401 @@ -1842,6 +1865,7 @@ class Products extends DolibarrApi $prodattr = new ProductAttribute($this->db); $prodattr_val = new ProductAttributeValue($this->db); + $cleanedFeatures = array(); foreach ($features as $id_attr => $id_value) { if ($prodattr->fetch((int) $id_attr) < 0) { throw new RestException(400, 'Invalid attribute ID: '.$id_attr); @@ -1849,6 +1873,7 @@ class Products extends DolibarrApi if ($prodattr_val->fetch((int) $id_value) < 0) { throw new RestException(400, 'Invalid attribute value ID: '.$id_value); } + $cleanedFeatures[(int) $id_attr] = (int) $id_value; } $result = $this->product->fetch((int) $id); @@ -1858,7 +1883,7 @@ class Products extends DolibarrApi $prodcomb = new ProductCombination($this->db); - $result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $features, array(), $price_impact_is_percent, $price_impact, $weight_impact, $reference, $ref_ext); + $result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $cleanedFeatures, array(), $price_impact_is_percent, (is_numeric($price_impact) ? (float) $price_impact : false), (is_numeric($weight_impact) ? (float) $weight_impact : false), $reference, $ref_ext); if ($result > 0) { return $result; } else { @@ -1901,6 +1926,7 @@ class Products extends DolibarrApi $prodattr = new ProductAttribute($this->db); $prodattr_val = new ProductAttributeValue($this->db); + $cleanedFeatures = []; foreach ($features as $id_attr => $id_value) { if ($prodattr->fetch((int) $id_attr) < 0) { throw new RestException(404); @@ -1908,6 +1934,7 @@ class Products extends DolibarrApi if ($prodattr_val->fetch((int) $id_value) < 0) { throw new RestException(404); } + $cleanedFeatures[(int) $id_attr] = (int) $id_value; } $result = $this->product->fetch(0, trim($ref)); @@ -1916,8 +1943,8 @@ class Products extends DolibarrApi } $prodcomb = new ProductCombination($this->db); - if (!$prodcomb->fetchByProductCombination2ValuePairs($this->product->id, $features)) { - $result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $features, array(), $price_impact_is_percent, $price_impact, $weight_impact); + if (!$prodcomb->fetchByProductCombination2ValuePairs($this->product->id, $cleanedFeatures)) { + $result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $cleanedFeatures, array(), $price_impact_is_percent, (is_numeric($price_impact) ? (float) $price_impact : false), (is_numeric($weight_impact) ? (float) $weight_impact : false)); if ($result > 0) { return $result; } else { @@ -2042,10 +2069,14 @@ class Products extends DolibarrApi // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore /** - * Clean sensible object datas + * Clean sensitive object data + * @phpstan-template T of Object * * @param Object $object Object to clean * @return Object Object with cleaned properties + * + * @phpstan-param T $object + * @phpstan-return T */ protected function _cleanObjectDatas($object) { @@ -2170,7 +2201,7 @@ class Products extends DolibarrApi } if (!empty($includestockdata) && DolibarrApiAccess::$user->hasRight('stock', 'lire')) { - $this->product->load_stock($includestockdata); + $this->product->load_stock((string) $includestockdata); if (is_array($this->product->stock_warehouse)) { foreach ($this->product->stock_warehouse as $keytmp => $valtmp) { diff --git a/htdocs/product/stock/class/api_stockmovements.class.php b/htdocs/product/stock/class/api_stockmovements.class.php index 2a51192218b..7d611017be6 100644 --- a/htdocs/product/stock/class/api_stockmovements.class.php +++ b/htdocs/product/stock/class/api_stockmovements.class.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; class StockMovements extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'product_id', @@ -92,6 +92,8 @@ class StockMovements extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.product_id:=:1) and (t.date_creation:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array Array of warehouse objects + * @phan-return MouvementStock[] + * @phpstan-return MouvementStock[] * * @throws RestException */ @@ -198,7 +200,7 @@ class StockMovements extends DolibarrApi $dateMvt = empty($datem) ? '' : dol_stringtotime($datem); $this->stockmovement->setOrigin($origin_type, $origin_id); - if ($this->stockmovement->_create(DolibarrApiAccess::$user, $product_id, $warehouse_id, $qty, $type, $price, $movementlabel, $movementcode, $dateMvt, $eatBy, $sellBy, $lot) <= 0) { + if ($this->stockmovement->_create(DolibarrApiAccess::$user, $product_id, $warehouse_id, $qty, $type, (float) $price, $movementlabel, $movementcode, $dateMvt, $eatBy, $sellBy, $lot) <= 0) { $errormessage = $this->stockmovement->error; if (empty($errormessage)) { $errormessage = implode(',', $this->stockmovement->errors); diff --git a/htdocs/product/stock/class/api_warehouses.class.php b/htdocs/product/stock/class/api_warehouses.class.php index c4fd8472e5f..6c7c8011298 100644 --- a/htdocs/product/stock/class/api_warehouses.class.php +++ b/htdocs/product/stock/class/api_warehouses.class.php @@ -30,7 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; class Warehouses extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'label', @@ -92,6 +92,8 @@ class Warehouses extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'WH-%') and (t.date_creation:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array Array of warehouse objects + * @phan-return Entrepot[] + * @phpstan-return Entrepot[] * * @throws RestException */ diff --git a/htdocs/projet/class/api_tasks.class.php b/htdocs/projet/class/api_tasks.class.php index 774cebd33d4..85710483550 100644 --- a/htdocs/projet/class/api_tasks.class.php +++ b/htdocs/projet/class/api_tasks.class.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; class Tasks extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'ref', @@ -106,6 +106,8 @@ class Tasks extends DolibarrApi * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names * @return array Array of project objects + * @phan-return Task[] + * @phpstan-return Task[] */ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '', $properties = '') { @@ -132,7 +134,7 @@ class Tasks extends DolibarrApi $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet AS p ON p.rowid = t.fk_projet"; $sql .= ' WHERE t.entity IN ('.getEntity('project').')'; if ($socids) { - $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")"; + $sql .= " AND t.fk_soc IN (".$this->db->sanitize((string) $socids).")"; } // Search on sale representative if ($search_sale && $search_sale != '-1') { @@ -270,6 +272,8 @@ class Tasks extends DolibarrApi * @param int $id Id of task * @param int $userid Id of user (0 = connected user) * @return array Array of roles + * @phan-return array + * @phpstan-return array * * @url GET {id}/roles */ @@ -295,7 +299,7 @@ class Tasks extends DolibarrApi $usert = new User($this->db); $usert->fetch($userid); } - $this->task->roles = $this->task->getUserRolesForProjectsOrTasks(null, $usert, 0, $id); + $this->task->roles = $this->task->getUserRolesForProjectsOrTasks(null, $usert, '0', $id); $result = array(); foreach ($this->task->roles as $line) { array_push($result, $this->_cleanObjectDatas($line)); @@ -531,6 +535,7 @@ class Tasks extends DolibarrApi * * @param int $id Task ID * @param datetime $date Date (YYYY-MM-DD HH:MI:SS in GMT) + * @phan-param string $date * @param int $duration Duration in seconds (3600 = 1h) * @param int $user_id User (Use 0 for connected user) * @param string $note Note @@ -593,6 +598,7 @@ class Tasks extends DolibarrApi * @param int $id Task ID * @param int $timespent_id Time spent ID (llx_element_time.rowid) * @param datetime $date Date (YYYY-MM-DD HH:MI:SS in GMT) + * @phan-param string $date * @param int $duration Duration in seconds (3600 = 1h) * @param int $user_id User (Use 0 for connected user) * @param string $note Note @@ -696,10 +702,14 @@ class Tasks extends DolibarrApi // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore /** - * Clean sensible object datas + * Clean sensitive object data + * @phpstan-template T of Object * * @param Object $object Object to clean * @return Object Object with cleaned properties + * + * @phpstan-param T $object + * @phpstan-return T */ protected function _cleanObjectDatas($object) { diff --git a/htdocs/reception/class/api_receptions.class.php b/htdocs/reception/class/api_receptions.class.php index 68cc80eaa61..f860207193a 100644 --- a/htdocs/reception/class/api_receptions.class.php +++ b/htdocs/reception/class/api_receptions.class.php @@ -765,12 +765,15 @@ class Receptions extends DolibarrApi /** * Validate fields before create or update object * - * @param array $data Array with data to verify + * @param ?array $data Array with data to verify * @return array * @throws RestException */ private function _validate($data) { + if ($data === null) { + $data = array(); + } $reception = array(); foreach (Receptions::$FIELDS as $field) { if (!isset($data[$field])) { diff --git a/htdocs/salaries/class/api_salaries.class.php b/htdocs/salaries/class/api_salaries.class.php index 8470768b1b1..4d1171ce34d 100644 --- a/htdocs/salaries/class/api_salaries.class.php +++ b/htdocs/salaries/class/api_salaries.class.php @@ -41,7 +41,7 @@ class Salaries extends DolibarrApi ); /** - * string[] $FIELDS Mandatory fields, checked when creating an object + * @var string[] Mandatory fields for mayment, checked when creating an object */ public static $FIELDSPAYMENT = array( "paiementtype", @@ -68,6 +68,8 @@ class Salaries extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @return array List of salary objects + * @phan-return Salary[] + * @phpstan-return Salary[] * * @throws RestException */ @@ -235,6 +237,8 @@ class Salaries extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @return array List of paymentsalary objects + * @phan-return PaymentSalary[] + * @phpstan-return PaymentSalary[] * * @url GET /payments * diff --git a/htdocs/societe/canvas/actions_card_common.class.php b/htdocs/societe/canvas/actions_card_common.class.php index 860c3e071f6..2876c174b10 100644 --- a/htdocs/societe/canvas/actions_card_common.class.php +++ b/htdocs/societe/canvas/actions_card_common.class.php @@ -357,7 +357,7 @@ abstract class ActionsCardCommon $i = 0; foreach ($listsalesrepresentatives as $val) { $userstatic->id = $val['id']; - $userstatic->lastname = $val['name']; + $userstatic->lastname = $val['lastname']; $userstatic->firstname = $val['firstname']; $this->tpl['sales_representatives'] .= $userstatic->getNomUrl(1); $i++; diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index 4517ed911e9..f7e5c811a03 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -86,6 +86,8 @@ class Thirdparties extends DolibarrApi * * @param string $email Email of third party to load * @return array|mixed Cleaned Societe object + * @phan-return Societe + * @phpstan-return Societe * * @url GET email/{email} * @@ -303,7 +305,9 @@ class Thirdparties extends DolibarrApi * @param array $request_data Data * @phan-param ?array $request_data * @phpstan-param ?array $request_data - * @return Object|false Updated object + * @return Object Updated object + * @phan-return Societe + * @phpstan-return Societe * * @throws RestException 401 * @throws RestException 404 @@ -364,6 +368,8 @@ class Thirdparties extends DolibarrApi * @param int $id ID of thirdparty to keep (the target third party) * @param int $idtodelete ID of thirdparty to remove (the thirdparty to delete), once data has been merged into the target third party. * @return Object Return the resulted third party. + * @phan-return Societe + * @phpstan-return Societe * * @url PUT {id}/merge/{idtodelete} */ @@ -425,7 +431,7 @@ class Thirdparties extends DolibarrApi if (!DolibarrApi::_checkAccessToResource('societe', $this->company->id)) { throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - $this->company->oldcopy = clone $this->company; + $this->company->oldcopy = clone $this->company; // @phan-suppress-current-line PhanTypeMismatchProperty $res = $this->company->delete($id); if ($res < 0) { @@ -578,7 +584,9 @@ class Thirdparties extends DolibarrApi * @param string $sortorder Sort order * @param int $limit Limit for list * @param int $page Page number - * @return array|void + * @return array + * @phan-return array,visible:int,ref_ext:string,multilangs?:array}> + * @phpstan-return array,visible:int,ref_ext:string,multilangs?:array}> * * @url GET {id}/categories */ @@ -613,7 +621,9 @@ class Thirdparties extends DolibarrApi * * @param int $id Id of thirdparty * @param int $category_id Id of category - * @return Object|void + * @return Object + * @phan-return Societe + * @phpstan-return Societe * * @url PUT {id}/categories/{category_id} */ @@ -651,7 +661,9 @@ class Thirdparties extends DolibarrApi * @param int $id Id of thirdparty * @param int $category_id Id of category * - * @return Object|void + * @return Object + * @phan-return Societe + * @phpstan-return Societe * * @url DELETE {id}/categories/{category_id} */ @@ -692,7 +704,9 @@ class Thirdparties extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * - * @return mixed + * @return array + * @phan-return array,visible:int,ref_ext:string,multilangs?:array}> + * @phpstan-return array,visible:int,ref_ext:string,multilangs?:array}> * * @url GET {id}/supplier_categories */ @@ -729,6 +743,8 @@ class Thirdparties extends DolibarrApi * @param int $category_id Id of category * * @return mixed + * @phan-return Societe + * @phpstan-return Societe * * @url PUT {id}/supplier_categories/{category_id} */ @@ -767,6 +783,8 @@ class Thirdparties extends DolibarrApi * @param int $category_id Id of category * * @return mixed + * @phan-return Societe + * @phpstan-return Societe * * @url DELETE {id}/supplier_categories/{category_id} */ @@ -808,6 +826,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/outstandingproposals * * @return array List of outstandings proposals of thirdparty + * @phan-return array{opened?:float} + * @phpstan-return array{opened?:float} * * @throws RestException 400 * @throws RestException 401 @@ -850,6 +870,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/outstandingorders * * @return array List of outstandings orders of thirdparty + * @phan-return array{opened?:float} + * @phpstan-return array{opened?:float} * * @throws RestException 400 * @throws RestException 401 @@ -890,7 +912,9 @@ class Thirdparties extends DolibarrApi * * @url GET {id}/outstandinginvoices * - * @return array List of outstandings invoices of thirdparty + * @return array List of outstanding invoices of third party + * @phan-return array{opened?:float} + * @phpstan-return array{opened?:float} * * @throws RestException 400 * @throws RestException 401 @@ -932,6 +956,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/representatives * * @return array List of representatives of thirdparty + * @phan-return int[]|array + * @phpstan-return int[]|array * * @throws RestException 400 * @throws RestException 401 @@ -952,7 +978,7 @@ class Thirdparties extends DolibarrApi } $result = $this->company->fetch($id); - if (!$result) { + if (!is_array($result)) { throw new RestException(404, 'Thirdparty not found'); } @@ -972,6 +998,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/fixedamountdiscounts * * @return array List of fixed discount of thirdparty + * @phan-return stdClass[] + * @phpstan-return stdClass[] * * @throws RestException 400 * @throws RestException 401 @@ -1035,6 +1063,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/getinvoicesqualifiedforreplacement * * @return array + * @phan-return array|int + * @phpstan-return array|int * @throws RestException 400 * @throws RestException 401 * @throws RestException 404 @@ -1078,6 +1108,8 @@ class Thirdparties extends DolibarrApi * @url GET {id}/getinvoicesqualifiedforcreditnote * * @return array + * @phan-return array|int + * @phpstan-return array|int * * @throws RestException 400 * @throws RestException 401 @@ -1105,7 +1137,7 @@ class Thirdparties extends DolibarrApi require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $invoice = new Facture($this->db); $result = $invoice->list_qualified_avoir_invoices($id); - if ($result < 0) { + if (!is_array($result) && $result < 0) { throw new RestException(405, $invoice->error); } @@ -1118,6 +1150,8 @@ class Thirdparties extends DolibarrApi * @param int $id ID of thirdparty * * @return array + * @phan-return array + * @phpstan-return array * * @url GET {id}/notifications */ @@ -1177,6 +1211,7 @@ class Thirdparties extends DolibarrApi $returnNotifications[] = $object; } + // Too complex for phan ?: @phan-suppress-next-line PhanTypeMismatchReturn return $returnNotifications; } @@ -1217,9 +1252,9 @@ class Thirdparties extends DolibarrApi $exists_sql = "SELECT rowid, fk_action as event, fk_soc as socid, fk_contact as contact_id, type, datec, tms as datem"; $exists_sql .= " FROM ".MAIN_DB_PREFIX."notify_def"; - $exists_sql .= " WHERE fk_action = '".$this->db->escape($event)."'"; - $exists_sql .= " AND fk_soc = '".$this->db->escape($socid)."'"; - $exists_sql .= " AND fk_contact = '".$this->db->escape($contact_id)."'"; + $exists_sql .= " WHERE fk_action = '".$this->db->escape((string) $event)."'"; + $exists_sql .= " AND fk_soc = '".$this->db->escape((string) $socid)."'"; + $exists_sql .= " AND fk_contact = '".$this->db->escape((string) $contact_id)."'"; $exists_result = $this->db->query($exists_sql); if ($this->db->num_rows($exists_result) > 0) { @@ -1287,9 +1322,9 @@ class Thirdparties extends DolibarrApi $exists_sql = "SELECT rowid, fk_action as event, fk_soc as socid, fk_contact as contact_id, type, datec, tms as datem"; $exists_sql .= " FROM ".MAIN_DB_PREFIX."notify_def"; - $exists_sql .= " WHERE fk_action = '".$this->db->escape($event)."'"; - $exists_sql .= " AND fk_soc = '".$this->db->escape($socid)."'"; - $exists_sql .= " AND fk_contact = '".$this->db->escape($contact_id)."'"; + $exists_sql .= " WHERE fk_action = '".$this->db->escape((string) $event)."'"; + $exists_sql .= " AND fk_soc = '".$this->db->escape((string) $socid)."'"; + $exists_sql .= " AND fk_contact = '".$this->db->escape((string) $contact_id)."'"; $exists_result = $this->db->query($exists_sql); if ($this->db->num_rows($exists_result) > 0) { @@ -1383,6 +1418,8 @@ class Thirdparties extends DolibarrApi * @param int $id ID of thirdparty * * @return array + * @phan-return array + * @phpstan-return array * * @url GET {id}/bankaccounts */ @@ -1498,7 +1535,7 @@ class Thirdparties extends DolibarrApi if (empty($account->rum)) { require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php'; $prelevement = new BonPrelevement($this->db); - $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, $account->id); + $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, (string) $account->id); $account->date_rum = dol_now(); } @@ -1553,7 +1590,7 @@ class Thirdparties extends DolibarrApi if (empty($account->rum)) { require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php'; $prelevement = new BonPrelevement($this->db); - $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, $account->id); + $account->rum = $prelevement->buildRumNumber($this->company->code_client, $account->datec, (string) $account->id); $account->date_rum = dol_now(); } @@ -1600,6 +1637,8 @@ class Thirdparties extends DolibarrApi * @param int $companybankid Companybank id * @param string $model Model of document to generate * @return array + * @phan-return array{success:int<0,1>} + * @phpstan-return array{success:int<0,1>} * * @url GET {id}/generateBankAccountDocument/{companybankid}/{model} */ @@ -2024,7 +2063,7 @@ class Thirdparties extends DolibarrApi * Delete a specific site account attached to a thirdparty (by account id) * * @param int $id ID of thirdparty - * @param int $site Site key + * @param string $site Site key * * @return void * @throws RestException 401 Unauthorized: User does not have permission to delete thirdparties accounts @@ -2183,6 +2222,8 @@ class Thirdparties extends DolibarrApi * @param string $email Email of third party (Warning, this can return several records) * @param string $ref_alias Name_alias of third party (Warning, this can return several records) * @return object cleaned Societe object + * @phan-return Societe + * @phpstan-return Societe * * @throws RestException */ @@ -2192,7 +2233,7 @@ class Thirdparties extends DolibarrApi throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login.'. No read permission on thirdparties.'); } - if ($rowid === 0) { + if ($rowid == 0) { $result = $this->company->initAsSpecimen(); } else { $result = $this->company->fetch($rowid, $ref, $ref_ext, $barcode, $idprof1, $idprof2, $idprof3, $idprof4, $idprof5, $idprof6, $email, $ref_alias); @@ -2216,8 +2257,8 @@ class Thirdparties extends DolibarrApi $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')"; } - $absolute_discount = $this->company->getAvailableDiscounts('', $filterabsolutediscount); - $absolute_creditnote = $this->company->getAvailableDiscounts('', $filtercreditnote); + $absolute_discount = $this->company->getAvailableDiscounts(null, $filterabsolutediscount); + $absolute_creditnote = $this->company->getAvailableDiscounts(null, $filtercreditnote); $this->company->absolute_discount = price2num($absolute_discount, 'MT'); $this->company->absolute_creditnote = price2num($absolute_creditnote, 'MT'); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 1828e733dba..94f69e34908 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -85,7 +85,7 @@ class Societe extends CommonObject public $fieldsforcombobox = 'nom,name_alias'; /** - * @var array> List of child tables. To test if we can delete object. + * @var array List of child tables. To test if we can delete object. */ protected $childtables = array( 'supplier_proposal' => array('name' => 'SupplierProposal'), @@ -2674,10 +2674,10 @@ class Societe extends CommonObject * Return array of sales representatives * * @param User $user Object user (not used) - * @param int $mode 0=Array with properties, 1=Array of IDs. + * @param int<0,1> $mode 0=Array with properties, 1=Array of IDs. * @param ?string $sortfield List of sort fields, separated by comma. Example: 't1.fielda,t2.fieldb' * @param ?string $sortorder Sort order, separated by comma. Example: 'ASC,DESC'; - * @return array|int Array of sales representatives of the current third party or <0 if KO + * @return int<-1,-1>|int[]|array Array of sales representatives of the current third party or <0 if KO */ public function getSalesRepresentatives(User $user, $mode = 0, $sortfield = null, $sortorder = null) { @@ -2712,7 +2712,7 @@ class Societe extends CommonObject $obj = $this->db->fetch_object($resql); if (empty($mode)) { - $reparray[$i]['id'] = $obj->rowid; + $reparray[$i]['id'] = (int) $obj->rowid; $reparray[$i]['lastname'] = $obj->lastname; $reparray[$i]['firstname'] = $obj->firstname; $reparray[$i]['email'] = $obj->email; @@ -2729,7 +2729,7 @@ class Societe extends CommonObject $reparray[$i]['photo'] = $obj->photo; $reparray[$i]['gender'] = $obj->gender; } else { - $reparray[] = $obj->rowid; + $reparray[] = (int) $obj->rowid; } $i++; } diff --git a/htdocs/webhook/class/api_webhook.class.php b/htdocs/webhook/class/api_webhook.class.php index 32474da267c..95aad63f9b8 100644 --- a/htdocs/webhook/class/api_webhook.class.php +++ b/htdocs/webhook/class/api_webhook.class.php @@ -261,6 +261,8 @@ class Webhook extends DolibarrApi * Get the list of all available triggers * * @return array + * @phan-return array + * @phpstan-return array * * @url GET triggers */ diff --git a/htdocs/zapier/class/api_zapier.class.php b/htdocs/zapier/class/api_zapier.class.php index d917d192024..859d2f7a598 100644 --- a/htdocs/zapier/class/api_zapier.class.php +++ b/htdocs/zapier/class/api_zapier.class.php @@ -37,7 +37,7 @@ require_once DOL_DOCUMENT_ROOT.'/zapier/class/hook.class.php'; class Zapier extends DolibarrApi { /** - * @var array Mandatory fields, checked when create and update object + * @var string[] Mandatory fields, checked when create and update object */ public static $FIELDS = array( 'url', From 4cc09b514996d40acf19f8ef21b6f084d38bc06d Mon Sep 17 00:00:00 2001 From: MDW Date: Mon, 3 Mar 2025 19:33:44 +0100 Subject: [PATCH 38/71] Qual: Ignore phpstan notices requiring deeper analysis --- dev/build/phpstan/phpstan-baseline.neon | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/dev/build/phpstan/phpstan-baseline.neon b/dev/build/phpstan/phpstan-baseline.neon index ce8c2a8fa80..0ed297ad58d 100644 --- a/dev/build/phpstan/phpstan-baseline.neon +++ b/dev/build/phpstan/phpstan-baseline.neon @@ -20214,6 +20214,18 @@ parameters: count: 1 path: ../../../htdocs/product/class/api_products.class.php + - + message: '#^Method Products\:\:getPurchasePrices\(\) should return array\ but returns object\.$#' + identifier: return.type + count: 1 + path: ../../../htdocs/product/class/api_products.class.php + + - + message: '#^Unable to resolve the template type T in call to method Products\:\:_cleanObjectDatas\(\)$#' + identifier: argument.templateType + count: 1 + path: ../../../htdocs/product/class/api_products.class.php + - message: '#^Method Products\:\:getSubproducts\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue @@ -21804,6 +21816,18 @@ parameters: count: 1 path: ../../../htdocs/projet/class/api_tasks.class.php + - + message: '#^Method Tasks\:\:getRoles\(\) should return array but returns list\\.$#' + identifier: return.type + count: 1 + path: ../../../htdocs/projet/class/api_tasks.class.php + + - + message: '#^Unable to resolve the template type T in call to method Tasks\:\:_cleanObjectDatas\(\)$#' + identifier: argument.templateType + count: 1 + path: ../../../htdocs/projet/class/api_tasks.class.php + - message: '#^Parameter \#1 \$object of method Tasks\:\:_cleanObjectDatas\(\) expects object, string given\.$#' identifier: argument.type From 04fd52cd70913505bb1e1a602a84c4b95cd4c272 Mon Sep 17 00:00:00 2001 From: MDW Date: Wed, 5 Mar 2025 13:32:45 +0100 Subject: [PATCH 39/71] Update baseline --- dev/tools/phan/baseline.txt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/dev/tools/phan/baseline.txt b/dev/tools/phan/baseline.txt index fd67711a514..79afcf466e4 100644 --- a/dev/tools/phan/baseline.txt +++ b/dev/tools/phan/baseline.txt @@ -9,12 +9,12 @@ */ return [ // # Issue statistics: - // PhanTypeMismatchArgument : 1200+ occurrences - // PhanUndeclaredProperty : 480+ occurrences - // PhanTypeMismatchArgumentNullable : 300+ occurrences + // PhanTypeMismatchArgument : 1110+ occurrences + // PhanUndeclaredProperty : 470+ occurrences + // PhanTypeMismatchArgumentNullable : 270+ occurrences // PhanTypeMismatchProperty : 150+ occurrences // PhanUndeclaredGlobalVariable : 100+ occurrences - // PhanTypeExpectedObjectPropAccess : 25+ occurrences + // PhanTypeExpectedObjectPropAccess : 20+ occurrences // PhanTypeInvalidDimOffset : 20+ occurrences // PhanTypeMismatchDimFetch : 20+ occurrences // PhanPluginUndeclaredVariableIsset : 15+ occurrences @@ -106,8 +106,6 @@ return [ 'htdocs/admin/pdf_other.php' => ['PhanTypeMismatchArgument'], 'htdocs/admin/prelevement.php' => ['PhanTypeMismatchArgument'], 'htdocs/admin/receiptprinter.php' => ['PhanTypeMismatchArgument'], - 'htdocs/admin/remotestore/class/PSWebServiceLibrary.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], - 'htdocs/admin/remotestore/class/dolistore.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/admin/system/filecheck.php' => ['PhanTypeMismatchArgument'], 'htdocs/admin/system/modules.php' => ['PhanTypeMismatchArgument'], 'htdocs/admin/taxes.php' => ['PhanTypeMismatchArgumentNullable'], @@ -588,7 +586,6 @@ return [ 'htdocs/societe/card.php' => ['PhanTypeMismatchProperty'], 'htdocs/societe/class/societe.class.php' => ['PhanTypeMismatchProperty'], 'htdocs/societe/paymentmodes.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchArgument'], - 'htdocs/stripe/class/stripe.class.php' => ['PhanTypeExpectedObjectPropAccess'], 'htdocs/supplier_proposal/card.php' => ['PhanTypeMismatchProperty', 'PhanUndeclaredGlobalVariable', 'PhanUndeclaredProperty'], 'htdocs/supplier_proposal/class/api_supplier_proposals.class.php' => ['PhanUndeclaredProperty'], 'htdocs/supplier_proposal/class/supplier_proposal.class.php' => ['PhanUndeclaredProperty'], From c0c49f53cbf50ecc4d2c46df269d194280c45746 Mon Sep 17 00:00:00 2001 From: omogenot Date: Thu, 27 Feb 2025 17:21:31 +0100 Subject: [PATCH 40/71] Update export_excel2007.modules.php Fix Excel Export for zero values --- htdocs/core/modules/export/export_excel2007.modules.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/export/export_excel2007.modules.php b/htdocs/core/modules/export/export_excel2007.modules.php index 1f9a804da46..d5bdd998b46 100644 --- a/htdocs/core/modules/export/export_excel2007.modules.php +++ b/htdocs/core/modules/export/export_excel2007.modules.php @@ -336,9 +336,9 @@ class ExportExcel2007 extends ModeleExports continue; } - $newvalue = !empty($objp->$alias) ? $objp->$alias : ''; + // $newvalue = !empty($objp->$alias) ? $objp->$alias : ''; - $newvalue = $this->excel_clean($newvalue); + $newvalue = $this->excel_clean($objp->$alias); $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { From c562c6ebab72a470242123efee288404c0bc785a Mon Sep 17 00:00:00 2001 From: omogenot Date: Wed, 5 Mar 2025 13:16:30 +0100 Subject: [PATCH 41/71] Add is_numeric condition to check empty values --- htdocs/core/modules/export/export_excel2007.modules.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/export/export_excel2007.modules.php b/htdocs/core/modules/export/export_excel2007.modules.php index d5bdd998b46..cc029b3cc4e 100644 --- a/htdocs/core/modules/export/export_excel2007.modules.php +++ b/htdocs/core/modules/export/export_excel2007.modules.php @@ -336,9 +336,9 @@ class ExportExcel2007 extends ModeleExports continue; } - // $newvalue = !empty($objp->$alias) ? $objp->$alias : ''; + $newvalue = (!empty($objp->$alias) || (is_numeric($objp->alias))) ? $objp->$alias : ''; - $newvalue = $this->excel_clean($objp->$alias); + $newvalue = $this->excel_clean($newvalue); $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { From 5d338a6b1d408f7e6788277ea55c8d526710e070 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Mar 2025 13:48:37 +0100 Subject: [PATCH 42/71] Update externalModules.class.php --- htdocs/admin/remotestore/class/externalModules.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/admin/remotestore/class/externalModules.class.php b/htdocs/admin/remotestore/class/externalModules.class.php index 8f0a28b1c04..86dbbf4bdf8 100644 --- a/htdocs/admin/remotestore/class/externalModules.class.php +++ b/htdocs/admin/remotestore/class/externalModules.class.php @@ -666,8 +666,6 @@ class ExternalModules dol_mkdir($cache_folder, DOL_DATA_ROOT); } - $yaml = ''; - if (!file_exists($cache_file) || filemtime($cache_file) < (dol_now() - $cache_time)) { // We get remote url $result = getURLContent($file_source_url); From 6a2616c1190af829bee406a65d39e18e8cf481ae Mon Sep 17 00:00:00 2001 From: atm-corentin Date: Wed, 5 Mar 2025 14:58:21 +0100 Subject: [PATCH 43/71] set field default vat code because it was not set for child product --- htdocs/product/class/product.class.php | 3 ++- htdocs/variants/class/ProductCombination.class.php | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 88ab82da615..cf3bf8360e2 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1121,6 +1121,7 @@ class Product extends CommonObject $sql .= ", batch_mask"; $sql .= ", fk_unit"; $sql .= ", mandatory_period"; + if (!empty($this->default_vat_code)) $sql.=", default_vat_code"; $sql .= ") VALUES ("; $sql .= "'".$this->db->idate($this->date_creation)."'"; $sql .= ", ".(!empty($this->entity) ? (int) $this->entity : (int) $conf->entity); @@ -1152,8 +1153,8 @@ class Product extends CommonObject $sql .= ", '".$this->db->escape($this->batch_mask)."'"; $sql .= ", ".($this->fk_unit > 0 ? ((int) $this->fk_unit) : 'NULL'); $sql .= ", '".$this->db->escape((string) $this->mandatory_period)."'"; + if (!empty($this->default_vat_code)) $sql.=", '".$this->db->escape($this->default_vat_code)."'"; $sql .= ")"; - dol_syslog(get_class($this)."::Create", LOG_DEBUG); $result = $this->db->query($sql); diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php index 088a56488a4..ec69ab242df 100644 --- a/htdocs/variants/class/ProductCombination.class.php +++ b/htdocs/variants/class/ProductCombination.class.php @@ -577,7 +577,6 @@ class ProductCombination } else { $new_price += $variation_price; } - $ret = $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, $i, $new_npr, $new_psq, 0, array(), $parent->default_vat_code); if ($ret < 0) { @@ -607,7 +606,7 @@ class ProductCombination $new_price += $this->variation_price; } - $ret = $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, 1, $new_npr, $new_psq); + $ret = $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, 1, $new_npr, $new_psq,0, array(), $parent->default_vat_code); if ($ret < 0) { $this->db->rollback(); From 973a11e1e9794a9914258c4e126996df56c90ed2 Mon Sep 17 00:00:00 2001 From: Jyhere Date: Wed, 5 Mar 2025 09:30:15 +0100 Subject: [PATCH 44/71] FIX: Warning when getNomUrl is called before top_httphead If Societe::getNomUrl() is called before top_httphead, this triggers a Cannot modify header warning --- htdocs/societe/class/societe.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 97a7adebb1b..42e1025bade 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3075,8 +3075,6 @@ class Societe extends CommonObject } else { $label = implode($this->getTooltipContentArray($params)); } - print "\n"; - //var_dump($label);exit; $linkstart = ''; $linkend = ''; From 30dffd6fddbbbdb735274e3ccfffb3891a91d0ee Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 17:48:41 +0100 Subject: [PATCH 45/71] Fix CI warnings --- htdocs/accountancy/class/bookkeeping.class.php | 2 +- htdocs/core/class/timespent.class.php | 8 +++----- .../class/conferenceorboothattendee.class.php | 4 +--- htdocs/hrm/class/evaluationdet.class.php | 4 +--- htdocs/hrm/class/position.class.php | 4 +--- htdocs/hrm/class/skill.class.php | 1 + htdocs/hrm/class/skilldet.class.php | 4 +--- htdocs/hrm/class/skillrank.class.php | 4 +--- htdocs/partnership/class/partnership.class.php | 4 +--- htdocs/product/class/productfournisseurprice.class.php | 5 +++-- 10 files changed, 14 insertions(+), 26 deletions(-) diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 1befc5c4332..a2080f282ab 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1580,7 +1580,7 @@ class BookKeeping extends CommonObject $this->db->begin(); // Call triggers - if (! $error && ! $notrigger) { + if (!$notrigger) { $result = $this->call_trigger('BOOKKEEPING_DELETE', $user); if ($result < 0) { $error++; diff --git a/htdocs/core/class/timespent.class.php b/htdocs/core/class/timespent.class.php index fb79053c145..f863f849ddb 100644 --- a/htdocs/core/class/timespent.class.php +++ b/htdocs/core/class/timespent.class.php @@ -281,7 +281,8 @@ class TimeSpent extends CommonObject */ public function createFromClone(User $user, $fromid) { - global $langs, $extrafields; + global $extrafields; + $error = 0; dol_syslog(__METHOD__, LOG_DEBUG); @@ -296,16 +297,13 @@ class TimeSpent extends CommonObject // Reset some properties unset($object->id); unset($object->fk_user_creat); + unset($object->user_creation_id); unset($object->import_key); // Clear fields if (property_exists($object, 'ref')) { $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { - // @phan-suppress-next-line PhanUndeclaredProperty - $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - } if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } diff --git a/htdocs/eventorganization/class/conferenceorboothattendee.class.php b/htdocs/eventorganization/class/conferenceorboothattendee.class.php index 77357da66d6..f83e2bd845b 100644 --- a/htdocs/eventorganization/class/conferenceorboothattendee.class.php +++ b/htdocs/eventorganization/class/conferenceorboothattendee.class.php @@ -352,6 +352,7 @@ class ConferenceOrBoothAttendee extends CommonObject // Reset some properties unset($object->id); unset($object->fk_user_creat); + unset($object->user_creation_id); unset($object->import_key); // Clear fields @@ -359,9 +360,6 @@ class ConferenceOrBoothAttendee extends CommonObject // @phan-suppress-next-line PhanTypeInvalidDimOffset $object->ref = empty($this->fields['ref']['default']) ? "(PROV)" : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { - $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - } if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } diff --git a/htdocs/hrm/class/evaluationdet.class.php b/htdocs/hrm/class/evaluationdet.class.php index 10e55284fba..ad3ab437bdb 100644 --- a/htdocs/hrm/class/evaluationdet.class.php +++ b/htdocs/hrm/class/evaluationdet.class.php @@ -276,15 +276,13 @@ class EvaluationLine extends CommonObjectLine // Reset some properties unset($object->id); unset($object->fk_user_creat); + unset($object->user_creation_id); unset($object->import_key); // Clear fields if (property_exists($object, 'ref')) { $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { - $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - } if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php index 427f47f2e26..194b836f2a2 100644 --- a/htdocs/hrm/class/position.class.php +++ b/htdocs/hrm/class/position.class.php @@ -293,15 +293,13 @@ class Position extends CommonObject // Reset some properties unset($object->id); unset($object->fk_user_creat); + unset($object->user_ceation_id); unset($object->import_key); // Clear fields if (property_exists($object, 'ref')) { $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_" . $object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { - $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf") . " " . $object->label : $this->fields['label']['default']; - } if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } diff --git a/htdocs/hrm/class/skill.class.php b/htdocs/hrm/class/skill.class.php index f4adc185f7b..bec9e3b5999 100644 --- a/htdocs/hrm/class/skill.class.php +++ b/htdocs/hrm/class/skill.class.php @@ -344,6 +344,7 @@ class Skill extends CommonObject // Reset some properties unset($object->id); unset($object->fk_user_creat); + unset($object->user_creation_id); unset($object->import_key); // Clear fields diff --git a/htdocs/hrm/class/skilldet.class.php b/htdocs/hrm/class/skilldet.class.php index c5d9f1dc155..f42001024b5 100644 --- a/htdocs/hrm/class/skilldet.class.php +++ b/htdocs/hrm/class/skilldet.class.php @@ -265,15 +265,13 @@ class Skilldet extends CommonObjectLine // Reset some properties unset($object->id); unset($object->fk_user_creat); + unset($object->user_creation_id); unset($object->import_key); // Clear fields if (property_exists($object, 'ref')) { $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { - $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - } if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } diff --git a/htdocs/hrm/class/skillrank.class.php b/htdocs/hrm/class/skillrank.class.php index 34fb53116c6..e70775cd7ca 100644 --- a/htdocs/hrm/class/skillrank.class.php +++ b/htdocs/hrm/class/skillrank.class.php @@ -279,6 +279,7 @@ class SkillRank extends CommonObject // Reset some properties unset($object->id); unset($object->fk_user_creat); + unset($object->user_creation_id); unset($object->import_key); if (!empty($fk_object) && $fk_object > 0) { unset($object->fk_object); @@ -289,9 +290,6 @@ class SkillRank extends CommonObject if (property_exists($object, 'ref')) { $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { - $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - } if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php index 6593b6e40b2..666cda46456 100644 --- a/htdocs/partnership/class/partnership.class.php +++ b/htdocs/partnership/class/partnership.class.php @@ -307,6 +307,7 @@ class Partnership extends CommonObject // Reset some properties unset($object->id); unset($object->fk_user_creat); + unset($object->user_creation_id); unset($object->import_key); // Clear fields @@ -314,9 +315,6 @@ class Partnership extends CommonObject // @phan-suppress-next-line PhanTypeMismatchProperty $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { - $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - } if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } diff --git a/htdocs/product/class/productfournisseurprice.class.php b/htdocs/product/class/productfournisseurprice.class.php index 5f8372f6c83..a2f627acd75 100644 --- a/htdocs/product/class/productfournisseurprice.class.php +++ b/htdocs/product/class/productfournisseurprice.class.php @@ -328,15 +328,16 @@ class ProductFournisseurPrice extends CommonObject // Reset some properties unset($object->id); unset($object->fk_user_creat); + unset($object->user_creation_id); unset($object->import_key); // Clear fields if (property_exists($object, 'ref')) { $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { + /*if (property_exists($object, 'label')) { $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - } + }*/ if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } From 7a995646e17b9f8412f85b6873eb23e8b9e9d09a Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 18:13:20 +0100 Subject: [PATCH 46/71] Fix bad property name --- htdocs/core/modules/export/export_excel2007.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/export/export_excel2007.modules.php b/htdocs/core/modules/export/export_excel2007.modules.php index cc029b3cc4e..84a0128a0f6 100644 --- a/htdocs/core/modules/export/export_excel2007.modules.php +++ b/htdocs/core/modules/export/export_excel2007.modules.php @@ -336,7 +336,7 @@ class ExportExcel2007 extends ModeleExports continue; } - $newvalue = (!empty($objp->$alias) || (is_numeric($objp->alias))) ? $objp->$alias : ''; + $newvalue = (!empty($objp->$alias) || (is_numeric($objp->$alias))) ? $objp->$alias : ''; $newvalue = $this->excel_clean($newvalue); $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; From 4cb5939542728ce1d2a54a078d597ac363cc3033 Mon Sep 17 00:00:00 2001 From: Mohamed DAOUD Date: Wed, 5 Mar 2025 18:34:19 +0100 Subject: [PATCH 47/71] fix sendermail signature --- htdocs/core/actions_sendmails.inc.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index 6492494039c..fb754af26fd 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -306,6 +306,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO $reg = array(); $fromtype = GETPOST('fromtype', 'alpha'); + $emailsendersignature = null; if ($fromtype === 'robot') { $from = dol_string_nospecial($conf->global->MAIN_MAIL_EMAIL_FROM, ' ', array(",")).' <' . getDolGlobalString('MAIN_MAIL_EMAIL_FROM').'>'; } elseif ($fromtype === 'user') { @@ -319,12 +320,13 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO $tmp = explode(',', getDolGlobalString('MAIN_INFO_SOCIETE_MAIL_ALIASES')); $from = trim($tmp[((int) $reg[1] - 1)]); } elseif (preg_match('/senderprofile_(\d+)_(\d+)/', $fromtype, $reg)) { - $sql = 'SELECT rowid, label, email FROM '.MAIN_DB_PREFIX.'c_email_senderprofile'; + $sql = 'SELECT rowid, label, email, signature FROM '.MAIN_DB_PREFIX.'c_email_senderprofile'; $sql .= ' WHERE rowid = '.(int) $reg[1]; $resql = $db->query($sql); $obj = $db->fetch_object($resql); if ($obj) { $from = dol_string_nospecial($obj->label, ' ', array(",")).' <'.$obj->email.'>'; + $emailsendersignature = $obj->signature; } } elseif (preg_match('/from_template_(\d+)/', $fromtype, $reg)) { $sql = 'SELECT rowid, email_from FROM '.MAIN_DB_PREFIX.'c_email_templates'; @@ -384,6 +386,9 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO // Make substitution in email content $substitutionarray = getCommonSubstitutionArray($langs, 0, null, $object); + if (!empty($emailsendersignature)) { + $substitutionarray['__SENDEREMAIL_SIGNATURE__'] = $emailsendersignature; + } $substitutionarray['__EMAIL__'] = $sendto; $substitutionarray['__CHECK_READ__'] = (is_object($object) && is_object($object->thirdparty)) ? '' : ''; From 1f9901190cd792285372a57755788987b779bc71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 5 Mar 2025 18:36:34 +0100 Subject: [PATCH 48/71] fix CI --- htdocs/variants/class/ProductCombination.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php index ec69ab242df..19351cd2dbd 100644 --- a/htdocs/variants/class/ProductCombination.class.php +++ b/htdocs/variants/class/ProductCombination.class.php @@ -3,7 +3,7 @@ * Copyright (C) 2018 Juanjo Menent * Copyright (C) 2022 Open-Dsi * Copyright (C) 2024-2025 MDW - * Copyright (C) 2024 Frédéric France + * Copyright (C) 2024-2025 Frédéric France * * 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 @@ -606,7 +606,7 @@ class ProductCombination $new_price += $this->variation_price; } - $ret = $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, 1, $new_npr, $new_psq,0, array(), $parent->default_vat_code); + $ret = $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, 1, $new_npr, $new_psq, 0, [], $parent->default_vat_code); if ($ret < 0) { $this->db->rollback(); From f9f93287ea126ac3e46a5776454ce4ded5f4ea05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 5 Mar 2025 18:56:51 +0100 Subject: [PATCH 49/71] no label property on RecruitmentCandidature --- htdocs/recruitment/class/recruitmentcandidature.class.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index 3db699c6d45..7ed11f2c436 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -1,6 +1,6 @@ - * Copyright (C) 2024 Frédéric France + * Copyright (C) 2024-2025 Frédéric France * Copyright (C) 2024-2025 MDW * * This program is free software; you can redistribute it and/or modify @@ -313,9 +313,6 @@ class RecruitmentCandidature extends CommonObject // @phan-suppress-next-line PhanTypeMismatchProperty $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { - $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - } if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } From 16418cfda65c3f2346aa62e637b27130aea90412 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 19:10:22 +0100 Subject: [PATCH 50/71] Try a fix for migration error on bank line categories with postgres --- .../install/mysql/migration/20.0.0-21.0.0.sql | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/htdocs/install/mysql/migration/20.0.0-21.0.0.sql b/htdocs/install/mysql/migration/20.0.0-21.0.0.sql index cb764363909..88c781762cc 100644 --- a/htdocs/install/mysql/migration/20.0.0-21.0.0.sql +++ b/htdocs/install/mysql/migration/20.0.0-21.0.0.sql @@ -262,15 +262,8 @@ LEFT JOIN llx_categorie WHERE llx_categorie.rowid IS NULL; -- Update llx_category_bankline with the new rowid from llx_categorie -UPDATE llx_category_bankline AS bl -INNER JOIN llx_category_bank AS b - ON bl.fk_categ = b.rowid -INNER JOIN llx_categorie AS c - ON b.label = c.label - AND b.entity = c.entity - AND c.type = 8 -SET bl.fk_categ = c.rowid -WHERE c.rowid IS NOT NULL; +-- VMYSQL4.3 UPDATE llx_category_bankline AS bl INNER JOIN llx_category_bank AS b ON bl.fk_categ = b.rowid INNER JOIN llx_categorie AS c ON b.label = c.label AND b.entity = c.entity AND c.type = 8 SET bl.fk_categ = c.rowid WHERE c.rowid IS NOT NULL; +-- VPGSQL8.2 UPDATE llx_category_bankline AS bl SET fk_categ = c.rowid FROM llx_category_bank AS b INNER JOIN llx_categorie AS c ON b.label = c.label AND b.entity IS NOT NULL AND c.type = 8 WHERE bl.fk_categ = b.rowid AND c.rowid IS NOT NULL; INSERT INTO llx_categorie (entity, fk_parent, label, type, description, color, position, visible, date_creation) SELECT @@ -291,15 +284,9 @@ LEFT JOIN llx_categorie WHERE llx_categorie.rowid IS NULL; -- Update llx_category_bankline with the new rowid from llx_categorie -UPDATE llx_category_bankline AS bl -INNER JOIN llx_bank_categ AS b - ON bl.fk_categ = b.rowid -INNER JOIN llx_categorie AS c - ON b.label = c.label - AND b.entity = c.entity - AND c.type = 8 -SET bl.fk_categ = c.rowid -WHERE c.rowid IS NOT NULL; +-- VMYSQL4.3 UPDATE llx_category_bankline AS bl INNER JOIN llx_bank_categ AS b ON bl.fk_categ = b.rowid INNER JOIN llx_categorie AS c ON b.label = c.label AND b.entity = c.entity AND c.type = 8 SET bl.fk_categ = c.rowid WHERE c.rowid IS NOT NULL; +-- VPGSQL8.2 UPDATE llx_category_bankline AS bl SET fk_categ = c.rowid FROM llx_bank_categ AS b INNER JOIN llx_categorie AS c ON b.label = c.label AND b.entity IS NOT NULL AND c.type = 8 WHERE bl.fk_categ = b.rowid AND c.rowid IS NOT NULL; + -- Accounting - Add personalized multi-report create table llx_c_accounting_report From 1391c61a646b5fe3ade709631a8c2b32417c0f51 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 19:11:34 +0100 Subject: [PATCH 51/71] Remove test, not yet supported in v20 --- test/phpunit/FunctionsLibTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 30fb513b859..83ec3241e16 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -1928,8 +1928,8 @@ class FunctionsLibTest extends CommonClassTest $s = natural_search("t.field", "abc def"); $this->assertEquals($s, " AND (t.field LIKE '%abc%' AND t.field LIKE '%def%')"); - $s = natural_search("t.field", "'abc def' ghi"); - $this->assertEquals($s, " AND (t.field LIKE '%abc def%' AND t.field LIKE '%ghi%')"); + //$s = natural_search("t.field", "'abc def' ghi"); + //$this->assertEquals($s, " AND (t.field LIKE '%abc def%' AND t.field LIKE '%ghi%')"); $s = natural_search("t.field", "abc def,ghi", 3); $this->assertEquals($s, " AND (t.field IN ('abc def','ghi'))"); From e24ec490a71fbbf3db7c9ee4a4d3e7c68060f647 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 19:15:28 +0100 Subject: [PATCH 52/71] Fix bad value of cache delay --- htdocs/website/samples/wrapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/website/samples/wrapper.php b/htdocs/website/samples/wrapper.php index dd669a379a7..4c0907d3cc1 100644 --- a/htdocs/website/samples/wrapper.php +++ b/htdocs/website/samples/wrapper.php @@ -129,9 +129,9 @@ $original_file = str_replace("../", "/", $original_file); // Cache or not $cachestring = GETPOST("cache", 'aZ09'); // May be 1, or an int (delay in second of the cache if < 999999, or a timestamp), or a hash +$cachedelay = GETPOSTINT('cachedelay') ? GETPOSTINT('cachedelay') : ((is_numeric($cachestring) && (int) $cachestring > 1 && (int) $cachestring < 999999) ? $cachestring : '3600'); if ($cachestring || image_format_supported($original_file) >= 0) { // Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access. - $cachedelay = GETPOSTINT('cachedelay') ? GETPOSTINT('cachedelay') : ((is_numeric($cachestring) && (int) $cachestring > 1 && (int) $cachestring < 999999) ? $cachestring : '3600'); header('Cache-Control: max-age='.$cachedelay.', public, must-revalidate'); header('Pragma: cache'); // This is to avoid having Pragma: no-cache header('Expires: '.gmdate('D, d M Y H:i:s', time() + (int) $cachedelay).' GMT'); // This is to avoid to have Expires set by proxy or web server From c135bbfebdae148c936f7d7fbe3fb395bd9bfdaf Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 19:29:57 +0100 Subject: [PATCH 53/71] Fix warning --- htdocs/public/payment/paymentko.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/public/payment/paymentko.php b/htdocs/public/payment/paymentko.php index 88de37b4b11..1336cec30f2 100644 --- a/htdocs/public/payment/paymentko.php +++ b/htdocs/public/payment/paymentko.php @@ -70,6 +70,7 @@ if (isModEnabled('paypal')) { * @var HookManager $hookmanager * @var Societe $mysoc * @var Translate $langs + * @var User $user User object is initialized but empty as it is a public page * * @var string $dolibarr_main_url_root */ @@ -198,6 +199,7 @@ if (!empty($_SESSION['ipaddress'])) { // To avoid to make action twice $ipaddress = $_SESSION['ipaddress']; $errormessage = $_SESSION['errormessage']; + // @phpstan-ignore-next-line if (is_object($object) && method_exists($object, 'call_trigger')) { // Call trigger @phan-suppress-next-line PhanUndeclaredMethod $result = $object->call_trigger('PAYMENTONLINE_PAYMENT_KO', $user); From 93fab3bb4fcac93d726f381cdfe2b20ae9897e83 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Mar 2025 19:34:24 +0100 Subject: [PATCH 54/71] Update actions_sendmails.inc.php --- htdocs/core/actions_sendmails.inc.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index fb754af26fd..efb5c651089 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -306,7 +306,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO $reg = array(); $fromtype = GETPOST('fromtype', 'alpha'); - $emailsendersignature = null; + $emailsendersignature = ''; if ($fromtype === 'robot') { $from = dol_string_nospecial($conf->global->MAIN_MAIL_EMAIL_FROM, ' ', array(",")).' <' . getDolGlobalString('MAIN_MAIL_EMAIL_FROM').'>'; } elseif ($fromtype === 'user') { @@ -326,7 +326,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO $obj = $db->fetch_object($resql); if ($obj) { $from = dol_string_nospecial($obj->label, ' ', array(",")).' <'.$obj->email.'>'; - $emailsendersignature = $obj->signature; + = $obj->signature; } } elseif (preg_match('/from_template_(\d+)/', $fromtype, $reg)) { $sql = 'SELECT rowid, email_from FROM '.MAIN_DB_PREFIX.'c_email_templates'; @@ -386,9 +386,8 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO // Make substitution in email content $substitutionarray = getCommonSubstitutionArray($langs, 0, null, $object); - if (!empty($emailsendersignature)) { - $substitutionarray['__SENDEREMAIL_SIGNATURE__'] = $emailsendersignature; - } + + $substitutionarray['__SENDEREMAIL_SIGNATURE__'] = (empty($emailsendersignature) ? '' : $emailsendersignature); $substitutionarray['__EMAIL__'] = $sendto; $substitutionarray['__CHECK_READ__'] = (is_object($object) && is_object($object->thirdparty)) ? '' : ''; From 729e06a95ed89ff6ee0a277cec2c50b76f5fc113 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Mar 2025 19:34:53 +0100 Subject: [PATCH 55/71] Update actions_sendmails.inc.php --- htdocs/core/actions_sendmails.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index efb5c651089..93ca0de13b6 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -326,7 +326,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO $obj = $db->fetch_object($resql); if ($obj) { $from = dol_string_nospecial($obj->label, ' ', array(",")).' <'.$obj->email.'>'; - = $obj->signature; + $emailsendersignature = $obj->signature; } } elseif (preg_match('/from_template_(\d+)/', $fromtype, $reg)) { $sql = 'SELECT rowid, email_from FROM '.MAIN_DB_PREFIX.'c_email_templates'; From 04998ec7ec484fffc0963499896bd0b5494a48ec Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Mar 2025 19:37:47 +0100 Subject: [PATCH 56/71] Update actions_sendmails.inc.php --- htdocs/core/actions_sendmails.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index 93ca0de13b6..63111a9782c 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -387,7 +387,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO // Make substitution in email content $substitutionarray = getCommonSubstitutionArray($langs, 0, null, $object); - $substitutionarray['__SENDEREMAIL_SIGNATURE__'] = (empty($emailsendersignature) ? '' : $emailsendersignature); + $substitutionarray['__SENDEREMAIL_SIGNATURE__'] = (empty($emailsendersignature) ? $user->signature : $emailsendersignature); $substitutionarray['__EMAIL__'] = $sendto; $substitutionarray['__CHECK_READ__'] = (is_object($object) && is_object($object->thirdparty)) ? '' : ''; From 68676d5ac6c974b5627abb406399f34c31ac657a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 5 Mar 2025 20:00:35 +0100 Subject: [PATCH 57/71] no label property on RecruitmentCandidature --- .../class/recruitmentcandidature.class.php | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index 7ed11f2c436..148613c9824 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -313,17 +313,10 @@ class RecruitmentCandidature extends CommonObject // @phan-suppress-next-line PhanTypeMismatchProperty $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'status')) { - $object->status = self::STATUS_DRAFT; - } - if (property_exists($object, 'date_creation')) { - $object->date_creation = dol_now(); - } - if (property_exists($object, 'date_modification')) { - $object->date_modification = null; - } + $object->status = self::STATUS_DRAFT; + $object->date_creation = dol_now(); + $object->date_modification = null; - // ... // Clear extrafields that are unique if (is_array($object->array_options) && count($object->array_options) > 0) { $extrafields->fetch_name_optionals_label($this->table_element); From 66484095e02419aa6e302ad47a92260e8694acb7 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 20:25:12 +0100 Subject: [PATCH 58/71] Clean code from not used global variable --- ChangeLog | 2 +- dev/build/phpstan/phpstan-baseline.neon | 6 ----- htdocs/comm/propal/class/propal.class.php | 8 +++--- htdocs/core/actions_sendmails.inc.php | 32 ++++++++++------------- 4 files changed, 19 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0ac6d7906a6..b8c397b4bf7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,7 +19,7 @@ WARNING: The following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * The directory /build has been moved into /dev/build. * The use of GETPOST function is not allowed inside extrafields conditions or any strings that contains dynamic code evaluated with dol_eval() - +* The deprecated variable $trigger_name (duplicate of variable $triggersendname) has been removed. You must use $triggersendname everywhere now. ***** ChangeLog for 21.0.0 compared to 20.0 ***** diff --git a/dev/build/phpstan/phpstan-baseline.neon b/dev/build/phpstan/phpstan-baseline.neon index a3490213b80..1bb49a384e7 100644 --- a/dev/build/phpstan/phpstan-baseline.neon +++ b/dev/build/phpstan/phpstan-baseline.neon @@ -7488,12 +7488,6 @@ parameters: count: 1 path: ../../../htdocs/core/actions_sendmails.inc.php - - - message: '#^Variable \$paramname2 might not be defined\.$#' - identifier: variable.undefined - count: 1 - path: ../../../htdocs/core/actions_sendmails.inc.php - - message: '#^Variable \$result might not be defined\.$#' identifier: variable.undefined diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index dc79e395697..bb52fb19522 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2667,11 +2667,11 @@ class Propal extends CommonObject if ($resql) { // Status self::STATUS_REFUSED by default $modelpdf = getDolGlobalString('PROPALE_ADDON_PDF_ODT_CLOSED', $this->model_pdf); - $trigger_name = 'PROPAL_CLOSE_REFUSED'; // used later in call_trigger() + $triggersendname = 'PROPAL_CLOSE_REFUSED'; // used later in call_trigger() - if ($status == self::STATUS_SIGNED) { // Status self::STATUS_SIGNED - $trigger_name = 'PROPAL_CLOSE_SIGNED'; // used later in call_trigger() - $modelpdf = getDolGlobalString('PROPALE_ADDON_PDF_ODT_TOBILL') ? $conf->global->PROPALE_ADDON_PDF_ODT_TOBILL : $this->model_pdf; + if ($status == self::STATUS_SIGNED) { // Status self::STATUS_SIGNED + $triggersendname = 'PROPAL_CLOSE_SIGNED'; // used later in call_trigger() + $modelpdf = getDolGlobalString('PROPALE_ADDON_PDF_ODT_TOBILL', $this->model_pdf); // The connected company is classified as a client $soc = new Societe($this->db); diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index 6492494039c..4152d8a6c95 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -24,24 +24,25 @@ * \brief Code for actions on sending mails from object page */ -// $mysoc must be defined -// $id must be defined -// $paramname may be defined -// $autocopy may be defined (used to know the automatic BCC to add) -// $triggersendname must be set (can be '') -// $actiontypecode can be set -// $object and $subject may be defined /** + * @var Societe $mysoc * @var CommonObject $object * @var Conf $conf * @var DoliDB $db * @var HookManager $hookmanager * @var Societe $mysoc * @var Translate $langs + * @var User $user * - * @var string $dolibarr_main_url_root - * @var string $action + * @var int $id + * @var string $dolibarr_main_url_root + * @var string $action * @var ?string $subject + * @var ?string $triggersendname (can be '') + * @var ?string $sendcontext + * @var ?string $autocopy (used to know the automatic BCC to add) + * @var ?string $actiontypecode + * @var ?string $paramname */ ' @phan-var-force Societe $mysoc @@ -442,9 +443,9 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO $object->email_tocc = $sendtocc; $object->email_tobcc = $sendtobcc; - // Call of triggers (you should have set $triggersendname to execute trigger. $trigger_name is deprecated) - if (!empty($triggersendname) || !empty($trigger_name)) { - $result = $object->call_trigger(empty($triggersendname) ? $trigger_name : $triggersendname, $user); // @phan-suppress-current-line PhanPossiblyUndeclaredGlobalVariable + // Call of triggers (you should have set $triggersendname to execute trigger. + if (!empty($triggersendname)) { + $result = $object->call_trigger($triggersendname, $user); // @phan-suppress-current-line PhanPossiblyUndeclaredGlobalVariable if ($result < 0) { $error++; } @@ -460,12 +461,7 @@ if (($action == 'send' || $action == 'relance') && !GETPOST('addfile') && !GETPO $mesg = $langs->trans('MailSuccessfulySent', $mailfile->getValidAddress($from, 2), $mailfile->getValidAddress($sendto, 2)); setEventMessages($mesg, null, 'mesgs'); - $moreparam = ''; - if (isset($paramval2)) { // @phan-var-suppress-current-line PhanPluginUndeclaredVariableIsset - // @phan-var-suppress-next-line PhanUndeclaredGlobalVariable - $moreparam .= '&'.($paramname2 ? $paramname2 : 'mid').'='.$paramval2; - } - header('Location: '.$_SERVER["PHP_SELF"].'?'.($paramname ?? 'id').'='.(is_object($object) ? $object->id : '').$moreparam); + header('Location: '.$_SERVER["PHP_SELF"].'?'.($paramname ?? 'id').'='.(is_object($object) ? $object->id : '')); exit; } else { $langs->load("other"); From 9a15aeadfcf2148c94f022921c81fccd967ec504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 5 Mar 2025 20:51:39 +0100 Subject: [PATCH 59/71] fix --- htdocs/comm/propal/class/propal.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index bb52fb19522..07b37c1e3d1 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2713,7 +2713,7 @@ class Propal extends CommonObject if (!$notrigger && empty($error)) { // Call trigger - $result = $this->call_trigger($trigger_name, $user); + $result = $this->call_trigger($triggersendname, $user); if ($result < 0) { $error++; } From 41614183812aa3d734f49f9e4499307034a55aea Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 20:51:50 +0100 Subject: [PATCH 60/71] Clean name of var --- htdocs/comm/propal/class/propal.class.php | 6 +++--- htdocs/compta/prelevement/class/bonprelevement.class.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index bb52fb19522..31b5017172b 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2667,10 +2667,10 @@ class Propal extends CommonObject if ($resql) { // Status self::STATUS_REFUSED by default $modelpdf = getDolGlobalString('PROPALE_ADDON_PDF_ODT_CLOSED', $this->model_pdf); - $triggersendname = 'PROPAL_CLOSE_REFUSED'; // used later in call_trigger() + $triggerName = 'PROPAL_CLOSE_REFUSED'; // used later in call_trigger() if ($status == self::STATUS_SIGNED) { // Status self::STATUS_SIGNED - $triggersendname = 'PROPAL_CLOSE_SIGNED'; // used later in call_trigger() + $triggerName = 'PROPAL_CLOSE_SIGNED'; // used later in call_trigger() $modelpdf = getDolGlobalString('PROPALE_ADDON_PDF_ODT_TOBILL', $this->model_pdf); // The connected company is classified as a client @@ -2713,7 +2713,7 @@ class Propal extends CommonObject if (!$notrigger && empty($error)) { // Call trigger - $result = $this->call_trigger($trigger_name, $user); + $result = $this->call_trigger($triggerName, $user); if ($result < 0) { $error++; } diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index d502c49d1c2..c1fd906ff66 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -1514,13 +1514,13 @@ class BonPrelevement extends CommonObject } if (!$error && !$notrigger) { - $triggername = 'DIRECT_DEBIT_ORDER_CREATE'; + $triggerName = 'DIRECT_DEBIT_ORDER_CREATE'; if ($type != 'bank-transfer') { - $triggername = 'CREDIT_TRANSFER_ORDER_CREATE'; + $triggerName = 'CREDIT_TRANSFER_ORDER_CREATE'; } // Call trigger - $result = $this->call_trigger($triggername, $user); + $result = $this->call_trigger($triggerName, $user); if ($result < 0) { $error++; } From 77d2be90876885be1210573ceca6b4bdd9108554 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 20:53:39 +0100 Subject: [PATCH 61/71] Fix CI --- htdocs/recruitment/class/recruitmentcandidature.class.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index 3db699c6d45..af025d957cd 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -313,9 +313,6 @@ class RecruitmentCandidature extends CommonObject // @phan-suppress-next-line PhanTypeMismatchProperty $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; } - if (property_exists($object, 'label')) { - $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; - } if (property_exists($object, 'status')) { $object->status = self::STATUS_DRAFT; } From 941c80d108e9b33d45c3ce5b306669c2dcdad732 Mon Sep 17 00:00:00 2001 From: MDW Date: Wed, 5 Mar 2025 18:25:19 +0100 Subject: [PATCH 62/71] Qual: Fix phan notices (facture/1) --- htdocs/compta/facture/agenda-rec.php | 4 +-- htdocs/compta/facture/agenda.php | 3 +- htdocs/compta/facture/card-rec.php | 50 ++++++++++++++-------------- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/htdocs/compta/facture/agenda-rec.php b/htdocs/compta/facture/agenda-rec.php index 6cdbed1196e..86ce5589799 100644 --- a/htdocs/compta/facture/agenda-rec.php +++ b/htdocs/compta/facture/agenda-rec.php @@ -1,7 +1,7 @@ * Copyright (C) 2024 Frédéric France - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 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 @@ -171,7 +171,7 @@ if ($object->id > 0) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); diff --git a/htdocs/compta/facture/agenda.php b/htdocs/compta/facture/agenda.php index 866a0c4edee..9f56337ccce 100644 --- a/htdocs/compta/facture/agenda.php +++ b/htdocs/compta/facture/agenda.php @@ -1,6 +1,7 @@ * Copyright (C) 2024 Frédéric France + * Copyright (C) 2025 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 @@ -165,7 +166,7 @@ if ($object->id > 0) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); diff --git a/htdocs/compta/facture/card-rec.php b/htdocs/compta/facture/card-rec.php index b90c061e9f3..2a4a0cdb031 100644 --- a/htdocs/compta/facture/card-rec.php +++ b/htdocs/compta/facture/card-rec.php @@ -10,7 +10,7 @@ * Copyright (C) 2016 Meziane Sof * Copyright (C) 2017-2025 Frédéric France * Copyright (C) 2023 Nick Fragoulis - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 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 @@ -473,7 +473,7 @@ if (empty($reshook)) { setEventMessages($line->error, $line->errors, 'errors'); } } elseif ($action == 'update_extras' && $usercancreate) { - $object->oldcopy = dol_clone($object, 2); + $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty // Fill array 'array_options' with data from update form $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml')); @@ -719,14 +719,14 @@ if (empty($reshook)) { $info_bits |= 0x01; } - $fk_parent_line = GETPOST('fk_parent_line', 'int'); + $fk_parent_line = GETPOSTINT('fk_parent_line'); if ($usercanproductignorepricemin && (!empty($price_min) && ((float) price2num($pu_ht) * (1 - (float) price2num($remise_percent) / 100) < (float) price2num($price_min)))) { $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)); setEventMessages($mesg, null, 'errors'); } else { // Insert line - $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $price_base_type, $info_bits, 0, $pu_ttc, $type, -1, $special_code, $label, $fk_unit, 0, $date_start_fill, $date_end_fill, $fournprice, $buyingprice, $fk_parent_line); + $result = $object->addline($desc, $pu_ht, (float) $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $price_base_type, $info_bits, 0, $pu_ttc, $type, -1, $special_code, $label, (int) $fk_unit, 0, $date_start_fill, $date_end_fill, (int) $fournprice, (int) $buyingprice, $fk_parent_line); if ($result > 0) { // Define output language and generate document @@ -919,9 +919,9 @@ if (empty($reshook)) { $result = $object->updateline( GETPOSTINT('lineid'), $description, - $pu_ht, - $qty, - $vat_rate, + (float) $pu_ht, + (float) $qty, + (float) $vat_rate, $localtax1_rate, $localtax1_rate, GETPOSTINT('productid'), @@ -935,13 +935,13 @@ if (empty($reshook)) { $special_code, $label, GETPOST('units'), - $pu_ht_devise, + (float) $pu_ht_devise, 0, $date_start_fill, $date_end_fill, - $fournprice, - $buyingprice, - $fk_parent_line + (int) $fournprice, + (int) $buyingprice, + (int) $fk_parent_line ); if ($result >= 0) { @@ -1116,7 +1116,7 @@ if ($action == 'create') { // Payment mode print ""; @@ -1155,7 +1155,7 @@ if ($action == 'create') { // Bank account if ($object->fk_account > 0) { print ""; } @@ -1368,7 +1368,7 @@ if ($action == 'create') { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); @@ -1442,9 +1442,9 @@ if ($action == 'create') { print '
'; print $langs->trans("Categories"); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index df13db0447c..518f45860c8 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1517,7 +1517,7 @@ function get_left_menu_billing($mainmenu, &$newmenu, $usemenuhider = 1, $leftmen $newmenu->add("/compta/facture/stats/index.php?leftmenu=customers_bills_stats", $langs->trans("Statistics"), 1, $user->hasRight('facture', 'lire'), '', $mainmenu, 'customers_bills_stats'); // Categories - if (isModEnabled('categorie')) { + if (isModEnabled('category')) { $langs->load("categories"); $newmenu->add("/categories/index.php?leftmenu=cat&type=14", $langs->trans("Categories"), 1, $user->rights->categorie->lire, '', $mainmenu, 'cat'); } From fab5a0693acc31ffc08161561d161bef237c507a Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 27 Feb 2025 09:37:55 +0100 Subject: [PATCH 04/71] CI --- htdocs/core/modules/modCategorie.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/modules/modCategorie.class.php b/htdocs/core/modules/modCategorie.class.php index fc178d621d9..4584c7d8bba 100644 --- a/htdocs/core/modules/modCategorie.class.php +++ b/htdocs/core/modules/modCategorie.class.php @@ -170,7 +170,7 @@ class modCategorie extends DolibarrModules if (isModEnabled('order')) { $typeexample .= ($typeexample ? " / " : "")."16=Order"; } - if (isModEnabled('facture')) { + if (isModEnabled('invoice')) { $typeexample .= ($typeexample ? " / " : "")."17=Invoice"; } @@ -496,13 +496,13 @@ class modCategorie extends DolibarrModules } // 17 Invoice - if (isModEnabled("facture")) { + if (isModEnabled("invoice")) { ++$r; $this->exportTagLinks( $r, - 17, + 'invoice', 'Facture', - 'isModEnabled("facture")', + 'isModEnabled("invoice")', ['facture', 'facture', 'export'], [ 'rowid' => [ From dfc72d40289df55298b921ea54d25708ca5356a6 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 27 Feb 2025 09:45:19 +0100 Subject: [PATCH 05/71] CI --- htdocs/compta/facture/class/facture.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 04492e92921..b3c52aff32a 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -4718,14 +4718,14 @@ class Facture extends CommonInvoice */ /** - * Sets object to supplied categories. + * Sets object to given categories. * - * Deletes object from existing categories not supplied. * Adds it to non existing supplied categories. * Existing categories are left untouch. * * @param int[]|int $categories Category or categories IDs - * @return void + * + * @return int Return integer <0 if KO, >0 if OK */ public function setCategories($categories) { From 7eb0f22084e5fa45a85da6a24d26f4f0fea6aed6 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 27 Feb 2025 10:01:05 +0100 Subject: [PATCH 06/71] CI --- htdocs/compta/facture/card.php | 2 +- htdocs/core/modules/modCategorie.class.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index f86cdae5981..205fd16721b 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -4112,7 +4112,7 @@ if ($action == 'create') { print '
'.$langs->trans("Categories").''; $cate_arbo = $form->select_all_categories(Categorie::TYPE_INVOICE, '', 'parent', 64, 0, 1); $arrayselected = GETPOST('categories', 'array'); - print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, $arrayselected, 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, '0'); print "
'; + print '
'; print '
'; } // Output Kanban @@ -2169,7 +2169,7 @@ if ($num > 0) { } else { // Show line of result $j = 0; - print '
'.$langs->trans('PaymentConditionsShort').''; print img_picto('', 'payment', 'class="pictofixedwidth"'); - print $form->getSelectConditionsPaiements($cond_reglement_id, 'cond_reglement_id', 1, 1, 0, 'maxwidth200 widthcentpercentminusx', $deposit_percent); + print $form->getSelectConditionsPaiements($cond_reglement_id, 'cond_reglement_id', 1, 1, 0, 'maxwidth200 widthcentpercentminusx', (float) $deposit_percent); print '
'.$langs->trans('PaymentMode').''; print img_picto('', 'bank', 'class="pictofixedwidth"'); - print $form->select_types_paiements($mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx', 1); + print $form->select_types_paiements((string) $mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth200 widthcentpercentminusx', 1); print '
'; $incoterm_id = GETPOST('incoterm_id'); $location_incoterms = GETPOST('location_incoterms'); @@ -2176,7 +2176,7 @@ if ($action == 'create' && $usercancreate) { print '
'.$form->editfieldkey("Currency", 'multicurrency_code', '', $object, 0).''; - print img_picto('', 'currency', 'class="pictofixedwidth"').$form->selectMultiCurrency(((GETPOSTISSET('multicurrency_code') && !GETPOST('changecompany')) ? GETPOST('multicurrency_code') : $currency_code), 'multicurrency_code', 0, '', 0, 'maxwidth200 widthcentpercentminusx'); + print img_picto('', 'currency', 'class="pictofixedwidth"').$form->selectMultiCurrency(((GETPOSTISSET('multicurrency_code') && !GETPOST('changecompany')) ? GETPOST('multicurrency_code') : $currency_code), 'multicurrency_code', 0, '', false, 'maxwidth200 widthcentpercentminusx'); print '
'.$langs->trans('NotePublic').''; - $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%'); + $doleditor = new DolEditor('note_public', (string) $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%'); print $doleditor->Create(1); // print ''; print '
'.$langs->trans('NotePrivate').''; - $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%'); + $doleditor = new DolEditor('note_private', (string) $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%'); print $doleditor->Create(1); // print ''; print '
'; $editenable = $usercancreate && $object->statut == Commande::STATUS_DRAFT; - print $form->editfieldkey("Date", 'date', '', $object, $editenable); + print $form->editfieldkey("Date", 'date', '', $object, (int) $editenable); print ''; if ($action == 'editdate') { print ''; @@ -2711,7 +2711,7 @@ if ($action == 'create' && $usercancreate) { // Delivery date planned print '
'; $editenable = $usercancreate; - print $form->editfieldkey("DateDeliveryPlanned", 'date_livraison', '', $object, $editenable); + print $form->editfieldkey("DateDeliveryPlanned", 'date_livraison', '', $object, (int) $editenable); print ''; if ($action == 'editdate_livraison') { print ''; @@ -2733,12 +2733,12 @@ if ($action == 'create' && $usercancreate) { // Delivery delay print '
'; $editenable = $usercancreate; - print $form->editfieldkey("AvailabilityPeriod", 'availability', '', $object, $editenable); + print $form->editfieldkey("AvailabilityPeriod", 'availability', '', $object, (int) $editenable); print ''; if ($action == 'editavailability') { - $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'availability_id', 1); + $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->availability_id, 'availability_id', 1); } else { - $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'none', 1); + $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->availability_id, 'none', 1); } print '
'; $editenable = $usercancreate; - print $form->editfieldkey("SendingMethod", 'shippingmethod', '', $object, $editenable); + print $form->editfieldkey("SendingMethod", 'shippingmethod', '', $object, (int) $editenable); print ''; if ($action == 'editshippingmethod') { - $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'shipping_method_id', 1); + $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->shipping_method_id, 'shipping_method_id', 1); } else { - $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'none'); + $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->shipping_method_id, 'none'); } print '
'; $editenable = $usercancreate; - print $form->editfieldkey("Warehouse", 'warehouse', '', $object, $editenable); + print $form->editfieldkey("Warehouse", 'warehouse', '', $object, (int) $editenable); print ''; if ($action == 'editwarehouse') { $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'warehouse_id', 1); @@ -2778,24 +2778,24 @@ if ($action == 'create' && $usercancreate) { // Source reason (why we have an order) print '
'; $editenable = $usercancreate; - print $form->editfieldkey("Source", 'demandreason', '', $object, $editenable); + print $form->editfieldkey("Source", 'demandreason', '', $object, (int) $editenable); print ''; if ($action == 'editdemandreason') { - $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'demand_reason_id', 1); + $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->demand_reason_id, 'demand_reason_id', 1); } else { - $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'none'); + $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->demand_reason_id, 'none'); } print '
'; $editenable = $usercancreate; - print $form->editfieldkey("PaymentConditionsShort", 'conditions', '', $object, $editenable); + print $form->editfieldkey("PaymentConditionsShort", 'conditions', '', $object, (int) $editenable); print ''; if ($action == 'editconditions') { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent); } else { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none', 1, '', 1, $object->deposit_percent); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->cond_reglement_id, 'none', 1, '', 1, $object->deposit_percent); } print '
'; $editenable = $usercancreate; - print $form->editfieldkey("PaymentMode", 'mode', '', $object, $editenable); + print $form->editfieldkey("PaymentMode", 'mode', '', $object, (int) $editenable); print ''; if ($action == 'editmode') { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1); + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1); } else { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'none'); + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'none'); } print '
'; $editenable = $usercancreate; - print $form->editfieldkey("IncotermLabel", 'incoterm', '', $object, $editenable); + print $form->editfieldkey("IncotermLabel", 'incoterm', '', $object, (int) $editenable); print ''; if ($action != 'editincoterm') { @@ -2864,12 +2864,12 @@ if ($action == 'create' && $usercancreate) { if (getDolGlobalString('BANK_ASK_PAYMENT_BANK_DURING_ORDER') && isModEnabled("bank")) { print '
'; $editenable = $usercancreate; - print $form->editfieldkey("BankAccount", 'bankaccount', '', $object, $editenable); + print $form->editfieldkey("BankAccount", 'bankaccount', '', $object, (int) $editenable); print ''; if ($action == 'editbankaccount') { - $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1); + $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'fk_account', 1); } else { - $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none'); + $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none'); } print '
'; - print 'socid) ? " disabled" : "").'>'; + print 'socid) ? " disabled" : "").'>'; print ''; - print $form->getSelectConditionsPaiements($search_fk_cond_reglement, 'search_fk_cond_reglement', 1, 1, 1); + print $form->getSelectConditionsPaiements((int) $search_fk_cond_reglement, 'search_fk_cond_reglement', 1, 1, 1); print ''; - print ''; + print ''; print ''; + print ''; print dol_print_date($db->jdate($obj->delivery_date), 'day'); print '
'.$langs->trans("CreatedBy").''; print img_picto('', 'user', 'class="pictofixedwidth"'); -print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300'); +print $form->select_dolusers($userid, 'userid', 1, null, 0, '', '', '0', 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300'); // Status print '
'.$langs->trans("Status").''; if ($mode == 'customer') { diff --git a/htdocs/core/ajax/saveinplace.php b/htdocs/core/ajax/saveinplace.php index 9d94c28aac1..cabbe1a6e05 100644 --- a/htdocs/core/ajax/saveinplace.php +++ b/htdocs/core/ajax/saveinplace.php @@ -1,6 +1,6 @@ - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -164,7 +164,7 @@ if (!empty($field) && !empty($element) && !empty($table_element) && !empty($fk_e } //var_dump(GETPOST('action','aZ09')); //var_dump($newelement.'-'.$subelement."-".$feature."-".$object_id); - $check_access = restrictedArea($user, $feature, $object_id, '', $feature2); + $check_access = restrictedArea($user, $feature, $object_id, '', (string) $feature2); //var_dump($user->rights); /* if (!empty($user->rights->$newelement->creer) || !empty($user->rights->$newelement->create) || !empty($user->rights->$newelement->write) diff --git a/htdocs/core/modules/commande/mod_commande_saphir.php b/htdocs/core/modules/commande/mod_commande_saphir.php index bb0603ef0f0..d408b1093f5 100644 --- a/htdocs/core/modules/commande/mod_commande_saphir.php +++ b/htdocs/core/modules/commande/mod_commande_saphir.php @@ -4,7 +4,7 @@ * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2008 Raphael Bertrand (Resultic) * Copyright (C) 2019-2024 Frédéric France - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 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 @@ -150,7 +150,7 @@ class mod_commande_saphir extends ModeleNumRefCommandes $date = dol_now(); } - $numFinal = get_next_value($db, $mask, 'commande', 'ref', '', $objsoc, $date, 'next', false, null, $entity); + $numFinal = get_next_value($db, $mask, 'commande', 'ref', '', $objsoc, (int) $date, 'next', false, null, $entity); return $numFinal; } From c2c44272fb7c46dc2710be6a8e3776ffb951ea91 Mon Sep 17 00:00:00 2001 From: MDW Date: Tue, 4 Mar 2025 19:19:08 +0100 Subject: [PATCH 28/71] Qual: Optimize logo --- htdocs/theme/dolibarr_logo.svg | 138 +-------------------------------- 1 file changed, 1 insertion(+), 137 deletions(-) diff --git a/htdocs/theme/dolibarr_logo.svg b/htdocs/theme/dolibarr_logo.svg index 72795dfbbe7..94b7c1a6589 100644 --- a/htdocs/theme/dolibarr_logo.svg +++ b/htdocs/theme/dolibarr_logo.svg @@ -1,137 +1 @@ - - - -ERP/CRM + From 8162a78ce8edd3356a3463e74f991eebac2669a7 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 12:42:50 +0100 Subject: [PATCH 29/71] Removed deprecated code --- htdocs/stripe/class/stripe.class.php | 291 --------------------------- 1 file changed, 291 deletions(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index e0e1fc29508..cc08b6dfb19 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -61,12 +61,6 @@ class Stripe extends CommonObject */ public $entity; - /** - * @var string - * @deprecated Was used by createPaymentStripe only that is deprecated - */ - public $result; - /** * @var string */ @@ -1155,289 +1149,4 @@ class Stripe extends CommonObject return $sepa; } - - - /** - * Create charge. - * This was called by page htdocs/stripe/payment.php and may be deprecated. - * - * @param float $amount Amount to pay - * @param string $currency EUR, GPB... - * @param string $origin Object type to pay (order, invoice, contract...) - * @param int $item Object id to pay - * @param string $source src_xxxxx or card_xxxxx or pm_xxxxx - * @param string $customer Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe() - * @param string $account Stripe account ref 'acc_xxxxxxxxxxxxx' via getStripeAccount() - * @param int<0,1> $status Status (0=test, 1=live) - * @param int<0,1> $usethirdpartyemailforreceiptemail Use thirdparty email as receipt email - * @param bool $capture Set capture flag to true (take payment) or false (wait) - * @return Stripe - * @deprecated - */ - public function createPaymentStripe($amount, $currency, $origin, $item, $source, $customer, $account, $status = 0, $usethirdpartyemailforreceiptemail = 0, $capture = true) - { - global $conf; - - $error = 0; - - if (empty($status)) { - $service = 'StripeTest'; - } else { - $service = 'StripeLive'; - } - - $sql = "SELECT sa.key_account as key_account, sa.fk_soc, sa.entity"; - $sql .= " FROM ".MAIN_DB_PREFIX."societe_account as sa"; - $sql .= " WHERE sa.key_account = '".$this->db->escape($customer)."'"; - //$sql.= " AND sa.entity IN (".getEntity('societe').")"; - $sql .= " AND sa.site = 'stripe' AND sa.status = ".((int) $status); - $sql .= " ORDER BY sa.site_account DESC, sa.rowid DESC"; // To get the entry with a site_account defined in priority - - dol_syslog(get_class($this)."::fetch", LOG_DEBUG); - $result = $this->db->query($sql); - if ($result) { - if ($this->db->num_rows($result)) { - $obj = $this->db->fetch_object($result); - $key = $obj->fk_soc; - } else { - $key = null; - } - } else { - $key = null; - } - - $arrayzerounitcurrency = array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'); - if (!in_array($currency, $arrayzerounitcurrency)) { - $stripeamount = $amount * 100; - } else { - $stripeamount = $amount; - } - - $societe = new Societe($this->db); - if ($key > 0) { - $societe->fetch($key); - } - - $description = ""; - $ref = ""; - $invoice = null; - if ($origin == 'order') { - $order = new Commande($this->db); - $order->fetch($item); - $ref = $order->ref; - $description = "ORD=".$ref.".CUS=".$societe->id.".PM=stripe"; - } elseif ($origin == 'invoice') { - $invoice = new Facture($this->db); - $invoice->fetch($item); - $ref = $invoice->ref; - $description = "INV=".$ref.".CUS=".$societe->id.".PM=stripe"; - } - - $ipaddress = getUserRemoteIP(); - - $metadata = array( - "dol_id" => (string) $item, - "dol_type" => (string) $origin, - "dol_thirdparty_id" => (string) $societe->id, - 'dol_thirdparty_name' => $societe->name, - 'dol_version' => DOL_VERSION, - 'dol_entity' => $conf->entity, - 'ipaddress' => $ipaddress - ); - $return = new Stripe($this->db); - try { - // Force to use the correct API key - global $stripearrayofkeysbyenv; - \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); - - if (empty($conf->stripeconnect->enabled)) { // With a common Stripe account - if (preg_match('/pm_/i', $source)) { - $stripecard = $source; - $amountstripe = $stripeamount; - $FULLTAG = 'PFBO'; // Payment From Back Office - $stripe = $return; - $amounttopay = $amount; - $servicestatus = $status; - - dol_syslog("* createPaymentStripe get stripeacc", LOG_DEBUG); - $stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account if it exists (no network access here) - - dol_syslog("* createPaymentStripe Create payment for customer ".$customer." on source card ".$stripecard.", amounttopay=".$amounttopay.", amountstripe=".$amountstripe.", FULLTAG=".$FULLTAG, LOG_DEBUG); - - // Create payment intent and charge payment (confirmnow = true) - $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $invoice, $customer, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard, 1); - - $charge = new stdClass(); - if ($paymentintent->status == 'succeeded') { - $charge->status = 'ok'; - } else { - $charge->status = 'failed'; - $charge->failure_code = $stripe->code; - $charge->failure_message = $stripe->error; - $charge->failure_declinecode = $stripe->declinecode; - $stripefailurecode = $stripe->code; - $stripefailuremessage = $stripe->error; - $stripefailuredeclinecode = $stripe->declinecode; - } - } elseif (preg_match('/acct_/i', $source)) { - $charge = \Stripe\Charge::create(array( - "amount" => "$stripeamount", - "currency" => "$currency", - "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - "description" => "Stripe payment: ".$description, - "capture" => $capture, - "metadata" => $metadata, - "source" => "$source" - )); - } else { - $paymentarray = array( - "amount" => "$stripeamount", - "currency" => "$currency", - "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - "description" => "Stripe payment: ".$description, - "capture" => $capture, - "metadata" => $metadata, - "source" => (string) $source, - "customer" => (string) $customer - ); - - if ($societe->email && $usethirdpartyemailforreceiptemail) { - $paymentarray["receipt_email"] = $societe->email; - } - - $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description")); - } - } else { - // With Stripe Connect - $fee = $amount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE; - if ($fee >= $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL > $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) { - $fee = getDolGlobalString('STRIPE_APPLICATION_FEE_MAXIMAL'); - } elseif ($fee < $conf->global->STRIPE_APPLICATION_FEE_MINIMAL) { - $fee = getDolGlobalString('STRIPE_APPLICATION_FEE_MINIMAL'); - } - - if (!in_array($currency, $arrayzerounitcurrency)) { - $stripefee = round($fee * 100); - } else { - $stripefee = round($fee); - } - - $paymentarray = array( - "amount" => "$stripeamount", - "currency" => "$currency", - "statement_descriptor_suffix" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - "description" => "Stripe payment: ".$description, - "capture" => $capture, - "metadata" => $metadata, - "source" => (string) $source, - "customer" => (string) $customer - ); - if ($conf->entity != $conf->global->STRIPECONNECT_PRINCIPAL && $stripefee > 0) { - $paymentarray["application_fee_amount"] = $stripefee; - } - if ($societe->email && $usethirdpartyemailforreceiptemail) { - $paymentarray["receipt_email"] = $societe->email; - } - - if (preg_match('/pm_/i', $source)) { - $stripecard = $source; - $amountstripe = $stripeamount; - $FULLTAG = 'PFBO'; // Payment From Back Office - $stripe = $return; - $amounttopay = $amount; - $servicestatus = $status; - - dol_syslog("* createPaymentStripe get stripeacc", LOG_DEBUG); - $stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account if it exists (no network access here) - - dol_syslog("* createPaymentStripe Create payment on card ".$stripecard.", amounttopay=".$amounttopay.", amountstripe=".$amountstripe.", FULLTAG=".$FULLTAG, LOG_DEBUG); - - // Create payment intent and charge payment (confirmnow = true) - $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $invoice, $customer, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard, 1); - - $charge = new stdClass(); - if ($paymentintent->status == 'succeeded') { - $charge->status = 'ok'; - $charge->id = $paymentintent->id; - } else { - $charge->status = 'failed'; - $charge->failure_code = $stripe->code; - $charge->failure_message = $stripe->error; - $charge->failure_declinecode = $stripe->declinecode; - } - } else { - $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description", "stripe_account" => "$account")); - } - } - '@phan-var-force stdClass|\Stripe\Charge $charge'; - /* - if (isset($charge->id)) { - } - */ - - $return->result = 'success'; - $return->id = $charge->id; - - if (preg_match('/pm_/i', $source)) { - $return->message = 'Payment retrieved by card status = '.$charge->status; - } else { - if ($charge->source->type == 'card') { - $return->message = $charge->source->card->brand." ....".$charge->source->card->last4; - } elseif ($charge->source->type == 'three_d_secure') { - $stripe = new Stripe($this->db); - $src = \Stripe\Source::retrieve((string) $charge->source->three_d_secure->card, array( - "stripe_account" => $stripe->getStripeAccount($service) - )); - $return->message = $src->card->brand." ....".$src->card->last4; - } else { - $return->message = $charge->id; - } - } - } catch (\Stripe\Exception\CardException $e) { - include DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; - // Since it's a decline, \Stripe\Exception\Card will be caught - $body = $e->getJsonBody(); - $err = $body['error']; - - $return->result = 'error'; - $return->id = $err['charge']; - $return->type = $err['type']; - $return->code = $err['code']; - $return->message = $err['message']; - $body = "Error:
".$return->id." ".$return->message." "; - $subject = '[Alert] Payment error using Stripe'; - $cmailfile = new CMailFile($subject, $conf->global->ONLINE_PAYMENT_SENDEMAIL, $conf->global->MAIN_INFO_SOCIETE_MAIL, $body); - $cmailfile->sendfile(); - - $error++; - dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe'); - } catch (\Stripe\Exception\RateLimitException $e) { - // Too many requests made to the API too quickly - $error++; - dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe'); - } catch (\Stripe\Exception\InvalidRequestException $e) { - // Invalid parameters were supplied to Stripe's API - $error++; - dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe'); - } catch (\Stripe\Exception\AuthenticationException $e) { - // Authentication with Stripe's API failed - // (maybe you changed API keys recently) - $error++; - dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe'); - } catch (\Stripe\Exception\ApiConnectionException $e) { - // Network communication with Stripe failed - $error++; - dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe'); - } catch (\Stripe\Exception\ExceptionInterface $e) { - // Display a very generic error to the user, and maybe send - // yourself an email - $error++; - dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe'); - } catch (Exception $e) { - // Something else happened, completely unrelated to Stripe - $error++; - dol_syslog($e->getMessage(), LOG_WARNING, 0, '_stripe'); - } - return $return; - } } From 739bda4fc4b7727337d359a34367c773477d461f Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 12:52:02 +0100 Subject: [PATCH 30/71] Fix remove status for kanban tr (there is only 1 tr for all invoices) --- htdocs/compta/facture/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 66cd5e986a3..1f5e84d6a50 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -2149,7 +2149,7 @@ if ($num > 0) { if ($mode == 'kanban') { if ($i == 0) { - print '
'; + print '
'; print '
'; } // Output Kanban From 0ef806e15a2cfa198fe8887ba0867f29488b779d Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Wed, 5 Mar 2025 12:58:04 +0100 Subject: [PATCH 31/71] Close #33309 --- htdocs/comm/propal/list.php | 4 ++-- htdocs/compta/facture/list.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 79e32cc27d7..55f1df8d6a9 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -1853,11 +1853,11 @@ while ($i < $imaxinloop) { print '
'; + print ''; if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined $selected = 0; if (in_array($obj->rowid, $arrayofselected)) { diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 1f5e84d6a50..455c1a358b9 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -2169,7 +2169,7 @@ if ($num > 0) { } else { // Show line of result $j = 0; - print '
".$langs->trans("PaymentMode").""; print img_picto('', 'payment', 'class="pictofixedwidth"'); - print $form->select_types_paiements(GETPOSTISSET('mode_reglement_id') ? GETPOSTINT('mode_reglement_id') : $object->mode_reglement_id, 'mode_reglement_id', '', 0, 1, 0, 0, 1, '', 1); + print $form->select_types_paiements((string) (GETPOSTISSET('mode_reglement_id') ? GETPOSTINT('mode_reglement_id') : $object->mode_reglement_id), 'mode_reglement_id', '', 0, 1, 0, 0, 1, '', 1); //$form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', '', 1); print "
".$langs->trans('BankAccount').""; - $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none'); + $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none'); print "
'; print '
'; if ($action == 'editconditions') { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id'); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->cond_reglement_id, 'cond_reglement_id'); } else { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'none'); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->cond_reglement_id, 'none'); } print '
'; print ''; if ($action == 'editmode') { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1); + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1); } else { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'none'); + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->mode_reglement_id, 'none'); } print ''; @@ -1480,9 +1480,9 @@ if ($action == 'create') { print ''; if ($action == 'editbankaccountcustomer') { - $form->formRib($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_societe_rib, 'accountcustomerid', 'fk_soc='.$object->socid, 1, 1); + $form->formRib($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_societe_rib, 'accountcustomerid', 'fk_soc='.$object->socid, 1, 1); } else { - $form->formRib($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_societe_rib, 'none', '', 0, 1); + $form->formRib($_SERVER['PHP_SELF'] . '?id=' . $object->id, (string) $object->fk_societe_rib, 'none', '', 0, 1); } print ""; print ''; @@ -1499,9 +1499,9 @@ if ($action == 'create') { print ''; print ''; if ($action == 'editbankaccount') { - $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1); + $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'fk_account', 1); } else { - $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none'); + $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none'); } print ""; print ''; @@ -1614,7 +1614,7 @@ if ($action == 'create') { // Max period / Rest period print ''; if ($action == 'nb_gen_max' || $object->frequency > 0) { - print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $user->hasRight('facture', 'creer')); + print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', (string) $object->nb_gen_max, $object, $user->hasRight('facture', 'creer')); } else { print $langs->trans("MaxPeriodNumber"); } @@ -1630,7 +1630,7 @@ if ($action == 'create') { // Status of auto generated invoices print ''; if ($action == 'auto_validate' || $object->frequency > 0) { - print $form->editfieldkey($langs->trans("StatusOfAutoGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $user->hasRight('facture', 'creer')); + print $form->editfieldkey($langs->trans("StatusOfAutoGeneratedInvoices"), 'auto_validate', (string) $object->auto_validate, $object, $user->hasRight('facture', 'creer')); } else { print $langs->trans("StatusOfAutoGeneratedInvoices"); } @@ -1645,7 +1645,7 @@ if ($action == 'create') { print ''; print ''; if ($action == 'generate_pdf' || $object->frequency > 0) { - print $form->editfieldkey($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $user->hasRight('facture', 'creer')); + print $form->editfieldkey($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', (string) $object->generate_pdf, $object, $user->hasRight('facture', 'creer')); } else { print $langs->trans("StatusOfGeneratedDocuments"); } From cf7b7009ae78931f4956721f9cab405e2c60c7aa Mon Sep 17 00:00:00 2001 From: MDW Date: Wed, 5 Mar 2025 18:51:14 +0100 Subject: [PATCH 63/71] Fix writeHTMLCell arguments --- htdocs/core/modules/expedition/doc/pdf_merou.modules.php | 2 +- htdocs/core/modules/facture/doc/pdf_crabe.modules.php | 4 ++-- htdocs/core/modules/facture/doc/pdf_octopus.modules.php | 4 ++-- htdocs/core/modules/facture/doc/pdf_sponge.modules.php | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/core/modules/expedition/doc/pdf_merou.modules.php b/htdocs/core/modules/expedition/doc/pdf_merou.modules.php index bdc5dacba98..9557bd9c403 100644 --- a/htdocs/core/modules/expedition/doc/pdf_merou.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_merou.modules.php @@ -633,7 +633,7 @@ class pdf_merou extends ModelePdfExpedition $label .= $object->tracking_url; } $pdf->SetFont('', 'B', $default_font_size - 3); - $pdf->writeHTMLCell(50, 8, '', '', $label, 0, 1, false, true, 'L'); + $pdf->writeHTMLCell(50, 8, null, null, $label, 0, 1, false, true, 'L'); } } } else { diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index bdf3cd1c060..ed77866c1f8 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1336,7 +1336,7 @@ class pdf_crabe extends ModelePDFFactures if ($this->emetteur->country_code == 'FR') { if (getDolGlobalInt('TAX_MODE') == 1) { $pdf->SetXY($this->marge_gauche, $posy); - $pdf->writeHTMLCell(80, 5, '', '', $outputlangs->transnoentities("MentionVATDebitOptionIsOn"), 0, 1); + $pdf->writeHTMLCell(80, 5, null, null, $outputlangs->transnoentities("MentionVATDebitOptionIsOn"), 0, 1); $posy = $pdf->GetY() + 1; } @@ -1364,7 +1364,7 @@ class pdf_crabe extends ModelePDFFactures $linktopay = $langs->trans("ToOfferALinkForOnlinePayment", $servicename).' '.$outputlangs->transnoentities("ClickHere").''; $pdf->SetXY($this->marge_gauche, $posy); - $pdf->writeHTMLCell(80, 5, '', '', dol_htmlentitiesbr($linktopay), 0, 1); + $pdf->writeHTMLCell(80, 5, null, null, dol_htmlentitiesbr($linktopay), 0, 1); $posy = $pdf->GetY() + 1; } diff --git a/htdocs/core/modules/facture/doc/pdf_octopus.modules.php b/htdocs/core/modules/facture/doc/pdf_octopus.modules.php index cf5e3aa55f2..115abe3d4f5 100644 --- a/htdocs/core/modules/facture/doc/pdf_octopus.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_octopus.modules.php @@ -1508,7 +1508,7 @@ class pdf_octopus extends ModelePDFFactures if ($this->emetteur->country_code == 'FR') { if (getDolGlobalInt('TAX_MODE') == 1) { $pdf->SetXY($this->marge_gauche, $posy); - $pdf->writeHTMLCell(80, 5, '', '', $outputlangs->transnoentities("MentionVATDebitOptionIsOn"), 0, 1); + $pdf->writeHTMLCell(80, 5, null, null, $outputlangs->transnoentities("MentionVATDebitOptionIsOn"), 0, 1); $posy = $pdf->GetY() + 1; } @@ -1548,7 +1548,7 @@ class pdf_octopus extends ModelePDFFactures $linktopay = $langs->trans("ToOfferALinkForOnlinePayment", $servicename).' '.$outputlangs->transnoentities("ClickHere").''; $pdf->SetXY($this->marge_gauche, $posy); - $pdf->writeHTMLCell($posxend - $this->marge_gauche, 5, '', '', dol_htmlentitiesbr($linktopay), 0, 1); + $pdf->writeHTMLCell($posxend - $this->marge_gauche, 5, null, null, dol_htmlentitiesbr($linktopay), 0, 1); $posy = $pdf->GetY() + 1; } diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index c93c91d4ae9..31d8089f63e 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1438,7 +1438,7 @@ class pdf_sponge extends ModelePDFFactures if ($this->emetteur->country_code == 'FR') { if (getDolGlobalInt('TAX_MODE') == 1) { $pdf->SetXY($this->marge_gauche, $posy); - $pdf->writeHTMLCell(80, 5, '', '', $outputlangs->transnoentities("MentionVATDebitOptionIsOn"), 0, 1); + $pdf->writeHTMLCell(80, 5, null, null, $outputlangs->transnoentities("MentionVATDebitOptionIsOn"), 0, 1); $posy = $pdf->GetY() + 1; } @@ -1466,7 +1466,7 @@ class pdf_sponge extends ModelePDFFactures $linktopay = $langs->trans("ToOfferALinkForOnlinePayment", $servicename).' '.$outputlangs->transnoentities("ClickHere").''; $pdf->SetXY($this->marge_gauche, $posy); - $pdf->writeHTMLCell($posxend - $this->marge_gauche, 5, '', '', dol_htmlentitiesbr($linktopay), 0, 1); + $pdf->writeHTMLCell($posxend - $this->marge_gauche, 5, null, null, dol_htmlentitiesbr($linktopay), 0, 1); $posy = $pdf->GetY() + 1; } From 56e354e1128d1cb28f42674edfaf0ed011542513 Mon Sep 17 00:00:00 2001 From: MDW Date: Wed, 5 Mar 2025 19:38:05 +0100 Subject: [PATCH 64/71] Qual: Fix phan notices (facture/2) --- dev/tools/phan/baseline.txt | 21 +-- dev/tools/phan/config_fixer.php | 3 +- htdocs/compta/facture/card-rec.php | 4 +- htdocs/compta/facture/card.php | 74 ++++----- .../facture/class/facture-rec.class.php | 156 +++++++++--------- .../facture/class/factureligne.class.php | 16 +- .../facture/class/paymentterm.class.php | 4 +- htdocs/compta/facture/contact.php | 6 +- htdocs/compta/facture/document.php | 3 +- htdocs/compta/facture/prelevement.php | 16 +- htdocs/core/class/html.form.class.php | 8 +- htdocs/core/lib/functions.lib.php | 10 +- .../modules/facture/doc/pdf_crabe.modules.php | 8 +- 13 files changed, 162 insertions(+), 167 deletions(-) diff --git a/dev/tools/phan/baseline.txt b/dev/tools/phan/baseline.txt index 79afcf466e4..5eef4ce5338 100644 --- a/dev/tools/phan/baseline.txt +++ b/dev/tools/phan/baseline.txt @@ -9,10 +9,10 @@ */ return [ // # Issue statistics: - // PhanTypeMismatchArgument : 1110+ occurrences + // PhanTypeMismatchArgument : 1000+ occurrences // PhanUndeclaredProperty : 470+ occurrences - // PhanTypeMismatchArgumentNullable : 270+ occurrences - // PhanTypeMismatchProperty : 150+ occurrences + // PhanTypeMismatchArgumentNullable : 260+ occurrences + // PhanTypeMismatchProperty : 140+ occurrences // PhanUndeclaredGlobalVariable : 100+ occurrences // PhanTypeExpectedObjectPropAccess : 20+ occurrences // PhanTypeInvalidDimOffset : 20+ occurrences @@ -205,22 +205,15 @@ return [ 'htdocs/compta/deplacement/class/deplacement.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/deplacement/class/deplacementstats.class.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/deplacement/stats/index.php' => ['PhanTypeMismatchArgument'], - 'htdocs/compta/facture/agenda-rec.php' => ['PhanTypeMismatchArgument'], - 'htdocs/compta/facture/agenda.php' => ['PhanTypeMismatchArgument'], - 'htdocs/compta/facture/card-rec.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty'], - 'htdocs/compta/facture/card.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanTypeMismatchProperty', 'PhanUndeclaredProperty'], + 'htdocs/compta/facture/card-rec.php' => ['PhanTypeMismatchArgument'], + 'htdocs/compta/facture/card.php' => ['PhanUndeclaredProperty'], 'htdocs/compta/facture/class/api_invoices.class.php' => ['PhanTypeMismatchArgumentProbablyReal'], - 'htdocs/compta/facture/class/facture-rec.class.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'], + 'htdocs/compta/facture/class/facture-rec.class.php' => ['PhanUndeclaredProperty'], 'htdocs/compta/facture/class/facture.class.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], - 'htdocs/compta/facture/class/factureligne.class.php' => ['PhanTypeMismatchArgument'], - 'htdocs/compta/facture/class/paymentterm.class.php' => ['PhanTypeMismatchArgument'], - 'htdocs/compta/facture/contact.php' => ['PhanTypeMismatchArgument'], - 'htdocs/compta/facture/document.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/facture/invoicetemplate_list.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/compta/facture/list.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/compta/facture/messaging.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/facture/note.php' => ['PhanTypeMismatchArgument'], - 'htdocs/compta/facture/prelevement.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/facture/stats/index.php' => ['PhanTypeMismatchArgument'], 'htdocs/compta/facture/tpl/linkedobjectblock.tpl.php' => ['PhanEmptyFQSENInClasslike', 'PhanInvalidFQSENInClasslike', 'PhanTypeMismatchArgumentNullableInternal'], 'htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php' => ['PhanUndeclaredProperty'], @@ -365,7 +358,7 @@ return [ 'htdocs/core/modules/expedition/doc/pdf_rouget.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable'], 'htdocs/core/modules/expensereport/doc/pdf_standard_expensereport.modules.php' => ['PhanTypeMismatchArgument', 'PhanUndeclaredProperty'], 'htdocs/core/modules/expensereport/mod_expensereport_jade.php' => ['PhanTypeMismatchArgument'], - 'htdocs/core/modules/facture/doc/pdf_crabe.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], + 'htdocs/core/modules/facture/doc/pdf_crabe.modules.php' => ['PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/core/modules/facture/doc/pdf_octopus.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/core/modules/facture/doc/pdf_sponge.modules.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentNullable', 'PhanUndeclaredProperty'], 'htdocs/core/modules/facture/modules_facture.php' => ['PhanTypeMismatchArgument'], diff --git a/dev/tools/phan/config_fixer.php b/dev/tools/phan/config_fixer.php index 521cbcbedbf..1dc33a4c5e7 100644 --- a/dev/tools/phan/config_fixer.php +++ b/dev/tools/phan/config_fixer.php @@ -16,7 +16,8 @@ $config = include __DIR__.DIRECTORY_SEPARATOR."config.php"; //require_once __DIR__.'/plugins/SelectDateFixer.php'; //require_once __DIR__.'/plugins/setPageOrientationFixer.php'; //require_once __DIR__.'/plugins/textwithpictoFixer.php'; -require_once __DIR__.'/plugins/ifsqlFixer.php'; +//require_once __DIR__.'/plugins/ifsqlFixer.php'; +require_once __DIR__.'/plugins/writeHTMLCellFixer.php'; //require_once __DIR__.'/plugins/MultiCellFixer.php'; //require_once __DIR__.'/plugins/setAutoPageBreakFixer.php'; //require_once __DIR__.'/plugins/CellFixer.php'; diff --git a/htdocs/compta/facture/card-rec.php b/htdocs/compta/facture/card-rec.php index 2a4a0cdb031..dd78b407b33 100644 --- a/htdocs/compta/facture/card-rec.php +++ b/htdocs/compta/facture/card-rec.php @@ -10,7 +10,7 @@ * Copyright (C) 2016 Meziane Sof * Copyright (C) 2017-2025 Frédéric France * Copyright (C) 2023 Nick Fragoulis - * Copyright (C) 2024-2025 MDW + * Copyright (C) 2024-2025 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 @@ -934,7 +934,7 @@ if (empty($reshook)) { $position, $special_code, $label, - GETPOST('units'), + GETPOSTINT('units'), (float) $pu_ht_devise, 0, $date_start_fill, diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 205fd16721b..f37a548d3af 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -305,7 +305,7 @@ if (empty($reshook)) { if (($usercandelete && $isErasable > 0) || ($usercancreate && $isErasable == 1)) { - $result = $object->delete($user, 0, $idwarehouse); + $result = $object->delete($user, 0, (int) $idwarehouse); if ($result > 0) { header('Location: '.DOL_URL_ROOT.'/compta/facture/list.php?restore_lastsearch_values=1'); exit(); @@ -427,7 +427,7 @@ if (empty($reshook)) { if ($tmpvatratetoshow[0] != 0) { $langs->load("errors"); - setEventMessages($langs->trans("ErrorLinesCantBeNegativeForOneVATRate", $tmpvatratetoshow[0]), null, 'errors'); + setEventMessages($langs->trans("ErrorLinesCantBeNegativeForOneVATRate", (string) $tmpvatratetoshow[0]), null, 'errors'); $error++; $action = ''; } @@ -472,7 +472,7 @@ if (empty($reshook)) { } } elseif ($action == 'setretainedwarrantydatelimit' && $usercancreate) { $object->fetch($id); - $result = $object->setRetainedWarrantyDateLimit(GETPOSTFLOAT('retained_warranty_date_limit')); + $result = $object->setRetainedWarrantyDateLimit(GETPOSTINT('retained_warranty_date_limit')); if ($result < 0) { dol_print_error($db, $object->error); } @@ -607,7 +607,7 @@ if (empty($reshook)) { $result = $object->setBankAccount(GETPOSTINT('fk_account')); } elseif ($action == 'setremisepercent' && $usercancreate) { $object->fetch($id); - $result = $object->setDiscount($user, price2num(GETPOST('remise_percent'), '', 2)); + $result = $object->setDiscount($user, (float) price2num(GETPOST('remise_percent'), '', 2)); } elseif ($action == "setabsolutediscount" && $usercancreate) { // We have POST[remise_id] or POST[remise_id_for_payment] $db->begin(); @@ -1691,7 +1691,7 @@ if (empty($reshook)) { $descline .= ' - '.$srcobject->ref; $result = $object->addline( $descline, - $amount, // subprice + (float) $amount, // subprice 1, // quantity $tva, // vat rate 0, // localtax1_tx @@ -1749,7 +1749,7 @@ if (empty($reshook)) { if (is_array($lines)) { foreach ($lines as $line) { // We keep ->subprice and ->pa_ht, but we change the qty - $line->qty = price2num((float) $line->qty * (float) $valuestandardinvoice / 100, 'MS'); + $line->qty = (float) price2num((float) $line->qty * (float) $valuestandardinvoice / 100, 'MS'); } } } @@ -1758,7 +1758,7 @@ if (empty($reshook)) { if (is_array($lines)) { foreach ($lines as $line) { // We keep ->subprice and ->pa_ht, but we change the qty - $line->qty = price2num((float) $line->qty * (float) $valuedeposit / 100, 'MS'); + $line->qty = (float) price2num((float) $line->qty * (float) $valuedeposit / 100, 'MS'); } } } @@ -1971,7 +1971,7 @@ if (empty($reshook)) { $product->fetch(GETPOSTINT('idprod'.$i)); $startday = dol_mktime(12, 0, 0, GETPOSTINT('date_start'.$i.'month'), GETPOSTINT('date_start'.$i.'day'), GETPOSTINT('date_start'.$i.'year')); $endday = dol_mktime(12, 0, 0, GETPOSTINT('date_end'.$i.'month'), GETPOSTINT('date_end'.$i.'day'), GETPOSTINT('date_end'.$i.'year')); - $result = $object->addline($product->description, $product->price, price2num(GETPOST('qty'.$i), 'MS'), $product->tva_tx, $product->localtax1_tx, $product->localtax2_tx, GETPOSTINT('idprod'.$i), price2num(GETPOST('remise_percent'.$i), '', 2), $startday, $endday, 0, 0, 0, $product->price_base_type, $product->price_ttc, $product->type, -1, 0, '', 0, 0, 0, 0, '', array(), 100, 0, $product->fk_unit, 0, '', 1); + $result = $object->addline($product->description, $product->price, (float) price2num(GETPOST('qty'.$i), 'MS'), $product->tva_tx, $product->localtax1_tx, $product->localtax2_tx, GETPOSTINT('idprod'.$i), (float) price2num(GETPOST('remise_percent'.$i), '', 2), $startday, $endday, 0, 0, 0, $product->price_base_type, $product->price_ttc, $product->type, -1, 0, '', 0, 0, 0, 0, '', array(), 100, 0, $product->fk_unit, 0, '', 1); } } @@ -2181,7 +2181,7 @@ if (empty($reshook)) { if (!empty($line->vat_src_code)) { $tvatx .= ' ('.$line->vat_src_code.')'; } - $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, $remise_percent, $line->date_start, $line->date_end, $tvatx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit, $line->multicurrency_subprice); + $result = $object->updateline($line->id, $line->desc, $line->subprice, $line->qty, (float) $remise_percent, $line->date_start, $line->date_end, $tvatx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit, $line->multicurrency_subprice); } } elseif ($action == 'addline' && !GETPOST('submitforalllines', 'alpha') && !GETPOST('submitforallmargins', 'alpha') && $usercancreate) { // Add a new line $langs->load('errors'); @@ -2564,7 +2564,7 @@ if (empty($reshook)) { } // Insert line - $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $date_start, $date_end, 0, $info_bits, 0, $price_base_type, $pu_ttc, $type, min($rank, count($object->lines) + 1), $special_code, '', 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, GETPOST('progress'), 0, $fk_unit, $pu_ht_devise); + $result = $object->addline($desc, $pu_ht, (float) $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $date_start, $date_end, 0, $info_bits, 0, $price_base_type, $pu_ttc, $type, min($rank, count($object->lines) + 1), $special_code, '', 0, GETPOSTINT('fk_parent_line'), (int) $fournprice, $buyingprice, $label, $array_options, GETPOSTINT('progress'), 0, $fk_unit, (float) $pu_ht_devise); if ($result > 0) { // Define output language and generate document @@ -2843,9 +2843,9 @@ if (empty($reshook)) { $result = $object->updateline( GETPOSTINT('lineid'), $description, - $pu, - $qty, - $remise_percent, + (float) $pu, + (float) $qty, + (float) $remise_percent, $date_start, $date_end, $vat_rate, @@ -2862,8 +2862,8 @@ if (empty($reshook)) { $special_code, $array_options, $addprogress, - GETPOST('units', 'alpha'), - $pu_ht_devise + GETPOSTINT('units'), + (float) $pu_ht_devise ); if ($result >= 0) { @@ -2940,7 +2940,7 @@ if (empty($reshook)) { setEventMessages($mesg, null, 'warnings'); $result = -1; } else { - $object->update_percent($line, GETPOST('all_progress'), false); + $object->update_percent($line, GETPOSTINT('all_progress'), false); } } $object->update_price(1); @@ -3155,7 +3155,7 @@ if (empty($reshook)) { if ($action == 'update_extras' && $usercancreate) { - $object->oldcopy = dol_clone($object, 2); + $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty $attribute_name = GETPOST('attribute', 'restricthtml'); // Fill array 'array_options' with data from add form @@ -3183,7 +3183,7 @@ if (empty($reshook)) { $result = $object->fetch($id); if ($result > 0 && $id > 0) { - $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid')); + $contactid = (GETPOST('userid') ? GETPOSTINT('userid') : GETPOSTINT('contactid')); $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type')); $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09')); } @@ -3734,7 +3734,7 @@ if ($action == 'create') { print ''; // Next situation invoice - $opt = $form->selectSituationInvoices(GETPOSTINT('originid'), $socid); + $opt = $form->selectSituationInvoices((string) GETPOSTINT('originid'), $socid); print '
'; $tmp = ''.$langs->trans('InvoiceSubtype').''; - print $form->getSelectInvoiceSubtype(GETPOST('subtype'), 'subtype', 1, 0, ''); + print $form->getSelectInvoiceSubtype(GETPOSTINT('subtype'), 'subtype', 1, 0, ''); print ''; } @@ -4068,7 +4068,7 @@ if ($action == 'create') { // Payment mode print ''.$langs->trans('PaymentMode').''; print img_picto('', 'bank', 'class="pictofixedwidth"'); - print $form->select_types_paiements($mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth250 widthcentpercentminusx', 1); + print $form->select_types_paiements((string) $mode_reglement_id, 'mode_reglement_id', 'CRDT', 0, 1, 0, 0, 1, 'maxwidth250 widthcentpercentminusx', 1); print ''; // Bank Account @@ -4194,7 +4194,7 @@ if ($action == 'create') { print $form->textwithpicto($langs->trans('NotePublic'), $htmltext); print ''; print ''; - $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%'); + $doleditor = new DolEditor('note_public', (string) $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%'); print $doleditor->Create(1); // Private note @@ -4204,7 +4204,7 @@ if ($action == 'create') { print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext); print ''; print ''; - $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%'); + $doleditor = new DolEditor('note_private', (string) $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%'); print $doleditor->Create(1); // print ' print ''; @@ -4721,13 +4721,13 @@ if ($action == 'create') { $morehtmlref = '
'; // Ref invoice if ($object->status == $object::STATUS_DRAFT && !$mysoc->isInEEC() && getDolGlobalString('INVOICE_ALLOW_FREE_REF')) { - $morehtmlref .= $form->editfieldkey("Ref", 'ref', $object->ref, $object, $usercancreate, 'string', '', 0, 1); - $morehtmlref .= $form->editfieldval("Ref", 'ref', $object->ref, $object, $usercancreate, 'string', '', null, null, '', 1); + $morehtmlref .= $form->editfieldkey("Ref", 'ref', $object->ref, $object, (int) $usercancreate, 'string', '', 0, 1); + $morehtmlref .= $form->editfieldval("Ref", 'ref', $object->ref, $object, (int) $usercancreate, 'string', '', null, null, '', 1); $morehtmlref .= '
'; } // Ref customer - $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_customer, $object, $usercancreate, 'string', '', 0, 1); - $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_client', $object->ref_customer, $object, $usercancreate, 'string'.(getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1); + $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_client', $object->ref_customer, $object, (int) $usercancreate, 'string', '', 0, 1); + $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_client', $object->ref_customer, $object, (int) $usercancreate, 'string'.(getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', null, null, '', 1); // Thirdparty $morehtmlref .= '
'.$object->thirdparty->getNomUrl(1, 'customer'); if (!getDolGlobalString('MAIN_DISABLE_OTHER_LINK') && $object->thirdparty->id > 0) { @@ -4742,7 +4742,7 @@ if ($action == 'create') { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); @@ -4903,9 +4903,9 @@ if ($action == 'create') { print ''; if ($object->type != Facture::TYPE_CREDIT_NOTE) { if ($action == 'editconditions') { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id'); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->cond_reglement_id, 'cond_reglement_id'); } else { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'none'); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->cond_reglement_id, 'none'); } } else { print ' '; @@ -4947,9 +4947,9 @@ if ($action == 'create') { print ''; print ''; if ($action == 'editmode') { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1); + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1); } else { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'none', 'CRDT'); + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->mode_reglement_id, 'none', 'CRDT'); } print ''; @@ -4965,9 +4965,9 @@ if ($action == 'create') { print ''; print ''; if ($action == 'editbankaccount') { - $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1); + $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'fk_account', 1); } else { - $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none'); + $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none'); } print ""; print ''; @@ -5016,7 +5016,7 @@ if ($action == 'create') { print ''; $c = new Categorie($db); $cats = $c->containing($object->id, Categorie::TYPE_INVOICE); - $arrayselected=[]; + $arrayselected = []; foreach ($cats as $cat) { $arrayselected[] = $cat->id; } @@ -5091,7 +5091,7 @@ if ($action == 'create') { print ''; print ''; } else { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->retained_warranty_fk_cond_reglement, 'none'); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, (string) $object->retained_warranty_fk_cond_reglement, 'none'); if (!$displayWarranty) { print img_picto($langs->trans('RetainedWarrantyNeed100Percent'), 'warning.png', 'class="pictowarning valignmiddle" '); } @@ -6190,7 +6190,7 @@ if ($action == 'create') { $filedir, $urlsource, $genallowed, - $delallowed, + (int) $delallowed, $object->model_pdf, 1, 0, diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index 7e45aaa7faf..107b2c1c13f 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -373,7 +373,7 @@ class FactureRec extends CommonInvoice $sql .= ") VALUES ("; $sql .= "'".$this->db->escape($this->titre ? $this->titre : $this->title)."'"; $sql .= ", ".((int) $this->socid); - $sql .= ", ".($this->subtype ? "'".$this->db->escape($this->subtype)."'" : "null"); + $sql .= ", ".($this->subtype ? "'".$this->db->escape((string) $this->subtype)."'" : "null"); $sql .= ", ".((int) $conf->entity); $sql .= ", '".$this->db->idate($now)."'"; $sql .= ", ".(!empty($facsrc->total_ttc) ? ((float) $facsrc->total_ttc) : '0'); @@ -554,9 +554,9 @@ class FactureRec extends CommonInvoice /** * Update a line invoice_rec. * - * @param User $user User - * @param int $notrigger No trigger - * @return int Return integer <0 if KO, Id of line if OK + * @param User $user User + * @param int<0,1> $notrigger No trigger + * @return int Return integer <0 if KO, Id of line if OK */ public function update(User $user, $notrigger = 0) { @@ -611,12 +611,12 @@ class FactureRec extends CommonInvoice /** * Load object and lines * - * @param int $rowid Id of object to load - * @param string $ref Reference of recurring invoice - * @param string $ref_ext External reference of invoice - * @param int $noextrafields 0=Default to load extrafields, 1=No extrafields - * @param int $nolines 0=Default to load lines, 1=No lines - * @return int >0 if OK, <0 if KO, 0 if not found + * @param int $rowid Id of object to load + * @param string $ref Reference of recurring invoice + * @param string $ref_ext External reference of invoice + * @param int<0,1> $noextrafields 0=Default to load extrafields, 1=No extrafields + * @param int<0,1> $nolines 0=Default to load lines, 1=No lines + * @return int If OK >0, <0 if KO, 0 if not found */ public function fetch($rowid, $ref = '', $ref_ext = '', $noextrafields = 0, $nolines = 0) { @@ -859,10 +859,10 @@ class FactureRec extends CommonInvoice /** * Delete template invoice * - * @param User $user User that delete. - * @param int $notrigger 1=Does not execute triggers, 0= execute triggers - * @param int $idwarehouse Id warehouse to use for stock change. - * @return int Return integer <0 if KO, >0 if OK + * @param User $user User that delete. + * @param int<0,1> $notrigger 1=Does not execute triggers, 0= execute triggers + * @param int $idwarehouse Id warehouse to use for stock change. + * @return int Return integer <0 if KO, >0 if OK */ public function delete(User $user, $notrigger = 0, $idwarehouse = -1) { @@ -923,27 +923,27 @@ class FactureRec extends CommonInvoice * Add a line to invoice * * @param string $desc Description de la ligne - * @param double $pu_ht Prix unitaire HT (> 0 even for credit note) - * @param double $qty Quantite - * @param double $txtva Taux de tva force, sinon -1 - * @param double $txlocaltax1 Local tax 1 rate (deprecated) - * @param double $txlocaltax2 Local tax 2 rate (deprecated) + * @param float $pu_ht Prix unitaire HT (> 0 even for credit note) + * @param float $qty Quantite + * @param float $txtva Taux de tva force, sinon -1 + * @param float $txlocaltax1 Local tax 1 rate (deprecated) + * @param float $txlocaltax2 Local tax 2 rate (deprecated) * @param int $fk_product Product/Service ID predefined - * @param double $remise_percent Percentage discount of the line + * @param float $remise_percent Percentage discount of the line * @param string $price_base_type HT or TTC * @param int $info_bits VAT npr or not ? * @param int $fk_remise_except Id remise - * @param double $pu_ttc Prix unitaire TTC (> 0 even for credit note) + * @param float $pu_ttc Prix unitaire TTC (> 0 even for credit note) * @param int $type Type of line (0=product, 1=service) * @param int $rang Position of line * @param int $special_code Special code * @param string $label Label of the line - * @param string $fk_unit Unit - * @param double $pu_ht_devise Unit price in currency + * @param ?int $fk_unit Unit + * @param float $pu_ht_devise Unit price in currency * @param int $date_start_fill 1=Flag to fill start date when generating invoice * @param int $date_end_fill 1=Flag to fill end date when generating invoice - * @param int $fk_fournprice Supplier price id (to calculate margin) or '' - * @param int $pa_ht Buying price of line (to calculate margin) or '' + * @param ?int $fk_fournprice Supplier price id (to calculate margin) or '' + * @param float $pa_ht Buying price of line (to calculate margin) or '' * @param int $fk_parent_line Id of parent line * @return int Return integer <0 if KO, Id of line if OK */ @@ -961,7 +961,7 @@ class FactureRec extends CommonInvoice return -1; } - $localtaxes_type = getLocalTaxesFromRate($txtva, 0, $this->thirdparty, $mysoc); + $localtaxes_type = getLocalTaxesFromRate((float) $txtva, 0, $this->thirdparty, $mysoc); // Clean vat code $reg = array(); @@ -1086,7 +1086,7 @@ class FactureRec extends CommonInvoice $sql .= ", '".$this->db->escape(isset($localtaxes_type[0]) ? $localtaxes_type[0] : '')."'"; $sql .= ", ".price2num($txlocaltax2); $sql .= ", '".$this->db->escape(isset($localtaxes_type[2]) ? $localtaxes_type[2] : '')."'"; - $sql .= ", ".(!empty($fk_product) ? "'".$this->db->escape($fk_product)."'" : "null"); + $sql .= ", ".(!empty($fk_product) ? "'".$this->db->escape((string) $fk_product)."'" : "null"); $sql .= ", ".((int) $product_type); $sql .= ", ".price2num($remise_percent); $sql .= ", ".price2num($pu_ht); @@ -1129,28 +1129,28 @@ class FactureRec extends CommonInvoice * * @param int $rowid Id of line to update * @param string $desc Description de la ligne - * @param double $pu_ht Prix unitaire HT (> 0 even for credit note) - * @param double $qty Quantite - * @param double $txtva Taux de tva force, sinon -1 - * @param double $txlocaltax1 Local tax 1 rate (deprecated) - * @param double $txlocaltax2 Local tax 2 rate (deprecated) + * @param float $pu_ht Prix unitaire HT (> 0 even for credit note) + * @param float $qty Quantite + * @param float $txtva Taux de tva force, sinon -1 + * @param float $txlocaltax1 Local tax 1 rate (deprecated) + * @param float $txlocaltax2 Local tax 2 rate (deprecated) * @param int $fk_product Product/Service ID predefined - * @param double $remise_percent Percentage discount of the line + * @param float $remise_percent Percentage discount of the line * @param string $price_base_type HT or TTC * @param int $info_bits Bits of type of lines * @param int $fk_remise_except Id remise - * @param double $pu_ttc Prix unitaire TTC (> 0 even for credit note) + * @param float $pu_ttc Prix unitaire TTC (> 0 even for credit note) * @param int $type Type of line (0=product, 1=service) * @param int $rang Position of line * @param int $special_code Special code * @param string $label Label of the line - * @param string $fk_unit Unit - * @param double $pu_ht_devise Unit price in currency - * @param int $notrigger disable line update trigger + * @param ?int $fk_unit Unit + * @param float $pu_ht_devise Unit price in currency + * @param int<0,1> $notrigger disable line update trigger * @param int $date_start_fill 1=Flag to fill start date when generating invoice * @param int $date_end_fill 1=Flag to fill end date when generating invoice - * @param int $fk_fournprice Id of origin supplier price - * @param int $pa_ht Price (without tax) of product for margin calculation + * @param ?int $fk_fournprice Id of origin supplier price + * @param float $pa_ht Price (without tax) of product for margin calculation * @param int $fk_parent_line Id of parent line * @return int Return integer <0 if KO, Id of line if OK */ @@ -1268,7 +1268,7 @@ class FactureRec extends CommonInvoice $sql .= ", localtax1_type='".$this->db->escape($localtaxes_type[0])."'"; $sql .= ", localtax2_tx=".((float) $txlocaltax2); $sql .= ", localtax2_type='".$this->db->escape($localtaxes_type[2])."'"; - $sql .= ", fk_product=".(!empty($fk_product) ? "'".$this->db->escape($fk_product)."'" : "null"); + $sql .= ", fk_product=".(!empty($fk_product) ? "'".$this->db->escape((string) $fk_product)."'" : "null"); $sql .= ", product_type=".((int) $product_type); $sql .= ", remise_percent='".price2num($remise_percent)."'"; $sql .= ", subprice='".price2num($pu_ht)."'"; @@ -1284,7 +1284,7 @@ class FactureRec extends CommonInvoice $sql .= ", info_bits=".((int) $info_bits); $sql .= ", rang=".((int) $rang); $sql .= ", special_code=".((int) $special_code); - $sql .= ", fk_unit=".($fk_unit ? "'".$this->db->escape($fk_unit)."'" : "null"); + $sql .= ", fk_unit=".($fk_unit ? "'".$this->db->escape((string) $fk_unit)."'" : "null"); $sql .= ', multicurrency_subprice = '.price2num($pu_ht_devise); $sql .= ', multicurrency_total_ht = '.price2num($multicurrency_total_ht); $sql .= ', multicurrency_total_tva = '.price2num($multicurrency_total_tva); @@ -1319,7 +1319,7 @@ class FactureRec extends CommonInvoice /** * Return if maximum number of generation is reached * - * @return boolean False by default, True if maximum number of generation is reached + * @return bool False by default, True if maximum number of generation is reached */ public function isMaxNbGenReached() { @@ -1331,7 +1331,7 @@ class FactureRec extends CommonInvoice } /** - * Format string to output with by striking the string if max number of generation was reached + * Format string to output with by striking the string if max number of generations was reached * * @param string $ret Default value to output * @return string html formatted string @@ -1347,10 +1347,10 @@ class FactureRec extends CommonInvoice * * WARNING: This method change temporarily context $conf->entity to be in correct context for each recurring invoice found. * - * @param int $restrictioninvoiceid 0=All qualified template invoices found. > 0 = restrict action on invoice ID - * @param int $forcevalidation 1=Force validation of invoice whatever is template auto_validate flag. - * @param int $notrigger Disable the trigger - * @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK) + * @param int<0,max> $restrictioninvoiceid 0=All qualified template invoices found. > 0 = restrict action on invoice ID + * @param int<0,1> $forcevalidation 1=Force validation of invoice whatever is template auto_validate flag. + * @param int<0,1> $notrigger Disable the trigger + * @return int 0 if OK, < 0 if KO (this function is used also by cron so only 0 is OK) */ public function createRecurringInvoices($restrictioninvoiceid = 0, $forcevalidation = 0, $notrigger = 0) { @@ -1511,13 +1511,13 @@ class FactureRec extends CommonInvoice /** * Return clickable name (with picto eventually) * - * @param int $withpicto Add picto into link - * @param string $option Where point the link - * @param int $max Maxlength of ref - * @param int $short 1=Return just URL - * @param string $moretitle Add more text to title tooltip - * @param int $notooltip 1=Disable tooltip - * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @param int $withpicto Add picto into link + * @param string $option Where point the link + * @param int $max Maxlength of ref + * @param int<0,1> $short 1=Return just URL + * @param string $moretitle Add more text to title tooltip + * @param int<0,1> $notooltip 1=Disable tooltip + * @param int<-1,1> $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking * @return string String with URL */ public function getNomUrl($withpicto = 0, $option = '', $max = 0, $short = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1) @@ -1589,9 +1589,9 @@ class FactureRec extends CommonInvoice /** * Return label of object status * - * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=short label + picto, 6=Long label + picto - * @param integer $alreadypaid Not used on recurring invoices - * @return string Label of status + * @param int<0,6> $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=short label + picto, 6=Long label + picto + * @param int<-1,1> $alreadypaid Not used on recurring invoices + * @return string Label of status */ public function getLibStatut($mode = 0, $alreadypaid = -1) { @@ -1602,10 +1602,10 @@ class FactureRec extends CommonInvoice /** * Return label of a status * - * @param int $recur Is it a recurring invoice ? + * @param int<0,1> $recur Is it a recurring invoice ? * @param int $status Id status (suspended or not) * @param int<0,6> $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=short label + picto, 6=long label + picto - * @param int $alreadypaid Not used for recurring invoices + * @param int<-1,1> $alreadypaid Not used for recurring invoices * @param int $type Type invoice * @param int $nbofopendirectdebitorcredittransfer @unused-param Nb of open direct debit or credit transfer * @return string Label of status @@ -1737,9 +1737,9 @@ class FactureRec extends CommonInvoice /** * Return next reference of invoice not already used (or last reference) * - * @param Societe $soc Thirdparty object - * @param string $mode 'next' for next value or 'last' for last value - * @return string free ref or last ref + * @param Societe $soc Thirdparty object + * @param 'next'|'last' $mode 'next' for next value or 'last' for last value + * @return string free ref or last ref */ public function getNextNumRef($soc, $mode = 'next') { @@ -1965,7 +1965,7 @@ class FactureRec extends CommonInvoice } $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql .= ' SET frequency = '.($frequency ? $this->db->escape($frequency) : 'null'); + $sql .= ' SET frequency = '.($frequency ? $this->db->escape((string) $frequency) : 'null'); if (!empty($unit)) { $sql .= ', unit_frequency = \''.$this->db->escape($unit).'\''; } @@ -2051,9 +2051,9 @@ class FactureRec extends CommonInvoice /** * Update the maximum period * - * @param int $nb number of maximum period - * @param int $notrigger Disable the trigger - * @return int Return integer <0 if KO, >0 if OK + * @param int $nb number of maximum period + * @param int<0,1> $notrigger Disable the trigger + * @return int Return integer <0 if KO, >0 if OK */ public function setMaxPeriod($nb, $notrigger = 0) { @@ -2095,9 +2095,9 @@ class FactureRec extends CommonInvoice /** * Update the auto validate flag of invoice * - * @param int $validate 0 to create in draft, 1 to create and validate invoice - * @param int $notrigger Disable the trigger - * @return int Return integer <0 if KO, >0 if OK + * @param int<0,1> $validate 0 to create in draft, 1 to create and validate invoice + * @param int<0,1> $notrigger Disable the trigger + * @return int Return integer <0 if KO, >0 if OK */ public function setAutoValidate($validate, $notrigger = 0) { @@ -2135,9 +2135,9 @@ class FactureRec extends CommonInvoice /** * Update the auto generate documents * - * @param int $validate 0 no document, 1 to generate document - * @param int $notrigger Disable the trigger - * @return int Return integer <0 if KO, >0 if OK + * @param int<0,1> $validate 0 no document, 1 to generate document + * @param int<0,1> $notrigger Disable the trigger + * @return int Return integer <0 if KO, >0 if OK */ public function setGeneratePdf($validate, $notrigger = 0) { @@ -2176,7 +2176,7 @@ class FactureRec extends CommonInvoice * Update the model for documents * * @param string $model model of document generator - * @param int $notrigger Disable the trigger + * @param int<0,1> $notrigger Disable the trigger * @return int Return integer <0 if KO, >0 if OK */ public function setModelPdf($model, $notrigger = 0) @@ -2429,8 +2429,8 @@ class FactureLigneRec extends CommonInvoiceLine /** * Update a line to invoice_rec. * - * @param User $user User - * @param int $notrigger No trigger + * @param User $user User + * @param int<0,1> $notrigger No trigger * @return int Return integer <0 if KO, Id of line if OK */ public function update(User $user, $notrigger = 0) @@ -2456,9 +2456,9 @@ class FactureLigneRec extends CommonInvoiceLine $sql .= ", tva_tx=".price2num($this->tva_tx); $sql .= ", vat_src_code='".$this->db->escape($this->vat_src_code)."'"; $sql .= ", localtax1_tx=".price2num($this->localtax1_tx); - $sql .= ", localtax1_type='".$this->db->escape($this->localtax1_type)."'"; + $sql .= ", localtax1_type='".$this->db->escape((string) $this->localtax1_type)."'"; $sql .= ", localtax2_tx=".price2num($this->localtax2_tx); - $sql .= ", localtax2_type='".$this->db->escape($this->localtax2_type)."'"; + $sql .= ", localtax2_type='".$this->db->escape((string) $this->localtax2_type)."'"; $sql .= ", fk_product=".($this->fk_product > 0 ? $this->fk_product : "null"); $sql .= ", product_type=".((int) $this->product_type); $sql .= ", remise_percent=".price2num($this->remise_percent); @@ -2475,7 +2475,7 @@ class FactureLigneRec extends CommonInvoiceLine } $sql .= ", rang=".((int) $this->rang); $sql .= ", special_code=".((int) $this->special_code); - $sql .= ", fk_unit=".($this->fk_unit ? "'".$this->db->escape($this->fk_unit)."'" : "null"); + $sql .= ", fk_unit=".($this->fk_unit ? "'".$this->db->escape((string) $this->fk_unit)."'" : "null"); $sql .= ", fk_contract_line=".($this->fk_contract_line ? $this->fk_contract_line : "null"); $sql .= " WHERE rowid = ".((int) $this->id); diff --git a/htdocs/compta/facture/class/factureligne.class.php b/htdocs/compta/facture/class/factureligne.class.php index da644fff225..ae3ebbbbfda 100644 --- a/htdocs/compta/facture/class/factureligne.class.php +++ b/htdocs/compta/facture/class/factureligne.class.php @@ -20,7 +20,7 @@ * Copyright (C) 2022 Sylvain Legrand * Copyright (C) 2023 Gauthier VERDOL * Copyright (C) 2023 Nick Fragoulis - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 MDW * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -430,8 +430,8 @@ class FactureLigne extends CommonInvoiceLine $sql .= " ".price2num($this->tva_tx).","; $sql .= " ".price2num($this->localtax1_tx).","; $sql .= " ".price2num($this->localtax2_tx).","; - $sql .= " '".$this->db->escape($this->localtax1_type)."',"; - $sql .= " '".$this->db->escape($this->localtax2_type)."',"; + $sql .= " '".$this->db->escape((string) $this->localtax1_type)."',"; + $sql .= " '".$this->db->escape((string) $this->localtax2_type)."',"; $sql .= ' '.((!empty($this->fk_product) && $this->fk_product > 0) ? $this->fk_product : "null").','; $sql .= " ".((int) $this->product_type).","; $sql .= " ".price2num($this->remise_percent).","; @@ -445,7 +445,7 @@ class FactureLigne extends CommonInvoiceLine $sql .= ' '.((int) $this->special_code).','; $sql .= ' '.(!empty($this->fk_fournprice) ? $this->fk_fournprice : "null").','; $sql .= ' '.price2num($this->pa_ht).','; - $sql .= " '".$this->db->escape($this->info_bits)."',"; + $sql .= " '".$this->db->escape((string) $this->info_bits)."',"; $sql .= " ".price2num($this->total_ht).","; $sql .= " ".price2num($this->total_tva).","; $sql .= " ".price2num($this->total_ttc).","; @@ -647,13 +647,13 @@ class FactureLigne extends CommonInvoiceLine $sql .= ", tva_tx=".price2num($this->tva_tx); $sql .= ", localtax1_tx=".price2num($this->localtax1_tx); $sql .= ", localtax2_tx=".price2num($this->localtax2_tx); - $sql .= ", localtax1_type='".$this->db->escape($this->localtax1_type)."'"; - $sql .= ", localtax2_type='".$this->db->escape($this->localtax2_type)."'"; + $sql .= ", localtax1_type='".$this->db->escape((string) $this->localtax1_type)."'"; + $sql .= ", localtax2_type='".$this->db->escape((string) $this->localtax2_type)."'"; $sql .= ", qty=".price2num($this->qty); $sql .= ", date_start=".(!empty($this->date_start) ? "'".$this->db->idate($this->date_start)."'" : "null"); $sql .= ", date_end=".(!empty($this->date_end) ? "'".$this->db->idate($this->date_end)."'" : "null"); $sql .= ", product_type=".$this->product_type; - $sql .= ", info_bits='".$this->db->escape($this->info_bits)."'"; + $sql .= ", info_bits='".$this->db->escape((string) $this->info_bits)."'"; $sql .= ", special_code=" . (int) $this->special_code; if (empty($this->skip_update_total)) { $sql .= ", total_ht=".price2num($this->total_ht); @@ -662,7 +662,7 @@ class FactureLigne extends CommonInvoiceLine $sql .= ", total_localtax1=".price2num($this->total_localtax1); $sql .= ", total_localtax2=".price2num($this->total_localtax2); } - $sql .= ", fk_product_fournisseur_price=".(!empty($this->fk_fournprice) ? "'".$this->db->escape($this->fk_fournprice)."'" : "null"); + $sql .= ", fk_product_fournisseur_price=".(!empty($this->fk_fournprice) ? "'".$this->db->escape((string) $this->fk_fournprice)."'" : "null"); $sql .= ", buy_price_ht=".(($this->pa_ht || (string) $this->pa_ht === '0') ? price2num($this->pa_ht) : "null"); // $this->pa_ht should always be defined (set to 0 or to sell price depending on option) $sql .= ", fk_parent_line=".($this->fk_parent_line > 0 ? $this->fk_parent_line : "null"); if (!empty($this->rang)) { diff --git a/htdocs/compta/facture/class/paymentterm.class.php b/htdocs/compta/facture/class/paymentterm.class.php index 7cd3648e771..89116d35ae3 100644 --- a/htdocs/compta/facture/class/paymentterm.class.php +++ b/htdocs/compta/facture/class/paymentterm.class.php @@ -1,7 +1,7 @@ * Copyright (C) 2024 Frédéric France - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 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 @@ -164,7 +164,7 @@ class PaymentTerm // extends CommonObject $sql .= "nbjour,"; $sql .= "decalage"; $sql .= ") VALUES ("; - $sql .= " ".(!isset($this->entity) ? getEntity('c_payment_term') : "'".$this->db->escape($this->entity)."'").","; + $sql .= " ".(!isset($this->entity) ? getEntity('c_payment_term') : "'".$this->db->escape((string) $this->entity)."'").","; $sql .= " ".(!isset($this->code) ? 'NULL' : "'".$this->db->escape($this->code)."'").","; $sql .= " ".(!isset($this->sortorder) ? 'NULL' : "'".$this->db->escape($this->sortorder)."'").","; $sql .= " ".(!isset($this->active) ? 'NULL' : "'".$this->db->escape($this->active)."'").","; diff --git a/htdocs/compta/facture/contact.php b/htdocs/compta/facture/contact.php index 884a954e758..38f886ee9f5 100644 --- a/htdocs/compta/facture/contact.php +++ b/htdocs/compta/facture/contact.php @@ -6,7 +6,7 @@ * Copyright (C) 2017 Ferran Marcet * Copyright (C) 2023 Christian Foellmann * Copyright (C) 2024 Frédéric France - * Copyright (C) 2024 MDW + * Copyright (C) 2024-2025 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 @@ -64,7 +64,7 @@ if ($user->socid) { $object = new Facture($db); // Load object if ($id > 0 || !empty($ref)) { - $ret = $object->fetch($id, $ref, '', 0, getDolGlobalInt('INVOICE_USE_SITUATION')); + $ret = $object->fetch($id, $ref, '', 0, getDolGlobalBool('INVOICE_USE_SITUATION')); } // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context $hookmanager->initHooks(array('invoicecontactcard', 'globalcard')); @@ -169,7 +169,7 @@ if ($id > 0 || !empty($ref)) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); diff --git a/htdocs/compta/facture/document.php b/htdocs/compta/facture/document.php index 9155185c460..e362cec8b55 100644 --- a/htdocs/compta/facture/document.php +++ b/htdocs/compta/facture/document.php @@ -7,6 +7,7 @@ * Copyright (C) 2017 Ferran Marcet * Copyright (C) 2017-2024 Frédéric France * Copyright (C) 2025 Alexandre Spangaro + * Copyright (C) 2025 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 @@ -169,7 +170,7 @@ if ($id > 0 || !empty($ref)) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index 35a46efd9bc..3c164359ec2 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -132,7 +132,7 @@ if (empty($reshook)) { // Get chosen iban id $iban = GETPOSTINT('accountcustomerid'); $amount = GETPOST('withdraw_request_amount', 'alpha'); - $result = $object->demande_prelevement($user, price2num($amount), $newtype, $sourcetype, 0, $iban ?? 0); + $result = $object->demande_prelevement($user, (float) price2num($amount), $newtype, $sourcetype, 0, $iban ?? 0); if ($result > 0) { $db->commit(); @@ -389,7 +389,7 @@ if ($object->id > 0) { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $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 { if (!empty($object->fk_project)) { $proj = new Project($db); @@ -529,9 +529,9 @@ if ($object->id > 0) { print ''; if ($object->type != $object::TYPE_CREDIT_NOTE) { if ($action == 'editconditions') { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 0, $type); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->cond_reglement_id, 'cond_reglement_id', 0, $type); } else { - $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->cond_reglement_id, 'none'); + $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->cond_reglement_id, 'none'); } } else { print ' '; @@ -582,9 +582,9 @@ if ($object->id > 0) { $filtertype = 'DBIT'; } if ($action == 'editmode') { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', $filtertype, 1, 0, $type); + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'mode_reglement_id', $filtertype, 1, 0, $type); } else { - $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, $object->mode_reglement_id, 'none'); + $form->form_modes_reglement($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->mode_reglement_id, 'none'); } print ''; @@ -599,9 +599,9 @@ if ($object->id > 0) { print ''; print ''; if ($action == 'editbankaccount') { - $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1); + $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'fk_account', 1); } else { - $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none'); + $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, (string) $object->fk_account, 'none'); } print ''; print ''; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 6655346de96..c45d4fe748b 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6278,7 +6278,7 @@ class Form * Show a form + html select a date * * @param string $page Page - * @param string $selected Date preselected + * @param int|'' $selected Date preselected * @param string $htmlname Html name of date input fields or 'none' * @param int $displayhour Display hour selector * @param int $displaymin Display minutes selector @@ -7215,10 +7215,10 @@ class Form * - local date in user area, if set_time is '' (so if set_time is '', output may differs when done from two different location) * - Empty (fields empty), if set_time is -1 (in this case, parameter empty must also have value 1) * - * @param integer|string $set_time Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). + * @param int|'' $set_time Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). * @param integer|string $set_time_end Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). * @param string $prefix Prefix for fields name - * @param int $empty 0=Fields required, 1=Empty inputs are allowed, 2=Empty inputs are allowed for hours only + * @param int<0,2> $empty 0=Fields required, 1=Empty inputs are allowed, 2=Empty inputs are allowed for hours only * @param int $forcenewline Force new line between the 2 dates. * @return string Html for selectDate * @see form_date(), select_month(), select_year(), select_dayofweek() @@ -7242,7 +7242,7 @@ class Form * - local date in user area, if set_time is '' (so if set_time is '', output may differs when done from two different location) * - Empty (fields empty), if set_time is -1 (in this case, parameter empty must also have value 1) * - * @param integer|string $set_time Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). + * @param int|'' $set_time Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). * @param string $prefix Prefix for fields name * @param int $h 1 or 2=Show also hours (2=hours on a new line), -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 or 4 (4=hours on a new line)=Show hour always empty * @param int $m 1=Show also minutes, -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show minutes always empty diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 371b4646ff2..b453be32572 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7380,10 +7380,10 @@ function get_localtax_by_third($local) * Get tax (VAT) main information from Id. * You can also call getLocalTaxesFromRate() after to get only localtax fields. * - * @param int|string $vatrate VAT ID or Rate. Value can be value or the string with code into parenthesis or rowid if $firstparamisid is 1. Example: '8.5' or '8.5 (8.5NPR)' or 123. - * @param Societe $buyer Company object - * @param Societe $seller Company object - * @param int<0,1> $firstparamisid 1 if first param is id into table (use this if you can) + * @param float|string $vatrate VAT ID or Rate. Value can be value or the string with code into parenthesis or rowid if $firstparamisid is 1. Example: '8.5' or '8.5 (8.5NPR)' or 123. + * @param ?Societe $buyer Company object + * @param ?Societe $seller Company object + * @param int<0,1> $firstparamisid 1 if first param is id into table (use this if you can) * @return array{}|array{rowid:int,code:string,rate:float,localtax1:float,localtax1_type:string,localtax2:float,localtax2_type:string,npr:float,accountancy_code_sell:string,accountancy_code_buy:string} array('rowid'=> , 'code'=> ...) * @see getLocalTaxesFromRate() */ @@ -7458,7 +7458,7 @@ function getTaxesFromId($vatrate, $buyer = null, $seller = null, $firstparamisid * Instead this function must be called when adding a line to get the array of possible values for localtax and type, and then * provide the selected value to the function calcul_price_total. * - * @param int|string $vatrate VAT ID or Rate+Code. Value can be value or the string with code into parenthesis or rowid if $firstparamisid is 1. Example: '8.5' or '8.5 (8.5NPR)' or 123. + * @param float|string $vatrate VAT ID or Rate+Code. Value can be value or the string with code into parenthesis or rowid if $firstparamisid is 1. Example: '8.5' or '8.5 (8.5NPR)' or 123. * @param int<0,2> $local Number of localtax (1 or 2, or 0 to return 1 & 2) * @param ?Societe $buyer Company object * @param ?Societe $seller Company object diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index ed77866c1f8..dee5ed32a72 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1156,7 +1156,7 @@ class pdf_crabe extends ModelePDFFactures * @param Facture $object Object to show * @param float $posy Y * @param Translate $outputlangs Langs object - * @param Translate $outputlangsbis Object lang for output bis + * @param ?Translate $outputlangsbis Object lang for output bis * @return float Pos y */ protected function _tableau_info(&$pdf, $object, $posy, $outputlangs, $outputlangsbis) @@ -1449,7 +1449,7 @@ class pdf_crabe extends ModelePDFFactures * @param float $deja_regle Amount already paid (in the currency of invoice) * @param float $posy Position depart * @param Translate $outputlangs Object langs - * @param Translate $outputlangsbis Object lang for output bis + * @param ?Translate $outputlangsbis Object lang for output bis * @return float Position pour suite */ protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs, $outputlangsbis) @@ -1642,13 +1642,13 @@ class pdf_crabe extends ModelePDFFactures $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : ''); $totalvat .= ' '; if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') { - $totalvat .= vatrate($tvaval['vatrate'], true).$tvacompl; + $totalvat .= vatrate((string) $tvaval['vatrate'], true).$tvacompl; } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') { $totalvat .= $tvaval['vatcode'].$tvacompl; } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') { $totalvat .= $tvacompl; } else { - $totalvat .= vatrate($tvaval['vatrate'], true).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl; + $totalvat .= vatrate((string) $tvaval['vatrate'], true).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl; } $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true); $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); From 3f15c5fcb7e5c80ddc74025c89941d1fa8ba827d Mon Sep 17 00:00:00 2001 From: MDW Date: Wed, 5 Mar 2025 21:42:17 +0100 Subject: [PATCH 65/71] Fix phpstan notice --- htdocs/core/class/html.form.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index c45d4fe748b..f820a8467d5 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -7242,7 +7242,7 @@ class Form * - local date in user area, if set_time is '' (so if set_time is '', output may differs when done from two different location) * - Empty (fields empty), if set_time is -1 (in this case, parameter empty must also have value 1) * - * @param int|'' $set_time Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). + * @param int|'' $set_time Pre-selected date (must be a local PHP server timestamp), -1 to keep date not preselected, '' to use current date with 00:00 hour (Parameter 'empty' must be 0 or 2). Using a "string date" is deprecated and excluded from the param type. * @param string $prefix Prefix for fields name * @param int $h 1 or 2=Show also hours (2=hours on a new line), -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 or 4 (4=hours on a new line)=Show hour always empty * @param int $m 1=Show also minutes, -1 has same effect but hour and minutes are prefilled with 23:59 if date is empty, 3 show minutes always empty @@ -7311,7 +7311,7 @@ class Form $shour = ''; $smin = ''; $ssec = ''; - if (!empty($set_time) && preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', $set_time, $reg)) { // deprecated usage + if (!empty($set_time) && preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/', (string) $set_time, $reg)) { // deprecated usage // Date format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' $syear = (!empty($reg[1]) ? $reg[1] : ''); $smonth = (!empty($reg[2]) ? $reg[2] : ''); From 8f406d680a9d59fa3e328aa4d0234aed23c86d34 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Thu, 6 Mar 2025 02:05:44 +0100 Subject: [PATCH 66/71] FIX Missing ref_ext in group by in list of product --- htdocs/product/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/list.php b/htdocs/product/list.php index d262f757909..e1eed666587 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -658,7 +658,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; -$sql .= " GROUP BY p.rowid, p.ref, p.description, p.label, p.barcode, p.price, p.tva_tx, p.price_ttc, p.price_base_type,"; +$sql .= " GROUP BY p.rowid, p.ref, p.ref_ext, p.description, p.label, p.barcode, p.price, p.tva_tx, p.price_ttc, p.price_base_type,"; $sql .= " p.fk_product_type, p.duration, p.finished, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,"; $sql .= ' p.datec, p.tms, p.entity, p.tobatch, p.pmp, p.cost_price, p.stock,'; if (!getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) { From ca9763afc17ff07b10507ece8cfe78d9baa49917 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Thu, 6 Mar 2025 02:15:18 +0100 Subject: [PATCH 67/71] Fix type int --- htdocs/compta/facture/card-rec.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/card-rec.php b/htdocs/compta/facture/card-rec.php index dd78b407b33..433d1ded085 100644 --- a/htdocs/compta/facture/card-rec.php +++ b/htdocs/compta/facture/card-rec.php @@ -700,7 +700,7 @@ if (empty($reshook)) { $label = (GETPOST('product_label') ? GETPOST('product_label') : ''); $desc = $product_desc; $type = GETPOST('type'); - $fk_unit = GETPOST('units', 'alpha'); + $fk_unit = GETPOSTINT('units'); } $date_start_fill = GETPOSTINT('date_start_fill'); From 72ca805f990af51bf9057803d0273f62d82fb332 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Thu, 6 Mar 2025 02:57:01 +0100 Subject: [PATCH 68/71] Fix to avoid use of function that will permit sql injection --- htdocs/accountancy/class/bookkeeping.class.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index c6e40ccfbfc..969d9bbf2bd 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -2584,10 +2584,9 @@ class BookKeeping extends CommonObject /** * Get list of fiscal period ordered by start date. * - * @param string $filter Filter * @return array|int Return integer <0 if KO, Fiscal periods : [[id, date_start, date_end, label], ...] */ - public function getFiscalPeriods($filter = '') + public function getFiscalPeriods() { global $conf; $list = array(); @@ -2595,9 +2594,6 @@ class BookKeeping extends CommonObject $sql = "SELECT rowid, label, date_start, date_end, statut"; $sql .= " FROM " . $this->db->prefix() . "accounting_fiscalyear"; $sql .= " WHERE entity = " . ((int) $conf->entity); - if (!empty($filter)) { - $sql .= " AND (" . $this->db->sanitize($filter, 1, 1, 1) . ')'; - } $sql .= $this->db->order('date_start', 'ASC'); $resql = $this->db->query($sql); From caead5de9f4f2f3e4aac87f05c8b06d9495c9e9a Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Thu, 6 Mar 2025 03:29:54 +0100 Subject: [PATCH 69/71] Fix protect use of sanitize to make sql injection --- htdocs/compta/facture/list.php | 2 +- htdocs/core/db/DoliDB.class.php | 23 ++++++++++++++++-- htdocs/core/lib/functions.lib.php | 2 +- htdocs/projet/class/taskstats.class.php | 2 +- test/phpunit/FunctionsLibTest.php | 31 +++++++++++++++++++++---- 5 files changed, 51 insertions(+), 9 deletions(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 1ef606d0160..2e4920cd379 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -868,7 +868,7 @@ if ($search_status != '-1' && $search_status != '') { $sql .= " AND f.fk_statut = 3"; // abandoned } } else { - $sql .= " AND f.fk_statut IN (".$db->sanitize($db->escape($search_status)).")"; // When search_status is '1,2' for example + $sql .= " AND f.fk_statut IN (".$db->sanitize($search_status).")"; // When search_status is '1,2' for example } } diff --git a/htdocs/core/db/DoliDB.class.php b/htdocs/core/db/DoliDB.class.php index 63847079776..3a2346c2356 100644 --- a/htdocs/core/db/DoliDB.class.php +++ b/htdocs/core/db/DoliDB.class.php @@ -177,7 +177,8 @@ abstract class DoliDB implements Database * Sanitize a string for SQL forging * * @param string $stringtosanitize String to sanitize - * @param int $allowsimplequote 1=Allow simple quotes in string. When string is used as a list of SQL string ('aa', 'bb', ...) + * @param int $allowsimplequote 1=Allow simple quotes in string around val separated by "," but only when string is used as a list of SQL string "'aa', 'bb', 'cc', ..."). Can be used for IN ... + * 2=Allow all simple quotes. If you use this value, the return MUST be escaped to forge SQL strings. * @param int $allowsequals 1=Allow equals sign * @param int $allowsspace 1=Allow space char * @param int $allowschars 1=Allow a-z chars @@ -185,7 +186,25 @@ abstract class DoliDB implements Database */ public function sanitize($stringtosanitize, $allowsimplequote = 0, $allowsequals = 0, $allowsspace = 0, $allowschars = 1) { - return preg_replace('/[^0-9_\-\.,'.($allowschars ? 'a-z' : '').($allowsequals ? '=' : '').($allowsimplequote ? "\'" : '').($allowsspace ? ' ' : '').']/i', '', $stringtosanitize); + //$result = preg_replace('/[^0-9_\-\.,'.($allowschars ? '\p{L}' : '').($allowsequals ? '=' : '').($allowsimplequote ? "\'" : '').($allowsspace ? ' ' : '').']/ui', '', $stringtosanitize); + $result = preg_replace('/[^0-9_\-\.,'.($allowschars ? 'a-z' : '').($allowsequals ? '=' : '').($allowsimplequote ? "\'" : '').($allowsspace ? ' ' : '').']/i', '', $stringtosanitize); + + if ($allowsimplequote == 1) { + // Remove all quotes that are inside a string and not around + $tmpchars = explode(',', $result); + $newstringarray = array(); + foreach ($tmpchars as $tmpchar) { + $reg = array(); + if (preg_match('/^\'(.*)\'$/', $tmpchar, $reg)) { + $newstringarray[] = "'".str_replace("'", "", $reg[1])."'"; + } else { + $newstringarray[] = str_replace("'", "", $tmpchar); + } + } + $result = join(',', $newstringarray); + } + + return $result; } /** diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index b453be32572..25beda1136f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -14424,7 +14424,7 @@ function dolForgeSQLCriteriaCallback($matches) $reg = array(); $tmpelem = trim($tmpelem); if (preg_match('/^\'(.*)\'$/', $tmpelem, $reg)) { - $tmpelemarray[$tmpkey] = "'".$db->escape($db->sanitize($reg[1], 1, 1, 1, 1))."'"; + $tmpelemarray[$tmpkey] = "'".$db->escape($db->sanitize($reg[1], 2, 1, 1, 1))."'"; } elseif (ctype_digit((string) $tmpelem)) { // if only 0-9 chars, no . $tmpelemarray[$tmpkey] = (int) $tmpelem; } elseif (is_numeric((string) $tmpelem)) { // it can be a float with a . diff --git a/htdocs/projet/class/taskstats.class.php b/htdocs/projet/class/taskstats.class.php index 99a176c9470..f2f3ee3311e 100644 --- a/htdocs/projet/class/taskstats.class.php +++ b/htdocs/projet/class/taskstats.class.php @@ -162,7 +162,7 @@ class TaskStats extends Stats $sqlwhere[] = " t.datec BETWEEN '".$this->db->idate(dol_get_first_day($this->year, $this->month))."' AND '".$this->db->idate(dol_get_last_day($this->year, $this->month))."'"; } if (!empty($this->priority)) { - $sqlwhere[] = " t.priority IN (".$this->db->sanitize((string) $this->priority, 1).")"; + $sqlwhere[] = " t.priority = ".((int) $this->priority); } if (count($sqlwhere) > 0) { diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 30fb513b859..7f585eed557 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -1925,13 +1925,36 @@ class FunctionsLibTest extends CommonClassTest */ public function testNaturalSearch() { + global $db; + $s = natural_search("t.field", "abc def"); - $this->assertEquals($s, " AND (t.field LIKE '%abc%' AND t.field LIKE '%def%')"); + $this->assertEquals(" AND (t.field LIKE '%abc%' AND t.field LIKE '%def%')", $s); $s = natural_search("t.field", "'abc def' ghi"); - $this->assertEquals($s, " AND (t.field LIKE '%abc def%' AND t.field LIKE '%ghi%')"); + $this->assertEquals(" AND (t.field LIKE '%abc def%' AND t.field LIKE '%ghi%')", $s); - $s = natural_search("t.field", "abc def,ghi", 3); - $this->assertEquals($s, " AND (t.field IN ('abc def','ghi'))"); + $s = natural_search("t.field", "abc def,ghi", 3); // mode 3 is to provide a list of string separated with coma + $this->assertEquals(" AND (t.field IN ('abc def','ghi'))", $s); + + $s = natural_search("t.field", "'ab\'c' def','ghi', 'jkl'", 3); // mode 3 is to provide a list of string separated with coma + $this->assertEquals(" AND (t.field IN ('abc def','ghi','jkl'))", $s); + + $s = natural_search("t.field", "a,b", 3); // mode 3 is to provide a list of string separated with coma + $this->assertEquals(" AND (t.field IN ('a','b'))", $s); + + $s = natural_search("t.field", "A'@%B", 3); // mode 3 is to provide a list of string separated with coma + $this->assertEquals(" AND (t.field IN ('AB'))", $s); + + /* + $s = $db->sanitize("a,b", 1); + var_dump($s); + $s = $db->sanitize("'a',b", 1); + var_dump($s); + $s = $db->sanitize("'a'b',c", 1); + var_dump($s); + */ + + //$s = natural_search("t.field", "KØB", 3); // mode 3 is to provide a list of string separated with coma + //$this->assertEquals(" AND (t.field IN ('KØB'))", $s); } } From 7a0e9d4dc1a0f280d8d509f02889296fa28fd565 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Thu, 6 Mar 2025 03:56:05 +0100 Subject: [PATCH 70/71] Accept utf8 chars in the natural_search in mode 3. Close #32930 --- htdocs/core/db/DoliDB.class.php | 4 ++-- test/phpunit/FunctionsLibTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/db/DoliDB.class.php b/htdocs/core/db/DoliDB.class.php index 3a2346c2356..1caa8d6dcdf 100644 --- a/htdocs/core/db/DoliDB.class.php +++ b/htdocs/core/db/DoliDB.class.php @@ -186,8 +186,8 @@ abstract class DoliDB implements Database */ public function sanitize($stringtosanitize, $allowsimplequote = 0, $allowsequals = 0, $allowsspace = 0, $allowschars = 1) { - //$result = preg_replace('/[^0-9_\-\.,'.($allowschars ? '\p{L}' : '').($allowsequals ? '=' : '').($allowsimplequote ? "\'" : '').($allowsspace ? ' ' : '').']/ui', '', $stringtosanitize); - $result = preg_replace('/[^0-9_\-\.,'.($allowschars ? 'a-z' : '').($allowsequals ? '=' : '').($allowsimplequote ? "\'" : '').($allowsspace ? ' ' : '').']/i', '', $stringtosanitize); + $result = preg_replace('/[^0-9_\-\.,'.($allowschars ? '\p{L}' : '').($allowsequals ? '=' : '').($allowsimplequote ? "\'" : '').($allowsspace ? ' ' : '').']/ui', '', $stringtosanitize); + //$result = preg_replace('/[^0-9_\-\.,'.($allowschars ? 'a-z' : '').($allowsequals ? '=' : '').($allowsimplequote ? "\'" : '').($allowsspace ? ' ' : '').']/i', '', $stringtosanitize); if ($allowsimplequote == 1) { // Remove all quotes that are inside a string and not around diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 7f585eed557..67c3e13b816 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -1954,7 +1954,7 @@ class FunctionsLibTest extends CommonClassTest var_dump($s); */ - //$s = natural_search("t.field", "KØB", 3); // mode 3 is to provide a list of string separated with coma - //$this->assertEquals(" AND (t.field IN ('KØB'))", $s); + $s = natural_search("t.field", "KØB", 3); // mode 3 is to provide a list of string separated with coma + $this->assertEquals(" AND (t.field IN ('KØB'))", $s); } } From d20e730c665c1169ee23479abeabb32da677d49a Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Thu, 6 Mar 2025 04:56:54 +0100 Subject: [PATCH 71/71] Clean code --- htdocs/adherents/class/adherent.class.php | 2 +- htdocs/comm/action/class/actioncomm.class.php | 9 ++++++--- htdocs/compta/deplacement/class/deplacement.class.php | 2 +- htdocs/compta/facture/class/facture.class.php | 1 + htdocs/contrat/class/contrat.class.php | 6 ++++-- htdocs/core/class/commoninvoice.class.php | 11 ++++++----- htdocs/core/class/commonobject.class.php | 3 ++- htdocs/ecm/class/ecmfiles.class.php | 11 ++++++----- htdocs/fourn/class/fournisseur.facture.class.php | 1 + 9 files changed, 28 insertions(+), 18 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 34ef215eb13..e1794d87f0a 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -3211,7 +3211,7 @@ class Adherent extends CommonObject $sendtocc = ''; $sendtobcc = ''; $actioncode = 'EMAIL'; - $extraparams = ''; + $extraparams = array(); $actionmsg = ''; $actionmsg2 = $langs->transnoentities('MailSentByTo', CMailFile::getValidAddress($from, 4, 0, 1), CMailFile::getValidAddress($sendto, 4, 0, 1)); diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 10604bc532b..dd5f369cd4e 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -307,7 +307,7 @@ class ActionComm extends CommonObject public $icalcolor; /** - * @var string Extraparam + * @var array|string Extra parameters. Try to store here the array of parameters. Old code is sometimes storing a string. */ public $extraparams; @@ -531,6 +531,9 @@ class ActionComm extends CommonObject return -1; } + $extraparams = (!empty($this->extraparams) ? json_encode($this->extraparams) : null); + $extraparams = dol_trunc($extraparams, 250); + $this->db->begin(); $sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm"; @@ -592,11 +595,11 @@ class ActionComm extends CommonObject $sql .= "'".$this->db->escape($this->fulldayevent)."', "; $sql .= "'".$this->db->escape($this->location)."', "; $sql .= "'".$this->db->escape($this->transparency)."', "; - $sql .= (!empty($this->fk_element) ? ((int) $this->fk_element) : "null").", "; + $sql .= (!empty($this->elementid) ? ((int) $this->elementid) : "null").", "; $sql .= (!empty($this->elementtype) ? "'".$this->db->escape($this->elementtype)."'" : "null").", "; $sql .= (!empty($this->fk_bookcal_calendar) ? "'".$this->db->escape($this->fk_bookcal_calendar)."'" : "null").", "; $sql .= ((int) $conf->entity).","; - $sql .= (!empty($this->extraparams) ? "'".$this->db->escape($this->extraparams)."'" : "null").", "; + $sql .= (!empty($extraparams) ? "'".$this->db->escape($extraparams)."'" : "null").", "; // Fields emails $sql .= (!empty($this->email_msgid) ? "'".$this->db->escape($this->email_msgid)."'" : "null").", "; $sql .= (!empty($this->email_from) ? "'".$this->db->escape($this->email_from)."'" : "null").", "; diff --git a/htdocs/compta/deplacement/class/deplacement.class.php b/htdocs/compta/deplacement/class/deplacement.class.php index d976c63c5f5..f9be0193da3 100644 --- a/htdocs/compta/deplacement/class/deplacement.class.php +++ b/htdocs/compta/deplacement/class/deplacement.class.php @@ -304,7 +304,7 @@ class Deplacement extends CommonObject $this->note_public = $obj->note_public; $this->fk_project = $obj->fk_project; - $this->extraparams = (array) json_decode($obj->extraparams, true); + $this->extraparams = !empty($obj->extraparams) ? (array) json_decode($obj->extraparams, true) : array(); return 1; } else { diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 2b162e4714d..91b7ac1cb77 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -6044,6 +6044,7 @@ class Facture extends CommonInvoice $actioncomm->errors_to = $errors_to; $actioncomm->elementtype = 'invoice'; + $actioncomm->elementid = $tmpinvoice->id; $actioncomm->fk_element = $tmpinvoice->id; //$actioncomm->extraparams = $extraparams; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index e2e5496e0c8..2785a0f3535 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -1387,7 +1387,9 @@ class Contrat extends CommonObject if (isset($this->import_key)) { $this->import_key = trim($this->import_key); } - //if (isset($this->extraparams)) $this->extraparams=trim($this->extraparams); + + $extraparams = (!empty($this->extraparams) ? json_encode($this->extraparams) : null); + $extraparams = dol_trunc($extraparams, 250); // $this->oldcopy must have been set by the caller of update @@ -1407,7 +1409,7 @@ class Contrat extends CommonObject $sql .= " note_private=".(isset($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null").","; $sql .= " note_public=".(isset($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null").","; $sql .= " import_key=".(isset($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null"); - //$sql.= " extraparams=".(isset($this->extraparams)?"'".$this->db->escape($this->extraparams)."'":"null"); + $sql .= " extraparams=".(isset($extraparams) ? "'".$this->db->escape($extraparams)."'" : "null"); $sql .= " WHERE rowid=".((int) $this->id); $this->db->begin(); diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index a2a431b00db..40157e16ed7 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -1617,7 +1617,7 @@ abstract class CommonInvoice extends CommonObject $extraparams .= (($extraparams && $stripefailuredeclinecode) ? ' - ' : '') . $stripefailuredeclinecode; } else { $actioncode = 'PAYMENT_STRIPE_OK'; - $extraparams = ''; + $extraparams = array(); } } else { $error++; @@ -1635,7 +1635,7 @@ abstract class CommonInvoice extends CommonObject $object = $this; $actioncode = 'PAYMENT_STRIPE_KO'; - $extraparams = ''; + $extraparams = array(); } } else { // If error because payment was canceled for a logical reason, we do nothing (no event added) @@ -1646,7 +1646,7 @@ abstract class CommonInvoice extends CommonObject $object = $this; $actioncode = ''; - $extraparams = ''; + $extraparams = array(); } } else { // Else of the if ($resultthirdparty > 0 && ! empty($customer)) { if ($resultthirdparty <= 0) { @@ -1669,7 +1669,7 @@ abstract class CommonInvoice extends CommonObject $object = $this; $actioncode = 'PAYMENT_STRIPE_KO'; - $extraparams = ''; + $extraparams = array(); } if ($description) { @@ -1701,8 +1701,9 @@ abstract class CommonInvoice extends CommonObject $actioncomm->email_subject = $object->email_subject; $actioncomm->errors_to = $object->errors_to;*/ $actioncomm->fk_element = $this->id; + $actioncomm->elementid = $this->id; $actioncomm->elementtype = $this->element; - $actioncomm->extraparams = dol_trunc($extraparams, 250); + $actioncomm->extraparams = $extraparams; // Can be null, empty string or array() $actioncomm->create($user); } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 81f282a76d7..35d777bcef0 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -823,7 +823,7 @@ abstract class CommonObject public $output; /** - * @var array|string extra parameters. Try to store here the array of parameters. Old code is sometimes storing a string. + * @var array|string Extra parameters. Try to store here the array of parameters. Old code is sometimes storing a string. */ public $extraparams = array(); @@ -5191,6 +5191,7 @@ abstract class CommonObject $this->db->begin(); $extraparams = (!empty($this->extraparams) ? json_encode($this->extraparams) : null); + $extraparams = dol_trunc($extraparams, 250); $sql = "UPDATE ".$this->db->prefix().$this->table_element; $sql .= " SET extraparams = ".(!empty($extraparams) ? "'".$this->db->escape($extraparams)."'" : "null"); diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php index 0bd44eceb31..97af81682a9 100644 --- a/htdocs/ecm/class/ecmfiles.class.php +++ b/htdocs/ecm/class/ecmfiles.class.php @@ -118,7 +118,7 @@ class EcmFiles extends CommonObject public $gen_or_uploaded; /** - * @var string extraparams + * @var array|string Extra parameters. Try to store here the array of parameters. Old code is sometimes storing a string. */ public $extraparams; @@ -250,9 +250,6 @@ class EcmFiles extends CommonObject if (isset($this->gen_or_uploaded)) { $this->gen_or_uploaded = trim($this->gen_or_uploaded); } - if (isset($this->extraparams)) { - $this->extraparams = trim($this->extraparams); - } if (isset($this->fk_user_c)) { $this->fk_user_c = (int) $this->fk_user_c; } @@ -305,6 +302,10 @@ class EcmFiles extends CommonObject if (!isset($this->entity)) { $this->entity = $conf->entity; } + + $extraparams = (!empty($this->extraparams) ? json_encode($this->extraparams) : null); + $extraparams = dol_trunc($extraparams, 250); + // Put here code to add control on parameters values // Insert request @@ -348,7 +349,7 @@ class EcmFiles extends CommonObject $sql .= ' '.(!isset($this->cover) ? 'NULL' : "'".$this->db->escape($this->cover)."'").','; $sql .= ' '.((int) $maxposition).','; $sql .= ' '.(!isset($this->gen_or_uploaded) ? 'NULL' : "'".$this->db->escape($this->gen_or_uploaded)."'").','; - $sql .= ' '.(!isset($this->extraparams) ? 'NULL' : "'".$this->db->escape($this->extraparams)."'").','; + $sql .= ' '.(!isset($extraparams) ? 'NULL' : "'".$this->db->escape($extraparams)."'").','; $sql .= " '".$this->db->idate($this->date_c)."',"; $sql .= ' '.(!isset($this->date_m) || dol_strlen((string) $this->date_m) == 0 ? 'NULL' : "'".$this->db->idate($this->date_m)."'").','; $sql .= ' '.(!isset($this->fk_user_c) ? $user->id : $this->fk_user_c).','; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index d911e369d69..3afb4e92bd5 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -3680,6 +3680,7 @@ class FactureFournisseur extends CommonInvoice $actioncomm->errors_to = $errors_to; $actioncomm->elementtype = 'invoice_supplier'; + $actioncomm->elementid = $tmpinvoice->id; $actioncomm->fk_element = $tmpinvoice->id; //$actioncomm->extraparams = $extraparams;