diff --git a/dev/tools/phan/config.php b/dev/tools/phan/config.php
index 9821b5049b7..1dc71344d2d 100644
--- a/dev/tools/phan/config.php
+++ b/dev/tools/phan/config.php
@@ -83,6 +83,7 @@ return [
// Alternately, you can pass in the full path to a PHP file
// with the plugin's implementation (e.g. 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php')
'plugins' => [
+ __DIR__.'/plugins/NoVarDumpPlugin.php',
// checks if a function, closure or method unconditionally returns.
// can also be written as 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php'
//'DeprecateAliasPlugin',
@@ -149,9 +150,13 @@ return [
'PhanPluginShortArray',
'PhanPluginNumericalComparison',
'PhanPluginUnknownObjectMethodCall',
- 'PhanPluginCanUseParamType',
'PhanPluginNonBoolInLogicalArith',
- 'PhanPluginCanUseReturnType',
+ // Fixers From PHPDocToRealTypesPlugin:
+ 'PhanPluginCanUseParamType', // Fixer - Report/Add types in the function definition (function abc(string $var) (adds string)
+ 'PhanPluginCanUseReturnType', // Fixer - Report/Add return types in the function definition (function abc(string $var) (adds string)
+ 'PhanPluginCanUseNullableParamType', // Fixer - Report/Add nullable parameter types in the function definition
+ 'PhanPluginCanUseNullableReturnType', // Fixer - Report/Add nullable return types in the function definition
+
// 'PhanPluginNotFullyQualifiedFunctionCall',
'PhanPluginConstantVariableScalar',
// 'PhanPluginNoCommentOnPublicProperty',
@@ -166,7 +171,6 @@ return [
'PhanPluginUnknownArrayMethodReturnType',
'PhanTypeMismatchArgumentInternal',
'PhanPluginDuplicateAdjacentStatement',
- 'PhanPluginCanUseNullableParamType',
'PhanTypeInvalidLeftOperandOfNumericOp',
'PhanTypeMismatchProperty',
// 'PhanPluginNoCommentOnPublicMethod',
@@ -190,7 +194,6 @@ return [
'PhanTypeInvalidLeftOperandOfAdd',
// 'PhanPluginNoCommentOnPrivateProperty',
// 'PhanPluginNoCommentOnFunction',
- 'PhanPluginCanUseNullableReturnType',
'PhanPluginUnknownArrayFunctionParamType',
// 'PhanPluginDescriptionlessCommentOnPublicProperty',
'PhanPluginUnknownFunctionParamType',
diff --git a/dev/tools/phan/config_extended.php b/dev/tools/phan/config_extended.php
index 2e748430fe2..9a721355daf 100644
--- a/dev/tools/phan/config_extended.php
+++ b/dev/tools/phan/config_extended.php
@@ -83,6 +83,7 @@ return [
// Alternately, you can pass in the full path to a PHP file
// with the plugin's implementation (e.g. 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php')
'plugins' => [
+ __DIR__.'/plugins/NoVarDumpPlugin.php',
'DeprecateAliasPlugin',
//'EmptyMethodAndFunctionPlugin',
'InvalidVariableIssetPlugin',
@@ -102,7 +103,7 @@ return [
'NonBoolBranchPlugin', // Requires test on bool, nont on ints
'NonBoolInLogicalArithPlugin',
'NumericalComparisonPlugin',
- 'PHPDocToRealTypesPlugin',
+ // 'PHPDocToRealTypesPlugin', // Report/Add types to function definitions
'PHPDocInWrongCommentPlugin', // Missing /** (/* was used)
//'ShortArrayPlugin', // Checks that [] is used
//'StrictLiteralComparisonPlugin',
@@ -138,10 +139,11 @@ return [
'PhanPluginCanUsePHP71Void', // Dolibarr is maintaining 7.0 compatibility
'PhanPluginShortArray', // Dolibarr uses array()
'PhanPluginShortArrayList', // Dolibarr uses array()
- // The following may require that --quick is not used
- 'PhanPluginCanUseParamType', // Does not seem useful: is reporting types already in PHPDoc?
- 'PhanPluginCanUseReturnType', // Does not seem useful: is reporting types already in PHPDoc?
- 'PhanPluginCanUseNullableParamType', // Does not seem useful: is reporting types already in PHPDoc?
+ // Fixers From PHPDocToRealTypesPlugin:
+ 'PhanPluginCanUseParamType', // Fixer - Report/Add types in the function definition (function abc(string $var) (adds string)
+ 'PhanPluginCanUseReturnType', // Fixer - Report/Add return types in the function definition (function abc(string $var) (adds string)
+ 'PhanPluginCanUseNullableParamType', // Fixer - Report/Add nullable parameter types in the function definition
+ 'PhanPluginCanUseNullableReturnType', // Fixer - Report/Add nullable return types in the function definition
'PhanPluginNonBoolBranch', // Not essential - 31240+ occurrences
'PhanPluginNumericalComparison', // Not essential - 19870+ occurrences
'PhanTypeMismatchArgument', // Not essential - 12300+ occurrences
diff --git a/dev/tools/phan/plugins/NoVarDumpPlugin.php b/dev/tools/phan/plugins/NoVarDumpPlugin.php
new file mode 100644
index 00000000000..b2b093922f7
--- /dev/null
+++ b/dev/tools/phan/plugins/NoVarDumpPlugin.php
@@ -0,0 +1,81 @@
+
+ */
+
+declare(strict_types=1);
+
+use ast\Node;
+use Phan\PluginV3;
+use Phan\PluginV3\PluginAwarePostAnalysisVisitor;
+use Phan\PluginV3\PostAnalyzeNodeCapability;
+
+/**
+ * NoVarDumpPlugin hooks into one event:
+ *
+ * - getPostAnalyzeNodeVisitorClassName
+ * This method returns a visitor that is called on every AST node from every
+ * file being analyzed
+ *
+ * A plugin file must
+ *
+ * - Contain a class that inherits from \Phan\PluginV3
+ *
+ * - End by returning an instance of that class.
+ *
+ * It is assumed without being checked that plugins aren't
+ * mangling state within the passed code base or context.
+ *
+ * Note: When adding new plugins,
+ * add them to the corresponding section of README.md
+ */
+class NoVarDumpPlugin extends PluginV3 implements PostAnalyzeNodeCapability
+{
+ /**
+ * @return string - name of PluginAwarePostAnalysisVisitor subclass
+ */
+ public static function getPostAnalyzeNodeVisitorClassName(): string
+ {
+ return NoVarDumpVisitor::class;
+ }
+}
+
+/**
+ * When __invoke on this class is called with a node, a method
+ * will be dispatched based on the `kind` of the given node.
+ *
+ * Visitors such as this are useful for defining lots of different
+ * checks on a node based on its kind.
+ */
+class NoVarDumpVisitor extends PluginAwarePostAnalysisVisitor
+{
+ // A plugin's visitors should not override visit() unless they need to.
+
+ /**
+ * @param Node $node A node to analyze
+ *
+ * @return void
+ *
+ * @override
+ */
+ public function visitCall(Node $node): void
+ {
+ $name = $node->children['expr']->children['name'] ?? null;
+ if (!is_string($name)) {
+ return;
+ }
+ if (strcasecmp($name, 'var_dump') !== 0) {
+ return;
+ }
+ $this->emitPluginIssue(
+ $this->code_base,
+ $this->context,
+ 'NoVarDumpPlugin',
+ 'var_dump() should be commented in submitted code',
+ []
+ );
+ }
+}
+
+// Every plugin needs to return an instance of itself at the
+// end of the file in which it's defined.
+return new NoVarDumpPlugin();
diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php
index d6981147691..9eb4626c3bc 100644
--- a/htdocs/admin/company.php
+++ b/htdocs/admin/company.php
@@ -106,13 +106,14 @@ if (($action == 'update' && !GETPOST("cancel", 'alpha'))
$db->begin();
- dolibarr_set_const($db, "MAIN_INFO_SOCIETE_NOM", GETPOST("nom", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
+ dolibarr_set_const($db, "MAIN_INFO_SOCIETE_NOM", GETPOST("name", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_INFO_SOCIETE_ADDRESS", GETPOST("MAIN_INFO_SOCIETE_ADDRESS", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_INFO_SOCIETE_TOWN", GETPOST("MAIN_INFO_SOCIETE_TOWN", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_INFO_SOCIETE_ZIP", GETPOST("MAIN_INFO_SOCIETE_ZIP", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_INFO_SOCIETE_REGION", GETPOST("region_code", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_MONNAIE", GETPOST("currency", 'aZ09'), 'chaine', 0, '', $conf->entity);
- dolibarr_set_const($db, "MAIN_INFO_SOCIETE_TEL", GETPOST("tel", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
+ dolibarr_set_const($db, "MAIN_INFO_SOCIETE_TEL", GETPOST("phone", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
+ dolibarr_set_const($db, "MAIN_INFO_SOCIETE_MOBILE", GETPOST("phone_mobile", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_INFO_SOCIETE_FAX", GETPOST("fax", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_INFO_SOCIETE_MAIL", GETPOST("mail", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_INFO_SOCIETE_WEB", GETPOST("web", 'alphanohtml'), 'chaine', 0, '', $conf->entity);
@@ -440,18 +441,18 @@ print '
'.$langs->
// Name
print ' '.$langs->trans("CompanyName").' ';
-print ' '."\n";
+print ' '."\n";
// Address
print ''.$langs->trans("CompanyAddress").' ';
-print ' '."\n";
+print ''."\n";
// Zip
print ''.$langs->trans("CompanyZip").' ';
-print ' '."\n";
+print ' '."\n";
print ''.$langs->trans("CompanyTown").' ';
-print ' '."\n";
+print ' '."\n";
// Country
print ''.$langs->trans("Country").' ';
@@ -481,13 +482,19 @@ print ' '."\n";
// Phone
print ''.$langs->trans("Phone").' ';
print img_picto('', 'object_phoning', '', false, 0, 0, '', 'pictofixedwidth');
-print ' ';
+print ' ';
+print ''."\n";
+
+// Phone mobile
+print ''.$langs->trans("PhoneMobile").' ';
+print img_picto('', 'object_phoning_mobile', '', false, 0, 0, '', 'pictofixedwidth');
+print ' ';
print ''."\n";
// Fax
print ''.$langs->trans("Fax").' ';
print img_picto('', 'object_phoning_fax', '', false, 0, 0, '', 'pictofixedwidth');
-print ' ';
+print ' ';
print ''."\n";
// Email
diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php
index 9fb167e4e46..0037dc520cf 100644
--- a/htdocs/categories/class/categorie.class.php
+++ b/htdocs/categories/class/categorie.class.php
@@ -10,7 +10,7 @@
* Copyright (C) 2015 Marcos García
* Copyright (C) 2015 Raphaël Doursenaud
* Copyright (C) 2016 Charlie Benke
- * Copyright (C) 2018-2023 Frédéric France
+ * Copyright (C) 2018-2024 Frédéric France
* Copyright (C) 2023 Benjamin Falière
*
* This program is free software; you can redistribute it and/or modify
@@ -1707,7 +1707,7 @@ class Categorie extends CommonObject
* @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
* @return string Chaine avec URL
*/
- public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $moreparam = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = '')
+ public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $moreparam = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = 0)
{
global $conf, $langs, $hookmanager;
diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php
index d471e9d7ca4..de9e0bd9892 100644
--- a/htdocs/commande/list.php
+++ b/htdocs/commande/list.php
@@ -2727,7 +2727,7 @@ while ($i < $imaxinloop) {
// Billed
if (!empty($arrayfields['c.facture']['checked'])) {
- print ''.yn($obj->billed).' ';
+ print ''.yn($obj->billed, 4).' ';
if (!$i) {
$totalarray['nbfield']++;
}
diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php
index eb113f1ddb9..bc316e5b80f 100644
--- a/htdocs/core/lib/files.lib.php
+++ b/htdocs/core/lib/files.lib.php
@@ -2660,14 +2660,14 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
}
}
// Fix modulepart for backward compatibility
- if ($modulepart == 'users') {
+ if ($modulepart == 'facture') {
+ $modulepart = 'invoice';
+ } elseif ($modulepart == 'users') {
$modulepart = 'user';
- }
- if ($modulepart == 'tva') {
+ } elseif ($modulepart == 'tva') {
$modulepart = 'tax-vat';
- }
- // Fix modulepart delivery
- if ($modulepart == 'expedition' && strpos($original_file, 'receipt/') === 0) {
+ } elseif ($modulepart == 'expedition' && strpos($original_file, 'receipt/') === 0) {
+ // Fix modulepart delivery
$modulepart = 'delivery';
}
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 779359719e5..391dbe2e0b4 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -7236,6 +7236,9 @@ function yn($yesno, $case = 1, $color = 0)
if ($case == 3) {
$result = ' '.$result;
}
+ if ($case == 4) {
+ $result = img_picto('check', 'check');
+ }
$classname = 'ok';
} elseif ($yesno == 0 || strtolower($yesno) == 'no' || strtolower($yesno) == 'false') {
@@ -7249,6 +7252,9 @@ function yn($yesno, $case = 1, $color = 0)
if ($case == 3) {
$result = ' '.$result;
}
+ if ($case == 4) {
+ $result = img_picto('uncheck', 'uncheck');
+ }
if ($color == 2) {
$classname = 'ok';
diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php
index df55b335132..27b78638c33 100644
--- a/htdocs/core/lib/functions2.lib.php
+++ b/htdocs/core/lib/functions2.lib.php
@@ -1912,7 +1912,7 @@ function getListOfModels($db, $type, $maxfilenamelength = 0)
}
if (is_dir($tmpdir)) {
// all type of template is allowed
- $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '', '', 'name', SORT_ASC, 0);
+ $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '', null, 'name', SORT_ASC, 0);
if (count($tmpfiles)) {
$listoffiles = array_merge($listoffiles, $tmpfiles);
}
diff --git a/htdocs/delivery/class/delivery.class.php b/htdocs/delivery/class/delivery.class.php
index 26cea82e0d7..1dfc406a9b9 100644
--- a/htdocs/delivery/class/delivery.class.php
+++ b/htdocs/delivery/class/delivery.class.php
@@ -6,7 +6,7 @@
* Copyright (C) 2011-2023 Philippe Grand
* Copyright (C) 2013 Florian Henry
* Copyright (C) 2014-2015 Marcos García
- * Copyright (C) 2023 Frédéric France
+ * Copyright (C) 2023-2024 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
@@ -599,10 +599,10 @@ class Delivery extends CommonObject
* Update a livraison line (only extrafields)
*
* @param int $id Id of line (livraison line)
- * @param array $array_options extrafields array
+ * @param array $array_options extrafields array
* @return int Return integer <0 if KO, >0 if OK
*/
- public function update_line($id, $array_options = 0)
+ public function update_line($id, $array_options = [])
{
// phpcs:enable
global $conf;
diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php
index 8c004650de0..5216aa24d81 100644
--- a/htdocs/fourn/class/fournisseur.facture.class.php
+++ b/htdocs/fourn/class/fournisseur.facture.class.php
@@ -250,55 +250,55 @@ class FactureFournisseur extends CommonInvoice
public $fk_fac_rec_source;
public $fields = array(
- 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10),
- 'ref' =>array('type'=>'varchar(255)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'showoncombobox'=>1, 'position'=>15),
- 'ref_supplier' =>array('type'=>'varchar(255)', 'label'=>'RefSupplier', 'enabled'=>1, 'visible'=>-1, 'position'=>20),
- 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>25, 'index'=>1),
- 'ref_ext' =>array('type'=>'varchar(255)', 'label'=>'RefExt', 'enabled'=>1, 'visible'=>0, 'position'=>30),
- 'type' =>array('type'=>'smallint(6)', 'label'=>'Type', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35),
- 'subtype' =>array('type'=>'smallint(6)', 'label'=>'InvoiceSubtype', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>36),
- 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'notnull'=>1, 'position'=>40),
- 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>45),
- 'datef' =>array('type'=>'date', 'label'=>'Date', 'enabled'=>1, 'visible'=>-1, 'position'=>50),
- 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>55),
- 'libelle' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>-1, 'position'=>60),
- 'paye' =>array('type'=>'smallint(6)', 'label'=>'Paye', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>65),
- 'amount' =>array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>70),
- 'remise' =>array('type'=>'double(24,8)', 'label'=>'Discount', 'enabled'=>1, 'visible'=>-1, 'position'=>75),
- 'close_code' =>array('type'=>'varchar(16)', 'label'=>'CloseCode', 'enabled'=>1, 'visible'=>-1, 'position'=>80),
- 'close_note' =>array('type'=>'varchar(128)', 'label'=>'CloseNote', 'enabled'=>1, 'visible'=>-1, 'position'=>85),
- 'tva' =>array('type'=>'double(24,8)', 'label'=>'Tva', 'enabled'=>1, 'visible'=>-1, 'position'=>90),
- 'localtax1' =>array('type'=>'double(24,8)', 'label'=>'Localtax1', 'enabled'=>1, 'visible'=>-1, 'position'=>95),
- 'localtax2' =>array('type'=>'double(24,8)', 'label'=>'Localtax2', 'enabled'=>1, 'visible'=>-1, 'position'=>100),
- 'total_ht' =>array('type'=>'double(24,8)', 'label'=>'TotalHT', 'enabled'=>1, 'visible'=>-1, 'position'=>105),
- 'total_tva' =>array('type'=>'double(24,8)', 'label'=>'TotalVAT', 'enabled'=>1, 'visible'=>-1, 'position'=>110),
- 'total_ttc' =>array('type'=>'double(24,8)', 'label'=>'TotalTTC', 'enabled'=>1, 'visible'=>-1, 'position'=>115),
- 'fk_user_author' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-1, 'position'=>125),
- 'fk_user_modif' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'position'=>130),
- 'fk_user_valid' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>135),
- 'fk_facture_source' =>array('type'=>'integer', 'label'=>'Fk facture source', 'enabled'=>1, 'visible'=>-1, 'position'=>140),
- 'fk_projet' =>array('type'=>'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'visible'=>-1, 'position'=>145),
- 'fk_account' =>array('type'=>'integer', 'label'=>'Account', 'enabled'=>'isModEnabled("banque")', 'visible'=>-1, 'position'=>150),
- 'fk_cond_reglement' =>array('type'=>'integer', 'label'=>'PaymentTerm', 'enabled'=>1, 'visible'=>-1, 'position'=>155),
- 'fk_mode_reglement' =>array('type'=>'integer', 'label'=>'PaymentMode', 'enabled'=>1, 'visible'=>-1, 'position'=>160),
- 'date_lim_reglement' =>array('type'=>'date', 'label'=>'DateLimReglement', 'enabled'=>1, 'visible'=>-1, 'position'=>165),
- 'note_private' =>array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>170),
- 'note_public' =>array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>175),
- 'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'ModelPdf', 'enabled'=>1, 'visible'=>0, 'position'=>180),
- 'extraparams' =>array('type'=>'varchar(255)', 'label'=>'Extraparams', 'enabled'=>1, 'visible'=>-1, 'position'=>190),
- 'fk_incoterms' =>array('type'=>'integer', 'label'=>'IncotermCode', 'enabled'=>1, 'visible'=>-1, 'position'=>195),
- 'location_incoterms' =>array('type'=>'varchar(255)', 'label'=>'IncotermLocation', 'enabled'=>1, 'visible'=>-1, 'position'=>200),
- 'fk_multicurrency' =>array('type'=>'integer', 'label'=>'MulticurrencyId', 'enabled'=>1, 'visible'=>-1, 'position'=>205),
- 'multicurrency_code' =>array('type'=>'varchar(255)', 'label'=>'MulticurrencyCode', 'enabled'=>1, 'visible'=>-1, 'position'=>210),
- 'multicurrency_tx' =>array('type'=>'double(24,8)', 'label'=>'MulticurrencyRate', 'enabled'=>1, 'visible'=>-1, 'position'=>215),
- 'multicurrency_total_ht' =>array('type'=>'double(24,8)', 'label'=>'MulticurrencyTotalHT', 'enabled'=>1, 'visible'=>-1, 'position'=>220),
- 'multicurrency_total_tva' =>array('type'=>'double(24,8)', 'label'=>'MulticurrencyTotalVAT', 'enabled'=>1, 'visible'=>-1, 'position'=>225),
- 'multicurrency_total_ttc' =>array('type'=>'double(24,8)', 'label'=>'MulticurrencyTotalTTC', 'enabled'=>1, 'visible'=>-1, 'position'=>230),
- 'date_pointoftax' =>array('type'=>'date', 'label'=>'Date pointoftax', 'enabled'=>1, 'visible'=>-1, 'position'=>235),
- 'date_valid' =>array('type'=>'date', 'label'=>'DateValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>240),
- 'last_main_doc' =>array('type'=>'varchar(255)', 'label'=>'Last main doc', 'enabled'=>1, 'visible'=>-1, 'position'=>245),
- 'fk_statut' =>array('type'=>'smallint(6)', 'label'=>'Status', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>500),
- 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>900),
+ 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
+ 'ref' => array('type' => 'varchar(255)', 'label' => 'Ref', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'showoncombobox' => 1, 'position' => 15),
+ 'ref_supplier' => array('type' => 'varchar(255)', 'label' => 'RefSupplier', 'enabled' => 1, 'visible' => -1, 'position' => 20),
+ 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => 1, 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 25, 'index' => 1),
+ 'ref_ext' => array('type' => 'varchar(255)', 'label' => 'RefExt', 'enabled' => 1, 'visible' => 0, 'position' => 30),
+ 'type' => array('type' => 'smallint(6)', 'label' => 'Type', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 35),
+ 'subtype' => array('type' => 'smallint(6)', 'label' => 'InvoiceSubtype', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 36),
+ 'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 'isModEnabled("societe")', 'visible' => -1, 'notnull' => 1, 'position' => 40),
+ 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 45),
+ 'datef' => array('type' => 'date', 'label' => 'Date', 'enabled' => 1, 'visible' => -1, 'position' => 50),
+ 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 55),
+ 'libelle' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'visible' => -1, 'position' => 60),
+ 'paye' => array('type' => 'smallint(6)', 'label' => 'Paye', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 65),
+ 'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 70),
+ 'remise' => array('type' => 'double(24,8)', 'label' => 'Discount', 'enabled' => 1, 'visible' => -1, 'position' => 75),
+ 'close_code' => array('type' => 'varchar(16)', 'label' => 'CloseCode', 'enabled' => 1, 'visible' => -1, 'position' => 80),
+ 'close_note' => array('type' => 'varchar(128)', 'label' => 'CloseNote', 'enabled' => 1, 'visible' => -1, 'position' => 85),
+ 'tva' => array('type' => 'double(24,8)', 'label' => 'Tva', 'enabled' => 1, 'visible' => -1, 'position' => 90),
+ 'localtax1' => array('type' => 'double(24,8)', 'label' => 'Localtax1', 'enabled' => 1, 'visible' => -1, 'position' => 95),
+ 'localtax2' => array('type' => 'double(24,8)', 'label' => 'Localtax2', 'enabled' => 1, 'visible' => -1, 'position' => 100),
+ 'total_ht' => array('type' => 'double(24,8)', 'label' => 'TotalHT', 'enabled' => 1, 'visible' => -1, 'position' => 105),
+ 'total_tva' => array('type' => 'double(24,8)', 'label' => 'TotalVAT', 'enabled' => 1, 'visible' => -1, 'position' => 110),
+ 'total_ttc' => array('type' => 'double(24,8)', 'label' => 'TotalTTC', 'enabled' => 1, 'visible' => -1, 'position' => 115),
+ 'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => -1, 'position' => 125),
+ 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 130),
+ 'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 135),
+ 'fk_facture_source' => array('type' => 'integer', 'label' => 'Fk facture source', 'enabled' => 1, 'visible' => -1, 'position' => 140),
+ 'fk_projet' => array('type' => 'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label' => 'Project', 'enabled' => "isModEnabled('project')", 'visible' => -1, 'position' => 145),
+ 'fk_account' => array('type' => 'integer', 'label' => 'Account', 'enabled' => 'isModEnabled("banque")', 'visible' => -1, 'position' => 150),
+ 'fk_cond_reglement' => array('type' => 'integer', 'label' => 'PaymentTerm', 'enabled' => 1, 'visible' => -1, 'position' => 155),
+ 'fk_mode_reglement' => array('type' => 'integer', 'label' => 'PaymentMode', 'enabled' => 1, 'visible' => -1, 'position' => 160),
+ 'date_lim_reglement' => array('type' => 'date', 'label' => 'DateLimReglement', 'enabled' => 1, 'visible' => -1, 'position' => 165),
+ 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 170),
+ 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 175),
+ 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'ModelPdf', 'enabled' => 1, 'visible' => 0, 'position' => 180),
+ 'extraparams' => array('type' => 'varchar(255)', 'label' => 'Extraparams', 'enabled' => 1, 'visible' => -1, 'position' => 190),
+ 'fk_incoterms' => array('type' => 'integer', 'label' => 'IncotermCode', 'enabled' => 1, 'visible' => -1, 'position' => 195),
+ 'location_incoterms' => array('type' => 'varchar(255)', 'label' => 'IncotermLocation', 'enabled' => 1, 'visible' => -1, 'position' => 200),
+ 'fk_multicurrency' => array('type' => 'integer', 'label' => 'MulticurrencyId', 'enabled' => 1, 'visible' => -1, 'position' => 205),
+ 'multicurrency_code' => array('type' => 'varchar(255)', 'label' => 'MulticurrencyCode', 'enabled' => 1, 'visible' => -1, 'position' => 210),
+ 'multicurrency_tx' => array('type' => 'double(24,8)', 'label' => 'MulticurrencyRate', 'enabled' => 1, 'visible' => -1, 'position' => 215),
+ 'multicurrency_total_ht' => array('type' => 'double(24,8)', 'label' => 'MulticurrencyTotalHT', 'enabled' => 1, 'visible' => -1, 'position' => 220),
+ 'multicurrency_total_tva' => array('type' => 'double(24,8)', 'label' => 'MulticurrencyTotalVAT', 'enabled' => 1, 'visible' => -1, 'position' => 225),
+ 'multicurrency_total_ttc' => array('type' => 'double(24,8)', 'label' => 'MulticurrencyTotalTTC', 'enabled' => 1, 'visible' => -1, 'position' => 230),
+ 'date_pointoftax' => array('type' => 'date', 'label' => 'Date pointoftax', 'enabled' => 1, 'visible' => -1, 'position' => 235),
+ 'date_valid' => array('type' => 'date', 'label' => 'DateValidation', 'enabled' => 1, 'visible' => -1, 'position' => 240),
+ 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'Last main doc', 'enabled' => 1, 'visible' => -1, 'position' => 245),
+ 'fk_statut' => array('type' => 'smallint(6)', 'label' => 'Status', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 500),
+ 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 900),
);
@@ -1350,7 +1350,7 @@ class FactureFournisseur extends CommonInvoice
$facligne->rang = 1;
$linecount = count($this->lines);
for ($ii = 1; $ii <= $linecount; $ii++) {
- $this->updateRangOfLine($this->lines[$ii - 1]->id, $ii+1);
+ $this->updateRangOfLine($this->lines[$ii - 1]->id, $ii + 1);
}
}
@@ -2658,7 +2658,7 @@ class FactureFournisseur extends CommonInvoice
}
if ($qualified) {
$paymentornot = ($obj->fk_paiementfourn ? 1 : 0);
- $return[$obj->rowid] = array('ref'=>$obj->ref, 'status'=>$obj->fk_statut, 'type'=>$obj->type, 'paye'=>$obj->paye, 'paymentornot'=>$paymentornot);
+ $return[$obj->rowid] = array('ref' => $obj->ref, 'status' => $obj->fk_statut, 'type' => $obj->type, 'paye' => $obj->paye, 'paymentornot' => $paymentornot);
}
}
@@ -2922,7 +2922,7 @@ class FactureFournisseur extends CommonInvoice
}
global $action;
$hookmanager->initHooks(array($this->element . 'dao'));
- $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
+ $parameters = array('id' => $this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) {
$result = $hookmanager->resPrint;
@@ -3689,7 +3689,7 @@ class FactureFournisseur extends CommonInvoice
return 0;
} else {
- $this->error = 'Nb of emails sent : '.$nbMailSend.', '.(!empty($errorsMsg)) ? join(', ', $errorsMsg) : $error;
+ $this->error = 'Nb of emails sent : '.$nbMailSend.', '.(!empty($errorsMsg)) ? implode(', ', $errorsMsg) : $error;
dol_syslog(__METHOD__." end - ".$this->error, LOG_INFO);
diff --git a/htdocs/product/stats/commande.php b/htdocs/product/stats/commande.php
index 3532afb8116..eedd1cb47c8 100644
--- a/htdocs/product/stats/commande.php
+++ b/htdocs/product/stats/commande.php
@@ -69,7 +69,7 @@ if (!$sortfield) {
$search_month = GETPOST('search_month', 'int');
$search_year = GETPOST('search_year', 'int');
if (GETPOSTISARRAY('search_status')) {
- $search_status = join(',', GETPOST('search_status', 'array:intcomma'));
+ $search_status = implode(',', GETPOST('search_status', 'array:intcomma'));
} else {
$search_status = (GETPOST('search_status', 'intcomma') != '' ? GETPOST('search_status', 'intcomma') : GETPOST('statut', 'intcomma'));
}
@@ -100,7 +100,7 @@ if ($id > 0 || !empty($ref)) {
$object = $product;
- $parameters = array('id'=>$id);
+ $parameters = array('id' => $id);
$reshook = $hookmanager->executeHooks('doActions', $parameters, $product, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook < 0) {
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
diff --git a/htdocs/product/stats/commande_fournisseur.php b/htdocs/product/stats/commande_fournisseur.php
index a76c572af19..44e35990683 100644
--- a/htdocs/product/stats/commande_fournisseur.php
+++ b/htdocs/product/stats/commande_fournisseur.php
@@ -69,7 +69,7 @@ if (!$sortfield) {
$search_month = GETPOST('search_month', 'int');
$search_year = GETPOST('search_year', 'int');
if (GETPOSTISARRAY('search_status')) {
- $search_status = join(',', GETPOST('search_status', 'array:intcomma'));
+ $search_status = implode(',', GETPOST('search_status', 'array:intcomma'));
} else {
$search_status = (GETPOST('search_status', 'intcomma') != '' ? GETPOST('search_status', 'intcomma') : GETPOST('statut', 'intcomma'));
}
diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php
index ff079efe387..265f218fc53 100644
--- a/htdocs/projet/class/task.class.php
+++ b/htdocs/projet/class/task.class.php
@@ -2,7 +2,7 @@
/* Copyright (C) 2008-2014 Laurent Destailleur
* Copyright (C) 2010-2012 Regis Houssin
* Copyright (C) 2014 Marcos García
- * Copyright (C) 2018-2024 Frédéric France
+ * Copyright (C) 2018-2024 Frédéric France
* Copyright (C) 2020 Juanjo Menent
* Copyright (C) 2022 Charlene Benke
* Copyright (C) 2023 Gauthier VERDOL
@@ -903,14 +903,14 @@ class Task extends CommonObjectLine
{
$this->id = 0;
- $this->fk_project = '';
+ $this->fk_project = 0;
$this->ref = 'TK01';
- $this->fk_task_parent = null;
+ $this->fk_task_parent = 0;
$this->label = 'Specimen task TK01';
$this->duration_effective = '';
- $this->fk_user_creat = null;
+ $this->fk_user_creat = 1;
$this->progress = '25';
- $this->status = null;
+ $this->status = 0;
$this->note = 'This is a specimen task not';
}
diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php
index 44ff7c4a6fb..ee2587cc04e 100644
--- a/htdocs/reception/class/reception.class.php
+++ b/htdocs/reception/class/reception.class.php
@@ -937,7 +937,7 @@ class Reception extends CommonObject
$this->fk_user_valid = trim($this->fk_user_valid);
}
if (isset($this->shipping_method_id)) {
- $this->shipping_method_id = trim($this->shipping_method_id);
+ $this->shipping_method_id = (int) $this->shipping_method_id;
}
if (isset($this->tracking_number)) {
$this->tracking_number = trim($this->tracking_number);
diff --git a/htdocs/resource/class/html.formresource.class.php b/htdocs/resource/class/html.formresource.class.php
index 0241e62a8fc..425ee481964 100644
--- a/htdocs/resource/class/html.formresource.class.php
+++ b/htdocs/resource/class/html.formresource.class.php
@@ -1,6 +1,6 @@
- * Copyright (C) 2019 Frédéric France
+ * Copyright (C) 2019-2024 Frédéric France
* Copyright (C) 2022 Ferran Marcet
* Copyright (C) 2023 William Mead
*
@@ -80,7 +80,7 @@ class FormResource
* @param bool $multiple add [] in the name of element and add 'multiple' attribute
* @return string|array HTML string with
*/
- public function select_resource_list($selected = 0, $htmlname = 'fk_resource', array $filter = [], $showempty = 0, $showtype = 0, $forcecombo = 0, $event = [], $filterkey = '', $outputmode = 0, $limit = 20, $morecss = '', $multiple = false)
+ public function select_resource_list($selected = 0, $htmlname = 'fk_resource', array $filter = [], $showempty = 0, $showtype = 0, $forcecombo = 0, $event = [], $filterkey = [], $outputmode = 0, $limit = 20, $morecss = '', $multiple = false)
{
// phpcs:enable
global $conf, $user, $langs;
diff --git a/test/phpunit/CodingPhpTest.php b/test/phpunit/CodingPhpTest.php
index 7e134b07bbb..5dd8a43257a 100644
--- a/test/phpunit/CodingPhpTest.php
+++ b/test/phpunit/CodingPhpTest.php
@@ -131,14 +131,20 @@ class CodingPhpTest extends CommonClassTest
//print 'Check php file '.$file['relativename']."\n";
$filecontent = file_get_contents($file['fullname']);
- $this->verifyIsModuleEnabledOk($filecontent, "htdocs/{$file['relativename']}");
+ // We are not interested in the comments
+ $filecontent = $this->removePhpComments(file_get_contents($file['fullname']));
+
+ // File path for reports
+ $report_filepath = "htdocs/{$file['relativename']}";
+
+ $this->verifyIsModuleEnabledOk($filecontent, $report_filepath);
if (preg_match('/\.class\.php/', $file['relativename'])
|| preg_match('/boxes\/box_/', $file['relativename'])
|| preg_match('/modules\/.*\/doc\/(doc|pdf)_/', $file['relativename'])
|| preg_match('/modules\/(import|mailings|printing)\//', $file['relativename'])
|| in_array($file['name'], array('modules_boxes.php', 'TraceableDB.php'))) {
- // Check into Class files
+ // Check Class files
if (! in_array($file['name'], array(
'api.class.php',
'commonobject.class.php',
@@ -152,18 +158,18 @@ class CodingPhpTest extends CommonClassTest
// Must not find $db->
$ok = true;
$matches = array();
- // Check string $db-> inside a class.php file (it should be $this->db-> into such classes)
+ // Check string $db-> inside a class.php file (it should be $this->db-> in such classes)
preg_match_all('/'.preg_quote('$db->', '/').'/', $filecontent, $matches, PREG_SET_ORDER);
foreach ($matches as $key => $val) {
$ok = false;
break;
}
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
- $this->assertTrue($ok, 'Found string $db-> into a .class.php file in '.$file['relativename'].'. Inside a .class file, you should use $this->db-> instead.');
+ $this->assertTrue($ok, 'Found string $db-> in a .class.php file in '.$file['relativename'].'. Inside a .class file, you should use $this->db-> instead.');
//exit;
}
- if (preg_match('/\.class\.php/', $file['relativename']) && ! in_array($file['relativename'], array(
+ if (preg_match('/\.class\.php$/', $file['relativename']) && ! in_array($file['relativename'], array(
'adherents/canvas/actions_adherentcard_common.class.php',
'contact/canvas/actions_contactcard_common.class.php',
'compta/facture/class/facture.class.php',
@@ -191,7 +197,7 @@ class CodingPhpTest extends CommonClassTest
// Must not find GETPOST
$ok = true;
$matches = array();
- // Check string GETPOSTFLOAT a class.php file (should not be found into classes)
+ // Check string GETPOSTFLOAT a class.php file (should not be found in classes)
preg_match_all('/GETPOST\(["\'](....)/', $filecontent, $matches, PREG_SET_ORDER);
foreach ($matches as $key => $val) {
if (in_array($val[1], array('lang', 'forc', 'mass', 'conf'))) {
@@ -201,11 +207,10 @@ class CodingPhpTest extends CommonClassTest
$ok = false;
break;
}
- //print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
- $this->assertTrue($ok, 'Found string GETPOST into a .class.php file in '.$file['relativename'].'.');
+ $this->assertTrue($ok, 'Found string GETPOST in a .class.php file in '.$file['relativename'].'.');
}
} else {
- // Check into Include files
+ // Check Include files
if (! in_array($file['name'], array(
'objectline_view.tpl.php',
'extrafieldsinexport.inc.php',
@@ -216,7 +221,7 @@ class CodingPhpTest extends CommonClassTest
// Must not found $this->db->
$ok = true;
$matches = array();
- // Check string $this->db-> into a non class.php file (it should be $db-> into such classes)
+ // Check string $this->db-> in a non class.php file (it should be $db-> in such classes)
preg_match_all('/'.preg_quote('$this->db->', '/').'/', $filecontent, $matches, PREG_SET_ORDER);
foreach ($matches as $key => $val) {
$ok = false;
@@ -228,9 +233,9 @@ class CodingPhpTest extends CommonClassTest
}
}
- // Check we don't miss top_httphead() into any ajax pages
+ // Check we don't miss top_httphead() in any ajax pages
if (preg_match('/ajax\//', $file['relativename'])) {
- print "Analyze ajax page ".$file['relativename']."\n";
+ //print "Analyze ajax page ".$file['relativename']."\n";
$ok = true;
$matches = array();
preg_match_all('/top_httphead/', $filecontent, $matches, PREG_SET_ORDER);
@@ -238,28 +243,13 @@ class CodingPhpTest extends CommonClassTest
$ok = false;
}
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
- $this->assertTrue($ok, 'Did not find top_httphead into the ajax page '.$file['relativename']);
+ $this->assertTrue($ok, 'Did not find top_httphead in the ajax page '.$file['relativename']);
//exit;
}
- // Check if a var_dump has been forgotten
+ // Check for unauthorised vardumps
if (!preg_match('/test\/phpunit/', $file['fullname'])) {
- if (! in_array($file['name'], array('class.nusoap_base.php'))) {
- $ok = true;
- $matches = array();
- preg_match_all('/(.)\s*var_dump\(/', $filecontent, $matches, PREG_SET_ORDER);
- //var_dump($matches);
- foreach ($matches as $key => $val) {
- if ($val[1] != '/' && $val[1] != '*') {
- $ok = false;
- break;
- }
- break;
- }
- //print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
- $this->assertTrue($ok, 'Found string var_dump that is not just after /* or // in '.$file['relativename']);
- //exit;
- }
+ $this->verifyNoActiveVardump($filecontent, $report_filepath);
}
// Check get_class followed by __METHOD__
@@ -311,7 +301,7 @@ class CodingPhpTest extends CommonClassTest
break;
}
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
- $this->assertTrue($ok, 'Found non quoted or not casted var into sql request '.$file['relativename'].' - Bad.');
+ $this->assertTrue($ok, 'Found non quoted or not casted var in sql request '.$file['relativename'].' - Bad.');
//exit;
// Check that forged sql string is using ' instead of " as string PHP quotes
@@ -327,7 +317,7 @@ class CodingPhpTest extends CommonClassTest
//if ($reg[0] != 'db') $ok=false;
}
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
- $this->assertTrue($ok, 'Found a forged SQL string that mix on same line the use of \' for PHP string and PHP variables into file '.$file['relativename'].' Use " to forge PHP string like this: $sql = "SELECT ".$myvar...');
+ $this->assertTrue($ok, 'Found a forged SQL string that mix on same line the use of \' for PHP string and PHP variables in file '.$file['relativename'].' Use " to forge PHP string like this: $sql = "SELECT ".$myvar...');
//exit;
// Check that forged sql string is using ' instead of " as string PHP quotes
@@ -339,7 +329,7 @@ class CodingPhpTest extends CommonClassTest
$ok = false;
break;
}
- $this->assertTrue($ok, 'Found a forged SQL string that mix on same line the use of \' for PHP string and PHP variables into file '.$file['relativename'].' Use " to forge PHP string like this: $sql = "SELECT ".$myvar...');
+ $this->assertTrue($ok, 'Found a forged SQL string that mix on same line the use of \' for PHP string and PHP variables in file '.$file['relativename'].' Use " to forge PHP string like this: $sql = "SELECT ".$myvar...');
// Check sql string VALUES ... , ".$xxx
// with xxx that is not 'db-' (for $db->escape). It means we forget a ' if string, or an (int) if int, when forging sql request.
@@ -358,7 +348,7 @@ class CodingPhpTest extends CommonClassTest
break;
}
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
- $this->assertTrue($ok, 'Found non quoted or not casted var into sql request '.$file['relativename'].' - Bad.');
+ $this->assertTrue($ok, 'Found non quoted or not casted var in sql request '.$file['relativename'].' - Bad.');
//exit;
// Check '".$xxx non escaped
@@ -514,7 +504,7 @@ class CodingPhpTest extends CommonClassTest
break;
}
}
- $this->assertTrue($ok, 'Found a forbidden string sequence into '.$file['relativename'].' : name="token" value="\'.$_SESSION[..., you must use a newToken() instead of $_SESSION[\'newtoken\'].');
+ $this->assertTrue($ok, 'Found a forbidden string sequence in '.$file['relativename'].' : name="token" value="\'.$_SESSION[..., you must use a newToken() instead of $_SESSION[\'newtoken\'].');
// Test we don't have preg_grep with a param without preg_quote
@@ -589,10 +579,93 @@ class CodingPhpTest extends CommonClassTest
$ok = false;
break;
}
- $this->assertTrue($ok, 'Found a CURDATE\(\) into code. Do not use this SQL method in file '.$file['relativename'].'. You must use the PHP function dol_now() instead.');
+ $this->assertTrue($ok, 'Found a CURDATE\(\) in code. Do not use this SQL method in file '.$file['relativename'].'. You must use the PHP function dol_now() instead.');
}
+ /**
+ * Verify that no active var_dump was left over in the code
+ *
+ * @param string $filecontent Contents to check for php code that uses a module name
+ * @param string $filename File name for the contents (used for reporting)
+ *
+ * @return void
+ */
+ private function verifyNoActiveVardump(&$filecontent, $filename)
+ {
+ $ok = true;
+ $matches = array();
+ // Match!:
+ // - Line-start, whitespace, var_dump
+ // - Line-start, no-comment-leader, var_dump
+ // no-commen-leader=
+ // - Any character not / or *
+ // - Any / not preceded with / and not followed by / or *
+ // - Any * not preceded with /
+ preg_match_all('{^(?:^|^(?:[ \t]*|(?:(?:[^*/]|(? $val) {
+ if (!isset($val[1]) || $val[1] != '/' && $val[1] != '*') {
+ $ok = false;
+ $failing_string = $val[0];
+ break;
+ }
+ }
+ $this->assertTrue($ok, "Found string var_dump that is not just after /* or // in '$filename': $failing_string");
+ }
+
+
+ /**
+ * Provide test data for testing the method detecting var_dump presence.
+ *
+ * @return array Test sets
+ */
+ public function vardumpTesterProvider()
+ {
+ return [
+ 'var_dump at start of file' => ["var_dump(\$help)\n", true],
+ 'var_dump at start of line' => ["\nvar_dump(\$help)\n", true],
+ 'var_dump after comment next line' => ["/* Hello */\nvar_dump(\$help)\n", true],
+ 'var_dump with space' => [" var_dump(\$help)\n", true],
+ 'var_dump after comment' => [" // var_dump(\$help)\n", false],
+ '2 var_dumps after comment' => [" // var_dump(\$help); var_dump(\$help)\n", false],
+ 'var_dump before and after comment' => [" var_dump(\$help); // var_dump(\$help)\n", true],
+ ];
+ }
+
+ /**
+ * Test that verifyNoActiveVardump generates a notification
+ *
+ * @param string $filecontent Fake file content
+ * @param bool $hasVardump When true, expect var_dump detection
+ *
+ * @return void
+ *
+ * @dataProvider vardumpTesterProvider
+ */
+ public function testVerifyNoActiveVardump(&$filecontent, $hasVardump)
+ {
+ $this->nbLinesToShow = 1;
+ // Create some dummy file content
+ $filename = $this->getName(false);
+
+ $notification = false;
+ ob_start(); // Do not disturb the output with tests that are meant to fail.
+ try {
+ $this->verifyNoActiveVardump($filecontent, $filename);
+ } catch (Throwable $e) {
+ $notification = (string) $e;
+ }
+ $output = ob_get_clean();
+
+ // Assert that a notification was generated
+ if ($hasVardump) {
+ $this->assertStringContainsString("Found string var_dump", $notification ?? '', "Expected notification not found.");
+ } else {
+ $this->assertFalse($notification, "Unexpection detection of var_dump");
+ }
+ }
+
/**
* Verify that only known modules are used
*
@@ -635,4 +708,72 @@ class CodingPhpTest extends CommonClassTest
);
}
}
+
+
+ /**
+ * Remove php comments from source string
+ *
+ * @param string $string The string from which the PHP comments are removed
+ *
+ * @return string The string without the comments
+ */
+ private function removePhpComments($string)
+ {
+ return preg_replace_callback(
+ '{(//.*?$)|(/\*.*?\*/)}ms',
+ static function ($match) {
+ if (isset($match[2])) {
+ // Count the number of newline characters in the comment
+ $num_newlines = substr_count($match[0], "\n");
+ // Generate whitespace equivalent to the number of newlines
+ if ($num_newlines == 0) {
+ // /* Comment on single line -> space
+ return " ";
+ } else {
+ // /* Comment on multiple lines -> new lines
+ return str_repeat("\n", $num_newlines);
+ }
+ } else {
+ // Double slash comment, just remove
+ return "";
+ }
+ },
+ $string
+ );
+ }
+
+ /**
+ * Provide test data for testing the comments remover
+ *
+ * @return array Test sets
+ */
+ public function commentRemovalTestProvider()
+ {
+ return [
+ 'complete line 1' => ["/*Comment complete line*/", " "],
+ 'complete line 2' => ["// Comment complete line", ""],
+ 'partial line 1' => ["a/*Comment complete line*/b", "a b"],
+ 'partial line 2' => ["a// Comment complete line", "a"],
+ 'multi line full 1' => ["/*Comment\ncomplete line*/", "\n"],
+ 'multi line full 2' => ["/*Comment\ncomplete line*/\n", "\n\n"],
+ 'multi line partials 1' => ["a/*Comment\ncomplete line*/b", "a\nb"],
+ ];
+ }
+
+ /**
+ * Test that comments are properly removed
+ *
+ * @param string $source Fake file content
+ * @param bool $expected When true, expect var_dump detection
+ *
+ * @return void
+ *
+ * @dataProvider commentRemovalTestProvider
+ */
+ public function testRemovePhpComments(&$source, &$expected)
+ {
+ $this->nbLinesToShow = 0;
+
+ $this->assertEquals($expected, $this->removePhpComments($source), "Comments not removed as expected");
+ }
}