diff --git a/SECURITY.md b/SECURITY.md index aacbeb1faf9..41c0fd43de1 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -5,7 +5,7 @@ This file contains some policies about the security reports on Dolibarr ERP CRM ## Supported Versions for security reports -Security report are valid only on current stable version (see https://dolibarr.org web site to get current stable version) or on development version (branch "develop" on https://github.com/Dolibarr/dolibarr). +Security report are valid only on any current stable version for the last 5 major versions (see https://dolibarr.org web site to get current stable version) or on development version (branch "develop" on https://github.com/Dolibarr/dolibarr). ## Reporting a Vulnerability diff --git a/dev/build/phpstan/phpstan-baseline.neon b/dev/build/phpstan/phpstan-baseline.neon index 8b5d79a5e40..a7729ec1878 100644 --- a/dev/build/phpstan/phpstan-baseline.neon +++ b/dev/build/phpstan/phpstan-baseline.neon @@ -1038,18 +1038,6 @@ parameters: count: 1 path: ../../../htdocs/admin/website.php - - - message: '#^Parameter \#1 \$array of function dol_sort_array contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: ../../../htdocs/admin/workflow.php - - - - message: '#^Return type of call to function dol_sort_array contains unresolvable type\.$#' - identifier: function.unresolvableReturnType - count: 1 - path: ../../../htdocs/admin/workflow.php - - message: '#^Loose comparison using \=\= between ''edit'' and ''edit'' will always evaluate to true\.$#' identifier: equal.alwaysTrue @@ -1590,30 +1578,6 @@ parameters: count: 1 path: ../../../htdocs/categories/categorie_list.php - - - message: '#^Method Categorie\:\:get_full_arbo\(\) should return \-1\|array\ but returns array\\.$#' - identifier: return.type - count: 1 - path: ../../../htdocs/categories/class/categorie.class.php - - - - message: '#^Parameter \#1 \$array of function dol_sort_array contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: ../../../htdocs/categories/class/categorie.class.php - - - - message: '#^Property Categorie\:\:\$cats \(array\\) does not accept array\\.$#' - identifier: assign.propertyType - count: 2 - path: ../../../htdocs/categories/class/categorie.class.php - - - - message: '#^Return type of call to function dol_sort_array contains unresolvable type\.$#' - identifier: function.unresolvableReturnType - count: 1 - path: ../../../htdocs/categories/class/categorie.class.php - - message: '#^If condition is always true\.$#' identifier: if.alwaysTrue @@ -5646,12 +5610,6 @@ parameters: count: 2 path: ../../../htdocs/core/class/html.form.class.php - - - message: '#^Parameter \#1 \$array of function dol_sort_array contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 3 - path: ../../../htdocs/core/class/html.form.class.php - - message: '#^Parameter \#15 \$excludeids of method Form\:\:select_company\(\) expects array\, array\ given\.$#' identifier: argument.type @@ -5676,54 +5634,6 @@ parameters: count: 1 path: ../../../htdocs/core/class/html.form.class.php - - - message: '#^Property Form\:\:\$cache_conditions_paiements has no type specified\.$#' - identifier: missingType.property - count: 1 - path: ../../../htdocs/core/class/html.form.class.php - - - - message: '#^Property Form\:\:\$cache_demand_reason has no type specified\.$#' - identifier: missingType.property - count: 1 - path: ../../../htdocs/core/class/html.form.class.php - - - - message: '#^Property Form\:\:\$cache_invoice_subtype has no type specified\.$#' - identifier: missingType.property - count: 1 - path: ../../../htdocs/core/class/html.form.class.php - - - - message: '#^Property Form\:\:\$cache_transport_mode has no type specified\.$#' - identifier: missingType.property - count: 1 - path: ../../../htdocs/core/class/html.form.class.php - - - - message: '#^Property Form\:\:\$cache_types_fees has no type specified\.$#' - identifier: missingType.property - count: 1 - path: ../../../htdocs/core/class/html.form.class.php - - - - message: '#^Property Form\:\:\$cache_types_paiements has no type specified\.$#' - identifier: missingType.property - count: 1 - path: ../../../htdocs/core/class/html.form.class.php - - - - message: '#^Property Form\:\:\$cache_vatrates has no type specified\.$#' - identifier: missingType.property - count: 1 - path: ../../../htdocs/core/class/html.form.class.php - - - - message: '#^Return type of call to function dol_sort_array contains unresolvable type\.$#' - identifier: function.unresolvableReturnType - count: 3 - path: ../../../htdocs/core/class/html.form.class.php - - message: '#^Right side of && is always true\.$#' identifier: booleanAnd.rightAlwaysTrue @@ -5760,24 +5670,12 @@ parameters: count: 1 path: ../../../htdocs/core/class/html.formcompany.class.php - - - message: '#^Parameter \#1 \$array of function dol_sort_array contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: ../../../htdocs/core/class/html.formcompany.class.php - - message: '#^Parameter \#3 \$selected of method Form\:\:multiselectarray\(\) expects array\, array\\|int\> given\.$#' identifier: argument.type count: 1 path: ../../../htdocs/core/class/html.formcompany.class.php - - - message: '#^Return type of call to function dol_sort_array contains unresolvable type\.$#' - identifier: function.unresolvableReturnType - count: 1 - path: ../../../htdocs/core/class/html.formcompany.class.php - - message: '#^Variable \$idprof might not be defined\.$#' identifier: variable.undefined @@ -10794,18 +10692,6 @@ parameters: count: 1 path: ../../../htdocs/main.inc.php - - - message: '#^Parameter \#1 \$array of function dol_sort_array contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: ../../../htdocs/margin/agentMargins.php - - - - message: '#^Return type of call to function dol_sort_array contains unresolvable type\.$#' - identifier: function.unresolvableReturnType - count: 1 - path: ../../../htdocs/margin/agentMargins.php - - message: '#^Ternary operator condition is always false\.$#' identifier: ternary.alwaysFalse @@ -14064,18 +13950,6 @@ parameters: count: 1 path: ../../../htdocs/reception/card.php - - - message: '#^Loose comparison using \=\= between ''''\|''CommandeFournisseur'' and ''commande'' will always evaluate to false\.$#' - identifier: equal.alwaysFalse - count: 2 - path: ../../../htdocs/reception/card.php - - - - message: '#^Loose comparison using \=\= between ''''\|''CommandeFournisseur'' and ''propal'' will always evaluate to false\.$#' - identifier: equal.alwaysFalse - count: 2 - path: ../../../htdocs/reception/card.php - - message: '#^Negated boolean expression is always true\.$#' identifier: booleanNot.alwaysTrue @@ -14088,12 +13962,6 @@ parameters: count: 1 path: ../../../htdocs/reception/card.php - - - message: '#^Result of && is always false\.$#' - identifier: booleanAnd.alwaysFalse - count: 8 - path: ../../../htdocs/reception/card.php - - message: '#^Variable \$extrafields in empty\(\) always exists and is not falsy\.$#' identifier: empty.variable @@ -14244,24 +14112,6 @@ parameters: count: 2 path: ../../../htdocs/reception/contact.php - - - message: '#^Loose comparison using \=\= between ''''\|''CommandeFournisseur'' and ''commande'' will always evaluate to false\.$#' - identifier: equal.alwaysFalse - count: 1 - path: ../../../htdocs/reception/dispatch.php - - - - message: '#^Loose comparison using \=\= between ''''\|''CommandeFournisseur'' and ''propal'' will always evaluate to false\.$#' - identifier: equal.alwaysFalse - count: 1 - path: ../../../htdocs/reception/dispatch.php - - - - message: '#^Result of && is always false\.$#' - identifier: booleanAnd.alwaysFalse - count: 4 - path: ../../../htdocs/reception/dispatch.php - - message: '#^Variable \$objectsrc might not be defined\.$#' identifier: variable.undefined @@ -15666,12 +15516,6 @@ parameters: count: 3 path: ../../../htdocs/user/class/user.class.php - - - message: '#^Parameter \#1 \$array of function dol_sort_array contains unresolvable type\.$#' - identifier: argument.unresolvableType - count: 1 - path: ../../../htdocs/user/class/user.class.php - - message: '#^Property User\:\:\$rights \(stdClass\) in empty\(\) is not falsy\.$#' identifier: empty.property @@ -15726,12 +15570,6 @@ parameters: count: 4 path: ../../../htdocs/user/class/user.class.php - - - message: '#^Return type of call to function dol_sort_array contains unresolvable type\.$#' - identifier: function.unresolvableReturnType - count: 1 - path: ../../../htdocs/user/class/user.class.php - - message: '#^Variable \$whereforadd in empty\(\) always exists and is not falsy\.$#' identifier: empty.variable @@ -16116,12 +15954,6 @@ parameters: count: 1 path: ../../../htdocs/webhook/triggerhistory_list.php - - - message: '#^Loose comparison using \=\= between ''auto'' and ''auto'' will always evaluate to true\.$#' - identifier: equal.alwaysTrue - count: 1 - path: ../../../htdocs/webportal/class/context.class.php - - message: '#^Result of && is always false\.$#' identifier: booleanAnd.alwaysFalse @@ -16134,24 +15966,6 @@ parameters: count: 1 path: ../../../htdocs/webportal/class/html.formcardwebportal.class.php - - - message: '#^Comparison operation "\<\=" between int\<2, max\> and 1 is always false\.$#' - identifier: smallerOrEqual.alwaysFalse - count: 1 - path: ../../../htdocs/webportal/class/html.formlistwebportal.class.php - - - - message: '#^Offset ''total'' on \*NEVER\* in isset\(\) always exists and is not nullable\.$#' - identifier: isset.offset - count: 1 - path: ../../../htdocs/webportal/class/html.formlistwebportal.class.php - - - - message: '#^Result of && is always false\.$#' - identifier: booleanAnd.alwaysFalse - count: 1 - path: ../../../htdocs/webportal/class/html.formlistwebportal.class.php - - message: '#^Call to function is_array\(\) with list\ will always evaluate to true\.$#' identifier: function.alreadyNarrowedType diff --git a/dev/tools/php-cs-fixer/.php-cs-fixer.dist.php b/dev/tools/php-cs-fixer/.php-cs-fixer.dist.php index 5b97cfb88be..e5345d9d723 100644 --- a/dev/tools/php-cs-fixer/.php-cs-fixer.dist.php +++ b/dev/tools/php-cs-fixer/.php-cs-fixer.dist.php @@ -1,20 +1,22 @@ + */ /* PHP 7.0 */ $finder = (new PhpCsFixer\Finder()) -->in(__DIR__) -->exclude([ - 'core/includes', - 'custom', - 'documents', - 'doctemplates', - 'vendor', - 'install/doctemplates', - 'htdocs/custom', - 'htdocs/includes', - 'htdocs/install/doctemplates', -]) -->notPath('vendor'); + ->in(__DIR__) + ->exclude([ + 'core/includes', + 'custom', + 'documents', + 'doctemplates', + 'vendor', + 'install/doctemplates', + 'htdocs/custom', + 'htdocs/includes', + 'htdocs/install/doctemplates', + ]) + ->notPath('vendor'); /* PHP 7.4+ */ @@ -43,8 +45,11 @@ return (new PhpCsFixer\Config()) // So we use target PHP70 for the moment. '@PHP70Migration' => true, //'@PHP71Migration' => true, - // Avoid adding public to const (incompatible with PHP 7.0): - 'visibility_required' => ['elements'=>['property', 'method']], + // Avoid adding public to const (incompatible with PHP 7.0): + 'visibility_required' => ['elements' => ['property', 'method']], + // Replace deprecated 'visibility_required' + 'modifier_keywords' => ['elements' => ['property', 'method']], + //'strict_param' => true, //'array_syntax' => ['syntax' => 'short'], @@ -59,5 +64,4 @@ return (new PhpCsFixer\Config()) ->setIndent("\t") // All files MUST use the Unix LF line ending only // https://www.php-fig.org/psr/psr-12/#22-files - ->setLineEnding("\n") -; + ->setLineEnding("\n"); diff --git a/dev/translation/ignore_translation_keys.lst b/dev/translation/ignore_translation_keys.lst index b4f1071bc6a..f1f33bb9f1c 100644 --- a/dev/translation/ignore_translation_keys.lst +++ b/dev/translation/ignore_translation_keys.lst @@ -145,8 +145,6 @@ Barcode BarcodeDesc BarcodeStickersMask BillOfMaterialsLine -BlockLogNeedAmountsValue -BlockLogNeedElement BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote BlockedLogAuthorityUrl BlockedLogSetup diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index d7fb7d2a3fd..2832520875f 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -851,7 +851,7 @@ if ($action == 'create') { print ''; print '' . $langs->trans("DateExport") . ''; print ''; - print $object->date_export ? img_picto($langs->trans("TransactionExportDesc"), 'fa-file-export', 'class="pictofixedwidth"').dol_print_date($object->date_export, 'dayhour') : ' '; + print $object->date_export ? img_picto($langs->trans("TransactionExportDesc"), 'fa-file-export', 'class="pictofixedwidth opacitymedium"').dol_print_date($object->date_export, 'dayhour') : ' '; print ''; print ''; @@ -859,7 +859,7 @@ if ($action == 'create') { print ''; print '' . $langs->trans("DateValidation") . ''; print ''; - print $object->date_validation ? img_picto($langs->trans("TransactionBlockedLockedDesc"), 'fa-lock', 'class="pictofixedwidth"').dol_print_date($object->date_validation, 'dayhour') : ' '; + print $object->date_validation ? img_picto($langs->trans("TransactionBlockedLockedDesc"), 'fa-lock', 'class="pictofixedwidth opacitymedium"').dol_print_date($object->date_validation, 'dayhour') : ' '; print ''; print ''; diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 93e89ca5abf..1eb4791d61d 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -1272,6 +1272,12 @@ while ($i < min($num, $limit)) { $object->piece_num = $line->piece_num; $object->ref = $line->ref; print $object->getNomUrl(1, '', 0, '', 1); + if (!empty($line->date_export)) { + print img_picto($langs->trans("DateExport").": ".dol_print_date($line->date_export, 'dayhour')." (".$langs->trans("TransactionExportDesc").")", 'fa-file-export', 'class="paddingleft pictofixedwidth opacitymedium"'); + } + if (!empty($line->date_validation)) { + print img_picto($langs->trans("DateValidation").": ".dol_print_date($line->date_validation, 'dayhour')." (".$langs->trans("TransactionBlockedLockedDesc").")", 'fa-lock', 'class="paddingleft pictofixedwidth opacitymedium"'); + } print ''; if (!$i) { $totalarray['nbfield']++; diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 9de49b6aa8c..c55f773781d 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -1421,10 +1421,10 @@ while ($i < min($num, $limit)) { $object->ref = $line->ref; print $object->getNomUrl(1, '', 0, '', 1); if (!empty($line->date_export)) { - print img_picto($langs->trans("DateExport").": ".dol_print_date($line->date_export, 'dayhour')." (".$langs->trans("TransactionExportDesc").")", 'fa-file-export', 'class="paddingleft pictofixedwidth"'); + print img_picto($langs->trans("DateExport").": ".dol_print_date($line->date_export, 'dayhour')." (".$langs->trans("TransactionExportDesc").")", 'fa-file-export', 'class="paddingleft pictofixedwidth opacitymedium"'); } if (!empty($line->date_validation)) { - print img_picto($langs->trans("DateValidation").": ".dol_print_date($line->date_validation, 'dayhour')." (".$langs->trans("TransactionBlockedLockedDesc").")", 'fa-lock', 'class="paddingleft pictofixedwidth"'); + print img_picto($langs->trans("DateValidation").": ".dol_print_date($line->date_validation, 'dayhour')." (".$langs->trans("TransactionBlockedLockedDesc").")", 'fa-lock', 'class="paddingleft pictofixedwidth opacitymedium"'); } print ''; if (!$i) { diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index 832d883305b..9e038d67a49 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -524,9 +524,6 @@ if (empty($reshook)) { } // Rename some POST variables into a generic name - if ($field == 'fk_user' && !(GETPOSTINT('fk_user') > 0)) { - $_POST['fk_user'] = ''; - } if ($field == 'topic') { $_POST['topic'] = GETPOST('topic-'.$rowid); } @@ -548,7 +545,7 @@ if (empty($reshook)) { } $sql .= $field."="; - if (GETPOST($keycode) == '' || (!in_array($keycode, array('langcode', 'position', 'private', 'defaultfortype')) && !GETPOST($keycode))) { + if ((GETPOST($keycode) == '' && in_array($keycode, array('langcode'))) || (!in_array($keycode, array('langcode', 'position', 'private', 'defaultfortype')) && !GETPOST($keycode))) { $sql .= "null"; // langcode,... must be '' if not defined so the unique key that include lang will work } elseif (GETPOST($keycode) == '0' && $keycode == 'langcode') { $sql .= "''"; // langcode must be '' if not defined so the unique key that include lang will work @@ -560,7 +557,9 @@ if (empty($reshook)) { } } elseif ($keycode == 'content') { $sql .= "'".$db->escape(GETPOST($keycode, 'restricthtml'))."'"; - } elseif (in_array($keycode, array('joinfiles', 'defaultfortype', 'private', 'position'))) { + } elseif ($keycode == 'position') { + $sql .= (GETPOSTINT($keycode) > 0 ? GETPOSTINT($keycode) : 1); + } elseif (in_array($keycode, array('joinfiles', 'defaultfortype', 'private'))) { $sql .= GETPOSTINT($keycode); } else { $sql .= "'".$db->escape(GETPOST($keycode, 'alphanohtml'))."'"; @@ -572,10 +571,10 @@ if (empty($reshook)) { if (!$user->admin) { // A non admin user can only edit its own template $sql .= " AND fk_user = ".((int) $user->id); } - //print $sql;exit; + dol_syslog("actionmodify", LOG_DEBUG); - //print $sql; + //print $sql; exit; $resql = $db->query($sql); if (!$resql) { $error++; @@ -731,7 +730,6 @@ $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $param .= $hookmanager->resPrint; -$linkback = ''; $titlepicto = 'title_setup'; @@ -1164,7 +1162,8 @@ if ($num) { if ($obj) { if (($action == 'edit' || $action == 'preview') && ($rowid == (!empty($obj->rowid) ? $obj->rowid : $obj->code))) { - print ''; + // TODO Move this 2 lines into a popup + print ''; $tmpaction = 'edit'; if ($action == 'edit') { @@ -1180,16 +1179,6 @@ if ($num) { $colspan = 0; - print ''; - print ''; - print ''; - print '
'; - if ($action == 'edit') { - print ''; - } - print ''; - print ''; - // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; @@ -1203,20 +1192,16 @@ if ($num) { // Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; - print ''; - print ''; - if ($action == 'edit') { - print ''; - } - print '
'; - print ''; print ''; $colspan++; } print "\n"; print ''; - print ''; + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } + print ''; $fieldsforcontent = array('topic', 'email_from','joinfiles', 'content'); if (getDolGlobalString('MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES')) { @@ -1259,7 +1244,7 @@ if ($num) { if (!getDolGlobalString('FCKEDITOR_ENABLE_MAIL')) { $okforextended = false; } - $doleditor = new DolEditor($tmpfieldlist.'-'.$rowid, (!empty($obj->{$tmpfieldlist}) ? $obj->{$tmpfieldlist} : ''), '', 500, 'dolibarr_mailings', 'In', false, $acceptlocallinktomedia, $okforextended, ROWS_6, '90%', ($action != 'edit' ? 1 : 0)); + $doleditor = new DolEditor($tmpfieldlist.'-'.$rowid, (!empty($obj->{$tmpfieldlist}) ? $obj->{$tmpfieldlist} : ''), '', 450, 'dolibarr_mailings', 'In', false, $acceptlocallinktomedia, $okforextended, ROWS_6, '80%', ($action != 'edit' ? 1 : 0)); print $doleditor->Create(1); } if ($tmpfieldlist == 'content_lines') { @@ -1269,16 +1254,27 @@ if ($num) { if (!getDolGlobalString('FCKEDITOR_ENABLE_MAIL')) { $okforextended = false; } - $doleditor = new DolEditor($tmpfieldlist.'-'.$rowid, (!empty($obj->{$tmpfieldlist}) ? $obj->{$tmpfieldlist} : ''), '', 140, 'dolibarr_mailings', 'In', false, $acceptlocallinktomedia, $okforextended, ROWS_6, '90%'); + $doleditor = new DolEditor($tmpfieldlist.'-'.$rowid, (!empty($obj->{$tmpfieldlist}) ? $obj->{$tmpfieldlist} : ''), '', 140, 'dolibarr_mailings', 'In', false, $acceptlocallinktomedia, $okforextended, ROWS_6, '80%'); print $doleditor->Create(1); } print ''; } } print ''; + print '
'; + print ''; + if ($action == 'edit') { + print ''; + } + print ''; + print '
'; print ''; - print "\n"; + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } + + print ''; $nbqualified++; } else { @@ -1509,7 +1505,7 @@ function fieldList($fieldlist, $obj = null, $tabname = '', $context = '') } elseif ($value == 'fk_user') { print ''; if ($user->admin && $context != 'preview') { - print $form->select_dolusers(GETPOSTISSET('fk_user') ? GETPOSTINT('fk_user') : (empty($obj->$value) ? '' : $obj->$value), 'fk_user', 1, array(), 0, ($user->admin ? '' : 'hierarchyme'), array(), '0', 0, 0, '', 0, '', 'minwidth75 maxwidth100'); + print $form->select_dolusers(GETPOSTISSET('fk_user') ? GETPOSTINT('fk_user') : (empty($obj->$value) ? '' : $obj->$value), 'fk_user', $langs->trans("Owner"), array(), 0, ($user->admin ? '' : 'hierarchyme'), array(), '0', 0, 0, '', 0, '', 'minwidth75 maxwidth100'); } else { if ($context == 'add') { // I am not admin and we show the add form print $user->getNomUrl(-1); // Me @@ -1536,7 +1532,7 @@ function fieldList($fieldlist, $obj = null, $tabname = '', $context = '') if ($context == 'edit') { $selectedlang = $obj->lang; } - print $formadmin->select_language($selectedlang, 'langcode', 0, array(), 1, 0, 0, 'maxwidth100'); + print $formadmin->select_language($selectedlang, 'langcode', 0, array(), $langs->trans("Language"), 0, 0, 'maxwidth100'); } else { if (!empty($obj->lang)) { print $obj->lang.' - '.$langs->trans('Language_'.$obj->lang); diff --git a/htdocs/admin/syslog.php b/htdocs/admin/syslog.php index 7e8d7da76d4..24ec3b36b15 100644 --- a/htdocs/admin/syslog.php +++ b/htdocs/admin/syslog.php @@ -28,8 +28,6 @@ // Load Dolibarr environment require '../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; - /** * @var Conf $conf * @var DoliDB $db @@ -37,6 +35,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; * @var Translate $langs * @var User $user */ +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; if (!$user->admin) { accessforbidden(); @@ -332,7 +331,7 @@ print ''; if (!empty($conf->loghandlers['mod_syslog_file']) && isModEnabled('cron')) { print ''.$langs->trans("SyslogFileNumberOfSaves").''; print ''; - print '   ('.$langs->trans('ConfigureCleaningCronjobToSetFrequencyOfSaves').')'; + print '   '.$langs->trans('ConfigureCleaningCronjobToSetFrequencyOfSaves').''; } print ''; diff --git a/htdocs/admin/workflow.php b/htdocs/admin/workflow.php index 0c568e70c99..76c38f94ff4 100644 --- a/htdocs/admin/workflow.php +++ b/htdocs/admin/workflow.php @@ -3,7 +3,7 @@ * Copyright (C) 2004 Eric Seigne * Copyright (C) 2005-2021 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin - * 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 @@ -65,9 +65,11 @@ if (preg_match('/del(.*)/', $action, $reg)) { } } + // List of workflow we can enable clearstatcache(); +/** @var array,reloadpage?:int<0,1>}> $workflowcodes */ $workflowcodes = array( // Automatic creation 'WORKFLOW_PROPAL_AUTOCREATE_ORDER' => array( @@ -227,6 +229,7 @@ $workflowcodes = array( if (!empty($conf->modules_parts['workflow']) && is_array($conf->modules_parts['workflow'])) { foreach ($conf->modules_parts['workflow'] as $workflow) { + /** @var array,reloadpage?:int<0,1>}> $workflow */ $workflowcodes = array_merge($workflowcodes, $workflow); } } diff --git a/htdocs/blockedlog/admin/blockedlog_archives.php b/htdocs/blockedlog/admin/blockedlog_archives.php index 7dc47a0fbfc..885d5cd5c4a 100644 --- a/htdocs/blockedlog/admin/blockedlog_archives.php +++ b/htdocs/blockedlog/admin/blockedlog_archives.php @@ -169,7 +169,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; -if (GETPOST('action') == 'upload' && $user->hasRight('blockedlog', 'read')) { // read is read/upload for blockedlog +if (GETPOST('action') == 'export' && $user->hasRight('blockedlog', 'read')) { // read is read/export for blockedlog $error = 0; $previoushash = ''; @@ -184,16 +184,20 @@ if (GETPOST('action') == 'upload' && $user->hasRight('blockedlog', 'read')) { / $error++; } + $dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 1); + $datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 12); + + if ($datee >= dol_now()) { + setEventMessages($langs->trans("ErrorPeriodMustBePastToAllowExport"), null, "errors"); + $error++; + } + if (!$error) { // Get the ID of the first line qualified $sql = "SELECT rowid,date_creation,tms,user_fullname,action,amounts,element,fk_object,date_object,ref_object,signature,fk_user,object_data"; $sql .= " FROM ".MAIN_DB_PREFIX."blockedlog"; $sql .= " WHERE entity = ".((int) $conf->entity); - if (GETPOSTINT('monthtoexport') > 0 || GETPOSTINT('yeartoexport') > 0) { - $dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 1); - $datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 12); - $sql .= " AND date_creation BETWEEN '".$db->idate($dates)."' AND '".$db->idate($datee)."'"; - } + $sql .= " AND date_creation BETWEEN '".$db->idate($dates)."' AND '".$db->idate($datee)."'"; $sql .= " ORDER BY rowid ASC"; // Required so we get the first one $sql .= $db->plimit(1); @@ -518,7 +522,7 @@ if ($action == 'deletefile') { print '
'; print ''; -print ''; +print ''; print '
'; diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 86141ed72bd..7c3e965e266 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -990,19 +990,29 @@ class BlockedLog // Check parameters/properties if (!isset($this->amounts)) { // amount can be 0 for some events (like when module is disabled) - $this->error = $langs->trans("BlockLogNeedAmountsValue"); + $langs->load("errors"); + $this->error = $langs->trans("ErrorBlockLogNeedAmountsValue"); dol_syslog($this->error, LOG_WARNING); return -1; } if (empty($this->element)) { - $this->error = $langs->trans("BlockLogNeedElement"); + $langs->load("errors"); + $this->error = $langs->trans("ErrorBlockLogNeedElement"); + dol_syslog($this->error, LOG_WARNING); + return -2; + } + + if (empty($this->object_data)) { + $langs->load("errors"); + $this->error = $langs->trans("ErrorBlockLogNeedObject"); dol_syslog($this->error, LOG_WARNING); return -2; } if (empty($this->action)) { - $this->error = $langs->trans("BadParameterWhenCallingCreateOfBlockedLog"); + $langs->load("errors"); + $this->error = $langs->trans("ErrorBadParameterWhenCallingCreateOfBlockedLog"); dol_syslog($this->error, LOG_WARNING); return -3; } diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index b84bacaaed0..96d846ffb62 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -1342,19 +1342,23 @@ class Categorie extends CommonObject $nbcateg = $this->db->num_rows($resql); while ($obj = $this->db->fetch_object($resql)) { - $this->cats[$obj->rowid]['rowid'] = $obj->rowid; - $this->cats[$obj->rowid]['id'] = $obj->rowid; - $this->cats[$obj->rowid]['fk_parent'] = $obj->fk_parent; - $this->cats[$obj->rowid]['label'] = !empty($obj->label_trans) ? $obj->label_trans : $obj->label; - $this->cats[$obj->rowid]['description'] = !empty($obj->description_trans) ? $obj->description_trans : $obj->description; - $this->cats[$obj->rowid]['color'] = $obj->color; - $this->cats[$obj->rowid]['position'] = $obj->position; - $this->cats[$obj->rowid]['visible'] = $obj->visible; - $this->cats[$obj->rowid]['ref_ext'] = $obj->ref_ext; - $this->cats[$obj->rowid]['picto'] = 'category'; - // fields are filled with buildPathFromId later - $this->cats[$obj->rowid]['fullpath'] = ''; - $this->cats[$obj->rowid]['fulllabel'] = ''; + $this->cats[(int) $obj->rowid] + = array( + 'rowid' => (int) $obj->rowid, + 'id' => (int) $obj->rowid, + 'fk_parent' => (int) $obj->fk_parent, + 'label' => !empty($obj->label_trans) ? (string) $obj->label_trans : (string) $obj->label, + 'description' => !empty($obj->description_trans) ? (string) $obj->description_trans : (string) $obj->description, + 'color' => (string) $obj->color, + 'position' => (string) $obj->position, + 'visible' => (int) $obj->visible, + 'ref_ext' => (string) $obj->ref_ext, + 'picto' => 'category', + // fields are filled with buildPathFromId later + 'fullpath' => '', + 'fulllabel' => '', + 'level' => null, + ); $i++; } } else { diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 8c928751d46..79b22a73e64 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -100,11 +100,6 @@ $cancel = GETPOST('cancel', 'alpha'); $backtopage = GETPOST('backtopage', 'alpha'); // if not set, a default page will be used $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); // if not set, $backtopage will be used $lineid = GETPOSTINT('lineid'); -$userid = GETPOSTINT('userid'); -$search_ref = GETPOST('sf_ref', 'alpha') ? GETPOST('sf_ref', 'alpha') : GETPOST('search_ref', 'alpha'); -$search_societe = GETPOST('search_societe', 'alpha'); -$search_montant_ht = GETPOST('search_montant_ht', 'alpha'); -$search_montant_ttc = GETPOST('search_montant_ttc', 'alpha'); $origin = GETPOST('origin', 'alpha'); $originid = (GETPOSTINT('originid') ? GETPOSTINT('originid') : GETPOSTINT('origin_id')); // For backward compatibility $fac_rec = GETPOSTINT('fac_rec'); @@ -123,8 +118,6 @@ $hideref = (GETPOSTINT('hideref') ? GETPOSTINT('hideref') : (getDolGlobalString( // Number of lines for predefined product/service choices $NBLINES = 4; -$usehm = getDolGlobalInt('MAIN_USE_HOURMIN_IN_DATE_RANGE'); - $object = new Facture($db); $extrafields = new ExtraFields($db); @@ -1274,7 +1267,7 @@ if (empty($reshook)) { $sourceinvoice = GETPOSTINT('fac_avoir'); if (!($sourceinvoice > 0) && !getDolGlobalString('INVOICE_CREDIT_NOTE_STANDALONE')) { $error++; - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CorrectInvoice")), null, 'errors'); + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("InvoiceAvoirAskCombo")), null, 'errors'); $action = 'create'; } @@ -4309,7 +4302,7 @@ if ($action == 'create') { }); '; $text = ' '; - $text .= ' 0 ? 'checked' : '').' />
"; - //print '
'; - print '
0 ? 'checked' : '').' />
"; + print '
0 ? 'checked' : '').' />
"; + print '
0 ? 'checked' : '').' />
"; + // Adding a checkbox: "Automatically consume the credit note to close the corrected invoice" is better to be into + // the confirm popup when we validate the credit note print ''; print ''."\n"; diff --git a/htdocs/core/actions_printing.inc.php b/htdocs/core/actions_printing.inc.php index 52fc3fa27d9..8c204e99039 100644 --- a/htdocs/core/actions_printing.inc.php +++ b/htdocs/core/actions_printing.inc.php @@ -1,6 +1,6 @@ - * Copyright (C) 2014-2024 Frédéric France + * Copyright (C) 2014-2025 Frédéric France * Copyright (C) 2024 MDW * * This program is free software; you can redistribute it and/or modify @@ -65,6 +65,7 @@ if ($action == 'print_file' && $user->hasRight('printing', 'read')) { $subdir = ''; $module = GETPOST('printer', 'alpha'); + // TODO make conversion in printing module switch ($module) { case 'livraison': $subdir = 'receipt'; @@ -74,7 +75,7 @@ if ($action == 'print_file' && $user->hasRight('printing', 'read')) { $subdir = 'sending'; break; case 'commande_fournisseur': - $module = 'fournisseur'; + $module = 'commande_fournisseur'; $subdir = 'commande'; break; } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 52e1f42ed13..b4f272abcec 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1000,6 +1000,7 @@ class Form $langs->load("dict"); $out = ''; + /** @var array $countryArray */ $countryArray = array(); $favorite = array(); $label = array(); @@ -1020,12 +1021,15 @@ class Form while ($i < $num) { $obj = $this->db->fetch_object($resql); - $countryArray[$i]['rowid'] = $obj->rowid; - $countryArray[$i]['code_iso'] = $obj->code_iso; - $countryArray[$i]['code_iso3'] = $obj->code_iso3; - $countryArray[$i]['label'] = ($obj->code_iso && $langs->transnoentitiesnoconv("Country" . $obj->code_iso) != "Country" . $obj->code_iso ? $langs->transnoentitiesnoconv("Country" . $obj->code_iso) : ($obj->label != '-' ? $obj->label : '')); - $countryArray[$i]['favorite'] = $obj->favorite; - $countryArray[$i]['eec'] = $obj->eec; + $countryArray[$i] + = array( + 'rowid' => (int) $obj->rowid, + 'code_iso' => (string) $obj->code_iso, + 'code_iso3' => (string) $obj->code_iso3, + 'label' => (string) ($obj->code_iso && $langs->transnoentitiesnoconv("Country" . $obj->code_iso) != "Country" . $obj->code_iso ? $langs->transnoentitiesnoconv("Country" . $obj->code_iso) : ($obj->label != '-' ? $obj->label : '')), + 'favorite' => (string) $obj->favorite, + 'eec' => (string) $obj->eec, + ); $favorite[$i] = $obj->favorite; $label[$i] = dol_string_unaccent($countryArray[$i]['label']); $i++; @@ -2107,7 +2111,7 @@ class Form dol_syslog(get_class($this) . "::select_remises", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { - print ''; $num = $this->db->num_rows($resql); $qualifiedlines = $num; @@ -4749,12 +4753,13 @@ class Form if ($resql) { $num = $this->db->num_rows($resql); $i = 0; + /** @var array */ $tmparray = array(); while ($i < $num) { $obj = $this->db->fetch_object($resql); // Si traduction existe, on l'utilise, sinon on prend le libelle par default - $label = ($obj->label != '-' ? $obj->label : ''); + $label = ($obj->label != '-' ? (string) $obj->label : ''); if ($langs->trans("DemandReasonType" . $obj->code) != "DemandReasonType" . $obj->code) { $label = $langs->trans("DemandReasonType" . $obj->code); // So translation key DemandReasonTypeSRC_XXX will work } @@ -4762,9 +4767,12 @@ class Form $label = $langs->trans($obj->code); // So translation key SRC_XXX will work } - $tmparray[$obj->rowid]['id'] = (int) $obj->rowid; - $tmparray[$obj->rowid]['code'] = $obj->code; - $tmparray[$obj->rowid]['label'] = $label; + $tmparray[(int) $obj->rowid] + = array( + 'id' => (int) $obj->rowid, + 'code' => (string) $obj->code, + 'label' => $label, + ); $i++; } @@ -5226,10 +5234,13 @@ class Form // If traduction exist, we use it else we take the default label $label = ($langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) != "PaymentTypeShort" . $obj->code ? $langs->transnoentitiesnoconv("PaymentTypeShort" . $obj->code) : ($obj->label != '-' ? $obj->label : '')); - $this->cache_transport_mode[$obj->rowid]['rowid'] = $obj->rowid; - $this->cache_transport_mode[$obj->rowid]['code'] = $obj->code; - $this->cache_transport_mode[$obj->rowid]['label'] = $label; - $this->cache_transport_mode[$obj->rowid]['active'] = $obj->active; + $this->cache_transport_mode[(int) $obj->rowid] + = array( + 'rowid' => (int) $obj->rowid, + 'code' => (string) $obj->code, + 'label' => (string) $label, + 'active' => (int) $obj->active, + ); $i++; } @@ -6844,10 +6855,10 @@ class Form * Show form with transport mode * * @param string $page Page - * @param string $selected Id mode pre-select + * @param int|'' $selected Id mode pre-select * @param string $htmlname Name of select html field - * @param int $active Active or not, -1 = all - * @param int $addempty 1=Add empty entry + * @param int<-1,1> $active Active or not, -1 = all + * @param int<0,1> $addempty 1=Add empty entry * @return void */ public function formSelectTransportMode($page, $selected = '', $htmlname = 'transport_mode_id', $active = 1, $addempty = 0) diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 4018933ed7e..3131b264e5d 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -582,6 +582,7 @@ class FormCompany extends Form if ($num) { $i = 0; $country = ''; + /** @var array $arraydata */ $arraydata = array(); while ($i < $num) { $obj = $this->db->fetch_object($resql); @@ -589,7 +590,7 @@ class FormCompany extends Form if ($obj->code) { // We exclude empty line, we will add it later $labelcountry = (($langs->trans("Country" . $obj->country_code) != "Country" . $obj->country_code) ? $langs->trans("Country" . $obj->country_code) : $obj->country); $labeljs = (($langs->trans("JuridicalStatus" . $obj->code) != "JuridicalStatus" . $obj->code) ? $langs->trans("JuridicalStatus" . $obj->code) : ($obj->label != '-' ? $obj->label : '')); // $obj->label is already in output charset (converted by database driver) - $arraydata[$obj->code] = array('code' => $obj->code, 'label' => $labeljs, 'label_sort' => $labelcountry . '_' . $labeljs, 'country_code' => $obj->country_code, 'country' => $labelcountry); + $arraydata[(int) $obj->code] = array('code' => (int) $obj->code, 'label' => $labeljs, 'label_sort' => $labelcountry . '_' . $labeljs, 'country_code' => (string) $obj->country_code, 'country' => $labelcountry); } $i++; } diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 6ab8eaca887..92f10d73c0c 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -507,8 +507,32 @@ class FormFile } $printer = 0; + $supportedmoduleparts = [ + 'company', + 'member', + 'product', + 'stock', + 'ficheinter', + 'user', + 'project', + 'contract', + 'facture', + 'supplier_proposal', + 'propal', + 'proposal', + 'order', + 'commande', + 'expedition', + 'commande_fournisseur', + 'facture_fournisseur', + 'expensereport', + 'delivery', + 'ticket', + 'bom', + 'mrp:mo', + ]; // The direct print feature is implemented only for such elements - if (in_array($modulepart, array('contract', 'facture', 'supplier_proposal', 'propal', 'proposal', 'order', 'commande', 'expedition', 'commande_fournisseur', 'expensereport', 'delivery', 'ticket'))) { + if (in_array($modulepart, $supportedmoduleparts)) { $printer = ($user->hasRight('printing', 'read') && isModEnabled('printing')); } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index a2136039999..a44357ecd92 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5691,7 +5691,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = 0, $srco 'accounting_account' => 'infobox-bank_account', 'accountline' => 'infobox-bank_account', 'accountancy' => 'infobox-bank_account', - 'admin'=> 'opacitymedium', + 'admin' => 'opacitymedium', 'asset' => 'infobox-bank_account', 'bank_account' => 'infobox-bank_account', 'bill' => 'infobox-commande', @@ -8445,7 +8445,8 @@ function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, } // If the (seller country = buyer country) then the default VAT = VAT of the product sold. End of rule. - if (empty($vatrule) && (($seller_country_code == $buyer_country_code) + if (empty($vatrule) && ( + ($seller_country_code == $buyer_country_code) || (in_array($seller_country_code, array('FR', 'MC')) && in_array($buyer_country_code, array('FR', 'MC'))) || (in_array($seller_country_code, array('MQ', 'GP')) && in_array($buyer_country_code, array('MQ', 'GP'))) // We should be able to manage the case of MQ, GP, ... with a deicated vat rate at previous step. )) { // Warning ->country_code not always defined @@ -8517,7 +8518,8 @@ function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, // Allow an external module to bypass the calculation of prices $parameters = array('vatvalue' => $vatvalue, 'vatrule' => $vatrule); - $tmpobject = null; $tmpaction = ''; + $tmpobject = null; + $tmpaction = ''; // @phan-suppress-next-line PhanPluginConstantVariableNull $reshook = $hookmanager->executeHooks('get_default_tva', $parameters, $tmpobject, $tmpaction); // @phan-suppress-current-line PhanPluginConstantVariableNull if ($reshook > 0 && !empty($hookmanager->resArray['vatvalue'])) { diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index b425ea09617..e5ad6f19dba 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -139,16 +139,16 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it */ public $rights_class; - public const URL_FOR_BLACKLISTED_MODULES = 'https://ping.dolibarr.org/modules-blacklist.txt'; + const URL_FOR_BLACKLISTED_MODULES = 'https://ping.dolibarr.org/modules-blacklist.txt'; - public const KEY_ID = 0; - public const KEY_LABEL = 1; - public const KEY_TYPE = 2; // deprecated - public const KEY_DEFAULT = 3; - public const KEY_FIRST_LEVEL = 4; - public const KEY_SECOND_LEVEL = 5; - public const KEY_MODULE = 6; - public const KEY_ENABLED = 7; + const KEY_ID = 0; + const KEY_LABEL = 1; + const KEY_TYPE = 2; // deprecated + const KEY_DEFAULT = 3; + const KEY_FIRST_LEVEL = 4; + const KEY_SECOND_LEVEL = 5; + const KEY_MODULE = 6; + const KEY_ENABLED = 7; /** * @var array|int<1,1> Module menu entries (1 means the menu entries are not declared into module descriptor but are hardcoded into menu manager) diff --git a/htdocs/core/modules/printing/modules_printing.php b/htdocs/core/modules/printing/modules_printing.php index e1df70fa5f7..d9aabb51d9a 100644 --- a/htdocs/core/modules/printing/modules_printing.php +++ b/htdocs/core/modules/printing/modules_printing.php @@ -1,6 +1,6 @@ + * Copyright (C) 2014-2025 Frédéric France * Copyright (C) 2024-2025 MDW * * This program is free software; you can redistribute it and/or modify @@ -47,7 +47,6 @@ class PrintingDriver */ public $errors = array(); - /** * @var string Name */ diff --git a/htdocs/core/modules/printing/printipp.modules.php b/htdocs/core/modules/printing/printipp.modules.php index f51d105f650..17f57351398 100644 --- a/htdocs/core/modules/printing/printipp.modules.php +++ b/htdocs/core/modules/printing/printipp.modules.php @@ -244,7 +244,6 @@ class printing_printipp extends PrintingDriver */ public function getlistAvailablePrinters() { - global $conf, $db; include_once DOL_DOCUMENT_ROOT.'/includes/printipp/CupsPrintIPP.php'; $ipp = new CupsPrintIPP(); $ipp->setLog(DOL_DATA_ROOT.'/dolibarr_printipp.log', 'file', 3); // logging very verbose @@ -254,7 +253,12 @@ class printing_printipp extends PrintingDriver if (!empty($this->user)) { $ipp->setAuthentication($this->user, $this->password); } - $ipp->getPrinters(); + try { + $ipp->getPrinters(); + } catch (Exception $e) { + setEventMessage($e->getMessage(), 'errors'); + } + return $ipp->available_printers; } diff --git a/htdocs/core/triggers/interface_95_modWebhook_WebhookTriggers.class.php b/htdocs/core/triggers/interface_95_modWebhook_WebhookTriggers.class.php index e2cfbcd2df3..f260ec47dd6 100644 --- a/htdocs/core/triggers/interface_95_modWebhook_WebhookTriggers.class.php +++ b/htdocs/core/triggers/interface_95_modWebhook_WebhookTriggers.class.php @@ -69,6 +69,7 @@ class InterfaceWebhookTriggers extends DolibarrTriggers */ public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) { + global $dolibarr_main_db_pass; if (!isModEnabled('webhook')) { return 0; // If module is not enabled, we do nothing } @@ -93,6 +94,9 @@ class InterfaceWebhookTriggers extends DolibarrTriggers return 0; } + // Create new instance of db for webhook history save + $dbhistory = getDoliDBInstance($conf->db->type, $conf->db->host, (string) $conf->db->user, $dolibarr_main_db_pass, $conf->db->name, (int) $conf->db->port); + $sendmanualtriggers = (!empty($object->context['sendmanualtriggers']) ? $object->context['sendmanualtriggers'] : ""); foreach ($target_url as $key => $tmpobject) { // Set list of all triggers for this targetinto $actionarray @@ -146,7 +150,8 @@ class InterfaceWebhookTriggers extends DolibarrTriggers }*/ } - $triggerhistory = new TriggerHistory($this->db); + $dbhistory->begin(); + $triggerhistory = new TriggerHistory($dbhistory); $triggerhistory->trigger_code = $action; $triggerhistory->trigger_data = $jsonstr; $triggerhistory->fk_target = $tmpobject->id; @@ -157,10 +162,14 @@ class InterfaceWebhookTriggers extends DolibarrTriggers if (!$resql) { $errors++; $this->errors = array_merge($this->errors, $triggerhistory->errors); + $dbhistory->rollback(); + } else { + $dbhistory->commit(); } } } + $dbhistory->close(); dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id." -> nbPost=".$nbPosts); if (!empty($errors)) { diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 9c4368b286a..28154fa95c6 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1395,17 +1395,17 @@ class EmailCollector extends CommonObject array_push($criteria, array($not."CC" => $rule['rulevalue'])); } if ($rule['type'] == 'subject') { - if (strpos($rule['rulevalue'], '!') === 0) { + if ($not) { //array_push($criteria, array("NOT SUBJECT" => $rule['rulevalue'])); - $searchfilterexcludesubjectarray[] = preg_replace('/^!/', '', $rule['rulevalue']); + $searchfilterexcludesubjectarray[] = $rule['rulevalue']; } else { array_push($criteria, array("SUBJECT" => $rule['rulevalue'])); } } if ($rule['type'] == 'body') { - if (strpos($rule['rulevalue'], '!') === 0) { + if ($not) { //array_push($criteria, array("NOT BODY" => $rule['rulevalue'])); - $searchfilterexcludebodyarray[] = preg_replace('/^!/', '', $rule['rulevalue']); + $searchfilterexcludebodyarray[] = $rule['rulevalue']; } else { array_push($criteria, array("BODY" => $rule['rulevalue'])); } diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index f00273f3599..a1018a8f10e 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -294,7 +294,16 @@ if (empty($reshook)) { if ($action == 'add' && $permissiontoadd) { $db->begin(); - if (GETPOSTINT('socid') < 1) { + if ($origin && $origin_id > 0) { + // We will loop on each line of the original document to complete the shipping object with various info and quantity to deliver + $classname = ucfirst($origin); + $objectsrc = new $classname($db); + '@phan-var-force Facture|Commande $objectsrc'; + $objectsrc->fetch($origin_id); + $object->socid = $objectsrc->socid; + } + + if (GETPOSTINT('socid') < 1 && $object->socid < 1) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ThirdParty")), null, 'errors'); $action = 'create'; @@ -1418,7 +1427,7 @@ $product_static = new Product($db); $shipment_static = new Expedition($db); $warehousestatic = new Entrepot($db); -if ($action == 'create' && !getDolGlobalString('SHIPMENT_STANDALONE')) { +if (!$origin && $action == 'create' && !getDolGlobalString('SHIPMENT_STANDALONE')) { print load_fiche_titre($langs->trans("CreateShipment"), '', 'dolly'); print '
' .$langs->trans("ShipmentCreationIsDoneFromOrder"); @@ -2257,7 +2266,7 @@ if ($action == 'create' && $usercancreate) { } } else { // ship from multiple locations - if (isModEnabled('productbatch') || !$product->hasbatch()) { + if (!isModEnabled('productbatch') || !$product->hasbatch()) { print ''; print ''; if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) { @@ -2464,6 +2473,7 @@ if ($action == 'create' && $usercancreate) { print ''; print ''; + print ''; //print '|'.$line->fk_product.'|'.$dbatch->batch.'|
'; print $langs->trans("Batch") . ': '; diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index 089374b8b6e..280329b3f0b 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -66,14 +66,14 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; // Load translation files required by the page $langs->loadLangs(array('bills', 'companies', 'interventions', 'stocks')); -$id = GETPOSTINT('id'); -$ref = GETPOST('ref', 'alpha'); +$id = GETPOSTINT('id'); +$ref = GETPOST('ref', 'alpha'); $ref_client = GETPOST('ref_client', 'alpha'); $socid = GETPOSTINT('socid'); $contratid = GETPOSTINT('contratid'); -$action = GETPOST('action', 'alpha'); -$cancel = GETPOST('cancel', 'alpha'); -$confirm = GETPOST('confirm', 'alpha'); +$action = GETPOST('action', 'alpha'); +$cancel = GETPOST('cancel', 'alpha'); +$confirm = GETPOST('confirm', 'alpha'); $backtopage = GETPOST('backtopage', 'alpha'); $mesg = GETPOST('msg', 'alpha'); diff --git a/htdocs/install/mysql/migration/22.0.0-23.0.0.sql b/htdocs/install/mysql/migration/22.0.0-23.0.0.sql index f8a2cce8326..90a6f131b39 100644 --- a/htdocs/install/mysql/migration/22.0.0-23.0.0.sql +++ b/htdocs/install/mysql/migration/22.0.0-23.0.0.sql @@ -394,4 +394,7 @@ CREATE TABLE llx_expensereport_det_extrafields ALTER TABLE llx_blockedlog ADD INDEX idx_ref_object (ref_object); ALTER TABLE llx_blockedlog ADD CONSTRAINT fk_linktoref FOREIGN KEY (linktoref) REFERENCES llx_blockedlog(ref_object); +ALTER TABLE llx_fichinterdet ADD COLUMN special_code integer DEFAULT 0 AFTER fk_parent_line; +ALTER TABLE llx_fichinterdet ADD COLUMN product_type integer DEFAULT 0 AFTER special_code; + -- end of migration diff --git a/htdocs/install/mysql/tables/llx_fichinterdet.sql b/htdocs/install/mysql/tables/llx_fichinterdet.sql index f25c14f14d8..0ee2ec41b51 100644 --- a/htdocs/install/mysql/tables/llx_fichinterdet.sql +++ b/htdocs/install/mysql/tables/llx_fichinterdet.sql @@ -22,6 +22,8 @@ create table llx_fichinterdet rowid integer AUTO_INCREMENT PRIMARY KEY, fk_fichinter integer, fk_parent_line integer NULL, + special_code integer DEFAULT 0, -- code for special lines (may be 1=transport, 2=ecotax, 3=option, moduleid=...) + product_type integer DEFAULT 0, date datetime, -- date de la ligne d'intervention description text, -- description de la ligne d'intervention duree integer, -- duree de la ligne d'intervention diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 8f32f43092a..e5e73ab10eb 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -683,6 +683,7 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ 'MAIN_MODULE_BLOCKEDLOG' => 'noboxes', 'MAIN_MODULE_DON' => 'newboxdefonly', 'MAIN_MODULE_ECM' => 'newboxdefonly', + 'MAIN_MODULE_EVENTORGANIZATION' => 'newboxdefonly', 'MAIN_MODULE_EXPENSEREPORT' => 'newboxdefonly', 'MAIN_MODULE_FACTURE' => 'newboxdefonly', 'MAIN_MODULE_FOURNISSEUR' => 'newboxdefonly', @@ -4567,8 +4568,8 @@ function migrate_productlot_path() } if ($dir) { - $lot->id = $obj->rowid; - $lot->ref = $obj->id; // No ref for the moment + $lot->id = (int) $obj->rowid; + $lot->ref = (string) $obj->rowid; // No ref for the moment $lot->batch = $obj->batch; $lot->entity = $obj->entity; $lot->fk_product = $obj->fk_product; diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index ef03e65b1aa..cd6131ffa1a 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -30,7 +30,7 @@ InvoiceReplacementShort=Replacement InvoiceReplacementAsk=Replacement invoice for invoice InvoiceReplacementDesc=Replacement invoice is used to completely replace an invoice with no payment already received.

Note: Only invoices with no payment on it can be replaced. If the invoice you replace is not yet closed, it will be automatically closed to 'abandoned'. InvoiceAvoir=Credit note -InvoiceAvoirAsk=Credit note +InvoiceAvoirAsk=Credit note from InvoiceAvoirAskCombo=Invoice to correct InvoiceAvoirDesc=The credit note is a negative invoice used to correct the fact that an invoice shows an amount that differs from the amount actually paid (eg the customer paid too much by mistake, or will not pay the complete amount since some products were returned). invoiceAvoirWithLines=Create Credit Note with lines from the origin invoice diff --git a/htdocs/langs/en_US/blockedlog.lang b/htdocs/langs/en_US/blockedlog.lang index f2ba1d3788c..9d83eab7b98 100644 --- a/htdocs/langs/en_US/blockedlog.lang +++ b/htdocs/langs/en_US/blockedlog.lang @@ -49,6 +49,7 @@ TotalTTCIfInvoiceSeeCompleteDataForDetail=Amount of event. Total including tax i TypeOfEvent=Type of event TotalForAction=Total for event %s SecretKey=Secret key +ErrorPeriodMustBePastToAllowExport=Export into archives is allowed only if period is completely past ## logTypes logBILL_DELETE=Customer invoice logically deleted diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index c118bbd2457..20c66ad8f15 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -369,6 +369,10 @@ ErrorPaymentAmountMustNotBeNull=Error, payment amount must be defined and not ze ErrorOneLineContainsADisactivatedProduct=Error, at least one product is not or no more on sale or for purchase ErrorCalendarIsNotYetOpenOrHasBeenClosed=This calendar is not yet open or has been closed ErrorFieldClassNotFoundForClassName=The class "%s" managing the field type "%s" is not found. +ErrorBlockLogNeedAmountsValue=The unalterbale log object needs amounts values to be set +ErrorBlockLogNeedElement=The unalterbale log object needs element type to be set +ErrorBlockLogNeedObject=The unalterbale log object needs object to be set +ErrorBadParameterWhenCallingCreateOfBlockedLog=Bad parameter when calling create of blocked log # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. diff --git a/htdocs/margin/agentMargins.php b/htdocs/margin/agentMargins.php index 43496922547..7c9fcc45315 100644 --- a/htdocs/margin/agentMargins.php +++ b/htdocs/margin/agentMargins.php @@ -280,23 +280,24 @@ if ($result) { print "\n"; if ($num > 0) { + /** @var array $group_list */ $group_list = array(); while ($objp = $db->fetch_object($result)) { if ($agentid > 0) { - $group_id = $objp->socid; + $group_id = (int) $objp->socid; } else { - $group_id = $objp->agent; + $group_id = (int) $objp->agent; } if (!isset($group_list[$group_id])) { if ($agentid > 0) { - $group_name = $objp->name; + $group_name = (string) $objp->name; $companystatic->id = $objp->socid; $companystatic->name = $objp->name; $companystatic->client = $objp->client; $group_htmlname = $companystatic->getNomUrl(1, 'customer'); } else { - $group_name = $objp->lastname; + $group_name = (string) $objp->lastname; $userstatic->fetch($objp->agent); $group_htmlname = $userstatic->getFullName($langs, 0, 0, 0); } @@ -317,15 +318,15 @@ if ($result) { } else { if ($obj_seller = $db->fetch_object($resql_seller)) { if ($obj_seller->nb > 0) { - $seller_nb = $obj_seller->nb; + $seller_nb = (int) $obj_seller->nb; } } } } - $group_list[$group_id]['selling_price'] += $objp->selling_price / $seller_nb; - $group_list[$group_id]['buying_price'] += $objp->buying_price / $seller_nb; - $group_list[$group_id]['marge'] += $objp->marge / $seller_nb; + $group_list[$group_id]['selling_price'] += (float) $objp->selling_price / $seller_nb; + $group_list[$group_id]['buying_price'] += (float) $objp->buying_price / $seller_nb; + $group_list[$group_id]['marge'] += (float) $objp->marge / $seller_nb; } // sort group array by sortfield diff --git a/htdocs/modulebuilder/admin/setup.php b/htdocs/modulebuilder/admin/setup.php index d4222b926b6..6ed53954e5f 100644 --- a/htdocs/modulebuilder/admin/setup.php +++ b/htdocs/modulebuilder/admin/setup.php @@ -1,6 +1,7 @@ * Copyright (C) 2024 Frédéric France + * Copyright (C) 2024 Benjamin Falière * * 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 @@ -144,61 +145,61 @@ if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { } print ''; -print ''.$langs->trans("UseSpecificEditorName").''; +print ''; print ''; -print ''; +print ''; print ''; print ''; print ''; -print ''.$langs->trans("UseSpecificEditorURL").''; +print ''; print ''; -print ''; +print ''; print ''; print ''; if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { print ''; - print ''.$langs->trans("UseSpecificFamily").''; + print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''.$langs->trans("UseSpecificAuthor").''; + print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''.$langs->trans("UseSpecificVersion").''; + print ''; print ''; - print ''; + print ''; print ''; print ''; } print ''; -print ''.$langs->trans("UseSpecificReadme").''; +print ''; print ''; -print ''; +print ''; print ''; print ''; print ''; -print ''.$langs->trans("AsciiToHtmlConverter").''; +print ''; print ''; -print ''; +print ''; print ' '.$langs->trans("Example").': asciidoc, asciidoctor'; print ''; print ''; print ''; -print ''.$langs->trans("AsciiToPdfConverter").''; +print ''; print ''; -print ''; +print ''; print ' '.$langs->trans("Example").': asciidoctor-pdf'; print ''; print ''; diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 05868f72fb0..a46d4ca06b9 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1342,6 +1342,9 @@ if (empty($reshook)) { } } + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; + // Actions to send emails $triggersendname = 'PRODUCT_SENTBYMAIL'; $paramname = 'id'; diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php index 6d37679a266..363f39b3968 100644 --- a/htdocs/product/stock/card.php +++ b/htdocs/product/stock/card.php @@ -284,6 +284,8 @@ if (empty($reshook)) { $action = ''; } + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; // Actions to build doc $upload_dir = $conf->stock->dir_output; diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index e97160987bf..b53a8ee9954 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -614,6 +614,9 @@ if (empty($reshook)) { } } + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; + // Actions to send emails $triggersendname = 'PROJECT_SENTBYMAIL'; $paramname = 'id'; diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index b9ca8e591da..7d1ff903a2f 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -945,6 +945,9 @@ if (empty($reshook)) { $upload_dir = !empty($conf->societe->multidir_output[$object->entity ?? $conf->entity]) ? $conf->societe->multidir_output[$object->entity ?? $conf->entity] : $conf->societe->dir_output; $permissiontoadd = $user->hasRight('societe', 'creer'); include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; } @@ -1094,12 +1097,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio } } - $object->phone = GETPOST('phone', 'alpha'); - $object->phone_mobile = (string) GETPOST("phone_mobile", 'alpha'); - $object->fax = GETPOST('fax', 'alpha'); - $object->email = GETPOST('email', 'email'); - $object->url = GETPOST('url', 'url'); - $object->capital = GETPOST('capital'); // can be null or 0 or a float value + $object->phone = GETPOST('phone', 'alpha'); + $object->phone_mobile = (string) GETPOST("phone_mobile", 'alpha'); + $object->fax = GETPOST('fax', 'alpha'); + $object->email = GETPOST('email', 'email'); + $object->url = GETPOST('url', 'url'); + $object->capital = GETPOST('capital'); // can be null or 0 or a float value $paymentTermId = GETPOSTINT('cond_reglement_id'); // can be set by default values on create page and not already in get or post variables if (empty($paymentTermId) && !GETPOSTISSET('cond_reglement_id')) { $paymentTermId = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TERM_ID'); @@ -1109,28 +1112,28 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio if (empty($paymentTypeId) && !GETPOSTISSET('mode_reglement_id')) { $paymentTypeId = getDolGlobalString('MAIN_DEFAULT_PAYMENT_TYPE_ID'); } - $object->mode_reglement_id = $paymentTypeId; - $object->barcode = GETPOST('barcode', 'alphanohtml'); - $object->idprof1 = GETPOST('idprof1', 'alphanohtml'); - $object->idprof2 = GETPOST('idprof2', 'alphanohtml'); - $object->idprof3 = GETPOST('idprof3', 'alphanohtml'); - $object->idprof4 = GETPOST('idprof4', 'alphanohtml'); - $object->idprof5 = GETPOST('idprof5', 'alphanohtml'); - $object->idprof6 = GETPOST('idprof6', 'alphanohtml'); + $object->mode_reglement_id = $paymentTypeId; + $object->barcode = GETPOST('barcode', 'alphanohtml'); + $object->idprof1 = GETPOST('idprof1', 'alphanohtml'); + $object->idprof2 = GETPOST('idprof2', 'alphanohtml'); + $object->idprof3 = GETPOST('idprof3', 'alphanohtml'); + $object->idprof4 = GETPOST('idprof4', 'alphanohtml'); + $object->idprof5 = GETPOST('idprof5', 'alphanohtml'); + $object->idprof6 = GETPOST('idprof6', 'alphanohtml'); $object->typent_id = GETPOSTINT('typent_id'); - $object->effectif_id = GETPOSTINT('effectif_id'); - $object->civility_id = GETPOST('civility_id', 'alpha'); + $object->effectif_id = GETPOSTINT('effectif_id'); + $object->civility_id = GETPOST('civility_id', 'alpha'); $object->tva_assuj = GETPOSTINT('assujtva_value'); $object->vat_reverse_charge = GETPOST('vat_reverse_charge') == 'on' ? 1 : 0; $object->status = GETPOSTINT('status'); //Local Taxes - $object->localtax1_assuj = GETPOSTINT('localtax1assuj_value'); - $object->localtax2_assuj = GETPOSTINT('localtax2assuj_value'); + $object->localtax1_assuj = GETPOSTINT('localtax1assuj_value'); + $object->localtax2_assuj = GETPOSTINT('localtax2assuj_value'); - $object->localtax1_value = GETPOST('lt1', 'alpha'); - $object->localtax2_value = GETPOST('lt2', 'alpha'); + $object->localtax1_value = GETPOST('lt1', 'alpha'); + $object->localtax2_value = GETPOST('lt2', 'alpha'); $object->tva_intra = GETPOST('tva_intra', 'alphanohtml'); @@ -1147,7 +1150,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio } } if (GETPOSTISSET('accountancy_code_buy')) { - $accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha'); + $accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha'); if (empty($accountancy_code_buy) || $accountancy_code_buy == '-1') { $object->accountancy_code_buy = ''; @@ -1159,7 +1162,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio $object->logo = (isset($_FILES['photo']) ? dol_sanitizeFileName($_FILES['photo']['name']) : ''); // Company logo management - $dir = $conf->societe->multidir_output[$conf->entity]."/".$object->id."/logos"; + $dir = $conf->societe->multidir_output[$conf->entity]."/".$object->id."/logos"; $file_OK = (isset($_FILES['photo']) ? is_uploaded_file($_FILES['photo']['tmp_name']) : false); if ($file_OK) { if (image_format_supported($_FILES['photo']['name'])) { diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index 4e83728ff7d..136add22e74 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -1094,6 +1094,7 @@ class Thirdparties extends DolibarrApi * @since 7.0.0 Initial implementation * * @param int $id ID of the third party + * @param string $mode 'customer' or 'supplier' * @param string $filter Filter exceptional discount. "none" will return every discount, "available" returns unapplied discounts, "used" returns applied discounts {@choice none,available,used} * @param string $sortfield Sort field * @param string $sortorder Sort order @@ -1109,7 +1110,7 @@ class Thirdparties extends DolibarrApi * @throws RestException 404 * @throws RestException 503 */ - public function getFixedAmountDiscounts($id, $filter = "none", $sortfield = "f.type", $sortorder = 'ASC') + public function getFixedAmountDiscounts($id, $mode = 'customer', $filter = "none", $sortfield = "f.type", $sortorder = 'ASC') { $obj_ret = array(); @@ -1130,15 +1131,27 @@ class Thirdparties extends DolibarrApi throw new RestException(404, 'Thirdparty not found'); } - - $sql = "SELECT f.ref, f.type as factype, re.fk_facture_source, re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc, re.description, re.fk_facture, re.fk_facture_line"; - $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re, ".MAIN_DB_PREFIX."facture as f"; - $sql .= " WHERE f.rowid = re.fk_facture_source AND re.fk_soc = ".((int) $id); - if ($filter == "available") { - $sql .= " AND re.fk_facture IS NULL AND re.fk_facture_line IS NULL"; - } - if ($filter == "used") { - $sql .= " AND (re.fk_facture IS NOT NULL OR re.fk_facture_line IS NOT NULL)"; + $sql = ''; + if ($mode === 'customer') { + $sql = "SELECT f.ref, f.type as factype, re.fk_facture_source, re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc, re.description, re.fk_facture, re.fk_facture_line"; + $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re, ".MAIN_DB_PREFIX."facture as f"; + $sql .= " WHERE f.rowid = re.fk_facture_source AND re.fk_soc = ".((int) $id); + if ($filter == "available") { + $sql .= " AND re.fk_facture IS NULL AND re.fk_facture_line IS NULL"; + } + if ($filter == "used") { + $sql .= " AND (re.fk_facture IS NOT NULL OR re.fk_facture_line IS NOT NULL)"; + } + } elseif ($mode === 'supplier') { + $sql = "SELECT f.ref, f.type as factype, re.fk_invoice_supplier_source, re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc, re.description, re.fk_invoice_supplier, re.fk_invoice_supplier_line"; + $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re, ".MAIN_DB_PREFIX."facture_fourn as f"; + $sql .= " WHERE f.rowid = re.fk_invoice_supplier_source AND re.fk_soc = ".((int) $id); + if ($filter == "available") { + $sql .= " AND re.fk_invoice_supplier IS NULL AND re.fk_invoice_supplier_line IS NULL"; + } + if ($filter == "used") { + $sql .= " AND (re.fk_invoice_supplier IS NOT NULL OR re.fk_invoice_supplier_line IS NOT NULL)"; + } } $sql .= $this->db->order($sortfield, $sortorder); diff --git a/htdocs/societe/consumption.php b/htdocs/societe/consumption.php index f9b4fe84da0..b7d40da8429 100644 --- a/htdocs/societe/consumption.php +++ b/htdocs/societe/consumption.php @@ -29,12 +29,6 @@ // Load Dolibarr environment require "../main.inc.php"; -require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php'; - - /** * @var Conf $conf * @var DoliDB $db @@ -42,6 +36,10 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php'; * @var Translate $langs * @var User $user */ +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php'; // Load translation files required by the page $langs->loadLangs(array("companies", "bills", "orders", "suppliers", "propal", "interventions", "contracts", "products")); @@ -508,7 +506,7 @@ if ($sql_select) { // Filters print ''; print ''; - print ''; + print ''; print ''; print ''; // date print $formother->select_month($month ? (string) $month : '-1', 'month', 1, 0, 'valignmiddle'); @@ -573,7 +571,7 @@ if ($sql_select) { } print ''; - print ''; + print ''; print $documentstatic->getNomUrl(1); print ''; print ''.dol_print_date($db->jdate($objp->dateprint), 'day').''; diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index b010c0555f1..404c780b2ef 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -1241,6 +1241,9 @@ td.wordbreak img, td.wordbreakimp img { .marginleftlarge { margin-: 20px !important; } +.marginleftlargeondesktop { + margin-: 20px; +} .paddinglarge { padding: 6px !important; } @@ -2280,6 +2283,10 @@ datalist { font-size: !important; } + .marginleftlargeondesktop { + margin-: 0; + } + div#login_left, div#login_right { min-width: 150px !important; max-width: 240px !important; @@ -4434,7 +4441,7 @@ td.border, div.tagtable div div.border { .nobordertop, .nobordertop tr:first-of-type td { border-top: none !important; } -.noborderbottom, .noborderbottom tr:last-of-type td { +.noborderbottom, tr.noborderbottom td, .noborderbottom tr:last-of-type td { border-bottom: none !important; } .bordertop { diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 0369cb6fadb..1b55a2214c9 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1397,6 +1397,9 @@ td.wordbreak img, td.wordbreakimp img { .marginleftlarge { margin-: 20px !important; } +.marginleftlargeondesktop { + margin-: 20px; +} .paddinglarge { padding: 6px !important; } @@ -1587,8 +1590,12 @@ span.fa.fa-plus-circle.paddingleft { margin-left: 1px; } .listofinvoicetype { - height: 28px; + min-height: 1.8em; vertical-align: middle; + padding-top: 7px; + padding-bottom: 1px; + display: flex; + align-items: center; } .divsocialnetwork:not(:last-child) { padding-: 20px; @@ -2395,6 +2402,10 @@ select.widthcentpercentminusxx, span.widthcentpercentminusxx:not(.select2-select font-size: !important; } + .marginleftlargeondesktop { + margin-: 0; + } + .login_vertical_align { padding-left: 0; } @@ -2436,7 +2447,7 @@ select.widthcentpercentminusxx, span.widthcentpercentminusxx:not(.select2-select height: 40px !important; } div.tabBar .listofinvoicetype table tr, div.tabBar .listofinvoicetype table tr td { - height: 28px !important; + height: 2.2em !important; } div.tabs div.tab a.tab { @@ -4478,7 +4489,7 @@ td.border, div.tagtable div div.border { .nobordertop, .nobordertop tr:first-of-type td { border-top: none !important; } -.noborderbottom, .noborderbottom tr:last-of-type td { +.noborderbottom, tr.noborderbottom td, .noborderbottom tr:last-of-type td { border-bottom: none !important; } .bordertop { diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 4b9c98d7bf0..cf4c724e88f 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -688,6 +688,8 @@ if (empty($reshook)) { $action = 'view'; } + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; $permissiondellink = $user->hasRight('ticket', 'write'); include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once' diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 241f56d47ef..a3c307bc880 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -879,6 +879,9 @@ if (empty($reshook)) { // Actions to build doc $upload_dir = $conf->user->dir_output; include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; } diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 9be513889f6..9b47ff3731b 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -372,7 +372,7 @@ class User extends CommonObject public $lastsearch_values; // To store last saved search criteria for user /** - * @var array|array,admin:int<0,1>,photo:string,fullpath:string,fullname:string,level:int}> Array of User (filled from fetchAll) or Array with hierarchy of user information (filled with get_full_tree() + * @var array|array,admin:int<0,1>,photo:string,fullpath:string,fullname:string,level:int}> Array of User (filled from fetchAll) or Array with hierarchy of user information (filled with get_full_tree()) */ public $users = array(); /** @@ -3923,23 +3923,26 @@ class User extends CommonObject if ($resql) { $i = 0; while ($obj = $this->db->fetch_object($resql)) { - $this->users[$obj->rowid]['rowid'] = $obj->rowid; - $this->users[$obj->rowid]['id'] = $obj->rowid; - $this->users[$obj->rowid]['fk_user'] = $obj->fk_user; - $this->users[$obj->rowid]['fk_soc'] = $obj->fk_soc; - $this->users[$obj->rowid]['firstname'] = $obj->firstname; - $this->users[$obj->rowid]['lastname'] = $obj->lastname; - $this->users[$obj->rowid]['login'] = $obj->login; - $this->users[$obj->rowid]['statut'] = $obj->statut; - $this->users[$obj->rowid]['entity'] = $obj->entity; - $this->users[$obj->rowid]['email'] = $obj->email; - $this->users[$obj->rowid]['gender'] = $obj->gender; - $this->users[$obj->rowid]['admin'] = $obj->admin; - $this->users[$obj->rowid]['photo'] = $obj->photo; - // fields are filled with build_path_from_id_user - $this->users[$obj->rowid]['fullpath'] = ''; - $this->users[$obj->rowid]['fullname'] = ''; - $this->users[$obj->rowid]['level'] = 0; + $this->users[(int) $obj->rowid] + = array( + 'rowid' => (int) $obj->rowid, + 'id' => (int) $obj->rowid, + 'fk_user' => (int) $obj->fk_user, + 'fk_soc' => (int) $obj->fk_soc, + 'firstname' => (string) $obj->firstname, + 'lastname' => (string) $obj->lastname, + 'login' => (string) $obj->login, + 'statut' => (int) $obj->statut, + 'entity' => (int) $obj->entity, + 'email' => (string) $obj->email, + 'gender' => (string) $obj->gender, + 'admin' => (int) $obj->admin, + 'photo' => (string) $obj->photo, + // fields are filled with build_path_from_id_user + 'fullpath' => '', + 'fullname' => '', + 'level' => 0, + ); $i++; } } else { diff --git a/htdocs/waf.inc.php b/htdocs/waf.inc.php index f514b46af26..60fc4e9c453 100644 --- a/htdocs/waf.inc.php +++ b/htdocs/waf.inc.php @@ -309,6 +309,13 @@ function analyseVarsForSqlAndScriptsInjection(&$var, $type, $stopcode = 1) } } +// Prevent the use of method TRACE +if ($_SERVER["REQUEST_METHOD"] == "TRACE") { + print 'Access refused with request method TRACE'; + http_response_code(405); + exit(); +} + // Sanity check on URL if (!defined('NOSCANPHPSELFFORINJECTION') && !empty($_SERVER["PHP_SELF"])) { $morevaltochecklikepost = array($_SERVER["PHP_SELF"]); diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php index f49d9994258..2c1c30bd9b5 100644 --- a/test/phpunit/AllTests.php +++ b/test/phpunit/AllTests.php @@ -253,6 +253,9 @@ class AllTests require_once dirname(__FILE__).'/AssetModelTest.php'; $suite->addTestSuite('AssetModelTest'); + require_once dirname(__FILE__).'/BlockedLogAndLNETest.php'; + $suite->addTestSuite('BlockedLogAndLNETest'); + // Rest require_once dirname(__FILE__).'/RestAPIUserTest.php'; $suite->addTestSuite('RestAPIUserTest'); diff --git a/test/phpunit/BlockedLogAndLNETest.php b/test/phpunit/BlockedLogAndLNETest.php new file mode 100644 index 00000000000..335a42ddd0d --- /dev/null +++ b/test/phpunit/BlockedLogAndLNETest.php @@ -0,0 +1,85 @@ + + * Copyright (C) 2023 Alexandre Janniaux + * Copyright (C) ---Put here your own copyright and developer email--- + * Copyright (C) 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file test/unit/BlockedLogAndLNETest.php + * \ingroup core + * \brief PHPUnit test for the BlockedLog and LNE class. + */ + +global $conf,$user,$langs,$db; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; +require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/compta/facture/class/facture.class.php'; +require_once dirname(__FILE__).'/../../htdocs/blockedlog/class/blockedlog.class.php'; +require_once dirname(__FILE__).'/CommonClassTest.class.php'; + +if (empty($user->id)) { + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + $user->loadRights(); +} +$conf->global->MAIN_DISABLE_ALL_MAILS = 1; + +$langs->load("main"); + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class BlockedLogAndLNETest extends CommonClassTest +{ + /** + * testBlockedLogAndLNETest + * + * @return int + */ + public function testBlockedLogAndLNETest() + { + global $conf,$user,$langs,$db; + $conf = $this->savconf; + $user = $this->savuser; + $langs = $this->savlangs; + $db = $this->savdb; + + $localobject = new BlockedLog($db); + $localobject->action = 'TEST'; + + $element = new Facture($db); + $element->initAsSpecimen(); + $localobject->element = $element->element; + $localobject->object_data = $element; + + $result = $localobject->create($user); + + print __METHOD__." result=".$result."\n"; + $this->assertLessThan($result, 0); + + return $result; + } + + + // TODO Add more tests +}