From: William Desportes <williamdes@wdes.fr>
Date: Sun, 15 Dec 2024 11:52:25 +0100
Subject: Upgrade symfony/* dependencies to v7

- https://github.com/symfony/monolog-bridge/compare/5.4...6.4
- https://github.com/symfony/monolog-bridge/compare/6.4...7.3 -> Migration to Monolog v3
- https://github.com/symfony/console/compare/5.4...6.4
- https://github.com/symfony/console/compare/6.4..7.3 -> A lot of changes, CHANGELOG okay
- https://github.com/symfony/event-dispatcher/compare/5.4...6.4 -> Changelog seems okay
- https://github.com/symfony/event-dispatcher/compare/6.4..7.3 -> Signature changes

Origin: vendor
Forwarded: no
Bug-Debian: https://bugs.debian.org/1117003
---
 composer.json                                      |   8 +-
 core/Console.php                                   |   2 +-
 core/Plugin/Archiver.php                           |   2 +-
 core/Plugin/ConsoleCommand.php                     |  36 ++--
 core/Plugin/Report.php                             |   2 +-
 core/Widget/WidgetConfig.php                       |   2 +-
 plugins/Actions/Reports/SiteSearchBase.php         |   2 +-
 plugins/CoreAdminHome/CustomLogo.php               |   2 +-
 plugins/CoreConsole/Commands/BuildTracker.php      |   2 +-
 .../CoreConsole/Commands/ComputeJsAssetSize.php    |   2 +-
 .../Commands/DevelopmentManageTestFiles.php        |   2 +-
 .../DevelopmentSyncProcessedSystemTests.php        |   2 +-
 .../CoreConsole/Commands/GeneratePluginBase.php    |   2 +-
 plugins/CoreConsole/Commands/GetSegmentSql.php     |   2 +-
 plugins/CoreConsole/Commands/GitCommit.php         |   2 +-
 plugins/CoreConsole/Commands/GitPull.php           |   2 +-
 plugins/CoreConsole/Commands/GitPush.php           |   2 +-
 plugins/CoreUpdater/Commands/ConvertToUtf8mb4.php  |   2 +-
 plugins/CoreUpdater/UpdateCommunication.php        |   2 +-
 plugins/CoreVue/Commands/Build.php                 |   2 +-
 plugins/CoreVue/Commands/BuildPolyfill.php         |   2 +-
 plugins/DBStats/Reports/Base.php                   |   2 +-
 plugins/Ecommerce/Reports/Base.php                 |   2 +-
 plugins/Ecommerce/Widgets/ProductsByDimension.php  |   2 +-
 plugins/ExampleReport/Reports/GetExampleReport.php |   2 +-
 .../GeoIp2/Commands/ConvertRegionCodesToIso.php    |   2 +-
 plugins/GeoIp2/Commands/UpdateRegionCodes.php      |   4 +-
 plugins/Intl/Commands/GenerateIntl.php             |   2 +-
 .../LanguagesManager/Commands/TranslationBase.php  |   2 +-
 plugins/Live/Reports/GetLastVisitsDetails.php      |   2 +-
 plugins/Login/Security/BruteForceDetection.php     |   4 +-
 plugins/Marketplace/UpdateCommunication.php        |   2 +-
 plugins/Monolog/Formatter/ConsoleFormatter.php     | 187 ++++++++++++++++++++-
 plugins/TestRunner/Commands/SyncScreenshots.php    |   2 +-
 plugins/VisitsSummary/Widgets/Index.php            |   2 +-
 35 files changed, 242 insertions(+), 57 deletions(-)

diff --git a/composer.json b/composer.json
index 60908ba..2f56364 100644
--- a/composer.json
+++ b/composer.json
@@ -57,12 +57,12 @@
         "php-di/php-di": "^7.0.0",
         "phpmailer/phpmailer": "^6.1",
         "psr/log": "^3.0",
-        "symfony/console": "~5.4.0",
-        "symfony/event-dispatcher": "~5.4.0",
-        "symfony/monolog-bridge": "~5.4.0",
+        "symfony/console": ">=6.4 <8",
+        "symfony/event-dispatcher": ">=6.4 <8",
+        "symfony/monolog-bridge": ">=6.4 <8",
         "symfony/polyfill-iconv": "^1.20",
         "symfony/polyfill-mbstring": "^1.20",
-        "symfony/process": "~5.4.0",
+        "symfony/process": ">=6.4 <8",
         "szymach/c-pchart": "~3.0.13",
         "tecnickcom/tcpdf": "~6.0",
         "tedivm/jshrink": "^1.6.5",
diff --git a/core/Console.php b/core/Console.php
index 6c01d25..7c5e518 100644
--- a/core/Console.php
+++ b/core/Console.php
@@ -86,7 +86,7 @@ class Console extends Application
         parent::renderThrowable($e, $output);
     }
 
-    public function doRun(InputInterface $input, OutputInterface $output)
+    public function doRun(InputInterface $input, OutputInterface $output): int
     {
         try {
             return $this->doRunImpl($input, $output);
diff --git a/core/Plugin/Archiver.php b/core/Plugin/Archiver.php
index 96ca8c1..840028b 100644
--- a/core/Plugin/Archiver.php
+++ b/core/Plugin/Archiver.php
@@ -333,7 +333,7 @@ class Archiver
      *
      * @return bool
      */
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return $this->enabled;
     }
diff --git a/core/Plugin/ConsoleCommand.php b/core/Plugin/ConsoleCommand.php
index 369c665..9d0d446 100644
--- a/core/Plugin/ConsoleCommand.php
+++ b/core/Plugin/ConsoleCommand.php
@@ -18,6 +18,7 @@ use Symfony\Component\Console\Exception\LogicException;
 use Symfony\Component\Console\Helper\ProgressBar;
 use Symfony\Component\Console\Helper\QuestionHelper;
 use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Helper\HelperInterface;
 use Symfony\Component\Console\Input\ArrayInput;
 use Symfony\Component\Console\Input\InputArgument;
 use Symfony\Component\Console\Input\InputInterface;
@@ -27,6 +28,7 @@ use Symfony\Component\Console\Output\OutputInterface;
 use Symfony\Component\Console\Question\ConfirmationQuestion;
 use Symfony\Component\Console\Question\Question;
 use Throwable;
+use Closure;
 
 /**
  * The base class for console commands.
@@ -192,9 +194,10 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
      *
      * Will only have an effect if the "SystemSignals" feature flag is enabled.
      */
-    final public function handleSignal(int $signal): void
+    final public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
     {
         $this->handleSystemSignal($signal);
+        return false;// Not sure about that
     }
 
     /**
@@ -223,7 +226,7 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
      * @param mixed             $default
      * @return ConsoleCommand
      */
-    public function addNegatableOption(string $name, $shortcut = null, string $description = '', $default = null)
+    public function addNegatableOption(string $name, array|string|null $shortcut = null, string $description = '', mixed $default = null)
     {
         return parent::addOption($name, $shortcut, InputOption::VALUE_NEGATABLE, $description, $default);
     }
@@ -240,9 +243,9 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
      */
     public function addOptionalValueOption(
         string $name,
-        $shortcut = null,
+        array|string|null $shortcut = null,
         string $description = '',
-        $default = null,
+        mixed $default = null,
         bool $acceptArrays = false
     ) {
         $mode = $acceptArrays ? InputOption::VALUE_IS_ARRAY : 0;
@@ -258,7 +261,7 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
      * @param mixed             $default
      * @return ConsoleCommand
      */
-    public function addNoValueOption(string $name, $shortcut = null, string $description = '', $default = null)
+    public function addNoValueOption(string $name, array|string|null $shortcut = null, string $description = '', mixed $default = null)
     {
         return parent::addOption($name, $shortcut, InputOption::VALUE_NONE, $description, $default);
     }
@@ -275,9 +278,9 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
      */
     public function addRequiredValueOption(
         string $name,
-        $shortcut = null,
+        array|string|null $shortcut = null,
         string $description = '',
-        $default = null,
+        mixed $default = null,
         bool $acceptArrays = false
     ) {
         $mode = $acceptArrays ? InputOption::VALUE_IS_ARRAY : 0;
@@ -291,11 +294,12 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
      */
     public function addOption(
         string $name,
-        $shortcut = null,
+        array|string|null $shortcut = null,
         ?int $mode = null,
         string $description = '',
-        $default = null
-    ) {
+        mixed $default = null,
+        Closure|array $suggestedValues = []
+    ): static {
         throw new \LogicException('addOption should not be used.');
     }
 
@@ -311,7 +315,7 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
     public function addOptionalArgument(
         string $name,
         string $description = '',
-        $default = null,
+        mixed $default = null,
         bool $acceptArrays = false
     ) {
         $mode = $acceptArrays ? InputArgument::IS_ARRAY : 0;
@@ -330,7 +334,7 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
     public function addRequiredArgument(
         string $name,
         string $description = '',
-        $default = null,
+        mixed $default = null,
         bool $acceptArrays = false
     ) {
         $mode = $acceptArrays ? InputArgument::IS_ARRAY : 0;
@@ -342,7 +346,7 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
      *
      * @see addOptionalArgument, addRequiredArgument
      */
-    public function addArgument(string $name, ?int $mode = null, string $description = '', $default = null)
+    public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null, Closure|array $suggestedValues = []): static
     {
         throw new \LogicException('addArgument can not be used.');
     }
@@ -434,7 +438,7 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
      *
      * @see askAndValidate(), askForConfirmation(), ask(), initProgressBar(), startProgressBar(), advanceProgressBar(), finishProgressBar(), renderTable()
      */
-    public function getHelper(string $name)
+    public function getHelper(string $name): HelperInterface
     {
         throw new \LogicException('getHelper can not be used');
     }
@@ -471,7 +475,7 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
     protected function askAndValidate(
         string $question,
         ?callable $validator = null,
-        $default = null,
+        mixed $default = null,
         ?iterable $autocompleterValues = null
     ) {
         /** @var QuestionHelper $helper */
@@ -491,7 +495,7 @@ class ConsoleCommand extends SymfonyCommand implements SignalableCommandInterfac
      * @param mixed|null $default
      * @return mixed
      */
-    protected function ask(string $question, $default = null)
+    protected function ask(string $question, mixed $default = null)
     {
         return $this->askAndValidate($question, null, $default);
     }
diff --git a/core/Plugin/Report.php b/core/Plugin/Report.php
index 4febcd1..ce041a4 100644
--- a/core/Plugin/Report.php
+++ b/core/Plugin/Report.php
@@ -259,7 +259,7 @@ class Report
      * @return bool
      * @api
      */
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return true;
     }
diff --git a/core/Widget/WidgetConfig.php b/core/Widget/WidgetConfig.php
index 952606f..f2728e3 100644
--- a/core/Widget/WidgetConfig.php
+++ b/core/Widget/WidgetConfig.php
@@ -213,7 +213,7 @@ class WidgetConfig
      * following: `return Piwik::hasUserSuperUserAccess();`
      * @return bool
      */
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return $this->isEnabled;
     }
diff --git a/plugins/Actions/Reports/SiteSearchBase.php b/plugins/Actions/Reports/SiteSearchBase.php
index f69baae..34dcd25 100644
--- a/plugins/Actions/Reports/SiteSearchBase.php
+++ b/plugins/Actions/Reports/SiteSearchBase.php
@@ -24,7 +24,7 @@ abstract class SiteSearchBase extends Base
         $this->onlineGuideUrl = Url::addCampaignParametersToMatomoLink('https://matomo.org/docs/site-search/');
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         $idSites = Common::getRequestVar('idSites', '', 'string');
         $idSite  = Common::getRequestVar('idSite', 0, 'int');
diff --git a/plugins/CoreAdminHome/CustomLogo.php b/plugins/CoreAdminHome/CustomLogo.php
index 194a4d0..64a2225 100644
--- a/plugins/CoreAdminHome/CustomLogo.php
+++ b/plugins/CoreAdminHome/CustomLogo.php
@@ -55,7 +55,7 @@ class CustomLogo
         return $svg;
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return $this->isCustomLogoFeatureEnabled() && Option::get('branding_use_custom_logo');
     }
diff --git a/plugins/CoreConsole/Commands/BuildTracker.php b/plugins/CoreConsole/Commands/BuildTracker.php
index c5b4c4f..cb50fce 100644
--- a/plugins/CoreConsole/Commands/BuildTracker.php
+++ b/plugins/CoreConsole/Commands/BuildTracker.php
@@ -25,7 +25,7 @@ class BuildTracker extends ConsoleCommand
         $this->addRequiredValueOption('plugin', null, 'The plugin to minify. If not supplied, minifies core tracker JS.');
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return \Piwik\Development::isEnabled();
     }
diff --git a/plugins/CoreConsole/Commands/ComputeJsAssetSize.php b/plugins/CoreConsole/Commands/ComputeJsAssetSize.php
index feafe71..216a950 100644
--- a/plugins/CoreConsole/Commands/ComputeJsAssetSize.php
+++ b/plugins/CoreConsole/Commands/ComputeJsAssetSize.php
@@ -41,7 +41,7 @@ class ComputeJsAssetSize extends ConsoleCommand
         $this->addRequiredValueOption('plugin', null, 'For submodule plugins and 3rd party plugins.');
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return SettingsPiwik::isGitDeployment();
     }
diff --git a/plugins/CoreConsole/Commands/DevelopmentManageTestFiles.php b/plugins/CoreConsole/Commands/DevelopmentManageTestFiles.php
index 5d3a69d..b96e465 100644
--- a/plugins/CoreConsole/Commands/DevelopmentManageTestFiles.php
+++ b/plugins/CoreConsole/Commands/DevelopmentManageTestFiles.php
@@ -14,7 +14,7 @@ use Piwik\Plugin\ConsoleCommand;
 
 class DevelopmentManageTestFiles extends ConsoleCommand
 {
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled();
     }
diff --git a/plugins/CoreConsole/Commands/DevelopmentSyncProcessedSystemTests.php b/plugins/CoreConsole/Commands/DevelopmentSyncProcessedSystemTests.php
index aa279e5..662c988 100644
--- a/plugins/CoreConsole/Commands/DevelopmentSyncProcessedSystemTests.php
+++ b/plugins/CoreConsole/Commands/DevelopmentSyncProcessedSystemTests.php
@@ -19,7 +19,7 @@ use Piwik\Plugin\ConsoleCommand;
 
 class DevelopmentSyncProcessedSystemTests extends ConsoleCommand
 {
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled();
     }
diff --git a/plugins/CoreConsole/Commands/GeneratePluginBase.php b/plugins/CoreConsole/Commands/GeneratePluginBase.php
index 681207e..ef4cb5d 100644
--- a/plugins/CoreConsole/Commands/GeneratePluginBase.php
+++ b/plugins/CoreConsole/Commands/GeneratePluginBase.php
@@ -26,7 +26,7 @@ abstract class GeneratePluginBase extends ConsoleCommand
         $this->throwErrorIfNotGitInstalled();
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled();
     }
diff --git a/plugins/CoreConsole/Commands/GetSegmentSql.php b/plugins/CoreConsole/Commands/GetSegmentSql.php
index 2f7372d..38ed6f4 100644
--- a/plugins/CoreConsole/Commands/GetSegmentSql.php
+++ b/plugins/CoreConsole/Commands/GetSegmentSql.php
@@ -21,7 +21,7 @@ use Piwik\Site;
 
 class GetSegmentSql extends ConsoleCommand
 {
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled();
     }
diff --git a/plugins/CoreConsole/Commands/GitCommit.php b/plugins/CoreConsole/Commands/GitCommit.php
index b504f31..05367a6 100644
--- a/plugins/CoreConsole/Commands/GitCommit.php
+++ b/plugins/CoreConsole/Commands/GitCommit.php
@@ -17,7 +17,7 @@ use Piwik\SettingsPiwik;
  */
 class GitCommit extends ConsoleCommand
 {
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled() && SettingsPiwik::isGitDeployment();
     }
diff --git a/plugins/CoreConsole/Commands/GitPull.php b/plugins/CoreConsole/Commands/GitPull.php
index eed00c9..77223dc 100644
--- a/plugins/CoreConsole/Commands/GitPull.php
+++ b/plugins/CoreConsole/Commands/GitPull.php
@@ -16,7 +16,7 @@ use Piwik\SettingsPiwik;
  */
 class GitPull extends ConsoleCommand
 {
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return SettingsPiwik::isGitDeployment();
     }
diff --git a/plugins/CoreConsole/Commands/GitPush.php b/plugins/CoreConsole/Commands/GitPush.php
index 20ce9e6..f9af9d4 100644
--- a/plugins/CoreConsole/Commands/GitPush.php
+++ b/plugins/CoreConsole/Commands/GitPush.php
@@ -17,7 +17,7 @@ use Piwik\SettingsPiwik;
  */
 class GitPush extends ConsoleCommand
 {
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled() && SettingsPiwik::isGitDeployment();
     }
diff --git a/plugins/CoreUpdater/Commands/ConvertToUtf8mb4.php b/plugins/CoreUpdater/Commands/ConvertToUtf8mb4.php
index 102f425..1877657 100644
--- a/plugins/CoreUpdater/Commands/ConvertToUtf8mb4.php
+++ b/plugins/CoreUpdater/Commands/ConvertToUtf8mb4.php
@@ -34,7 +34,7 @@ class ConvertToUtf8mb4 extends ConsoleCommand
         $this->addNoValueOption('keep-tracking', null, 'Do not disable tracking while conversion is running');
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         $dbSettings   = new Db\Settings();
         $charset      = $dbSettings->getUsedCharset();
diff --git a/plugins/CoreUpdater/UpdateCommunication.php b/plugins/CoreUpdater/UpdateCommunication.php
index 3ff70ce..d7266e9 100644
--- a/plugins/CoreUpdater/UpdateCommunication.php
+++ b/plugins/CoreUpdater/UpdateCommunication.php
@@ -30,7 +30,7 @@ class UpdateCommunication
      *
      * @return bool
      */
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         $isEnabled = (bool) Config::getInstance()->General['enable_update_communication'];
 
diff --git a/plugins/CoreVue/Commands/Build.php b/plugins/CoreVue/Commands/Build.php
index 54abb28..93d968f 100644
--- a/plugins/CoreVue/Commands/Build.php
+++ b/plugins/CoreVue/Commands/Build.php
@@ -33,7 +33,7 @@ class Build extends ConsoleCommand
         $this->addNoValueOption('print-build-command');
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return \Piwik\Development::isEnabled();
     }
diff --git a/plugins/CoreVue/Commands/BuildPolyfill.php b/plugins/CoreVue/Commands/BuildPolyfill.php
index cbcee7c..51a0d5f 100644
--- a/plugins/CoreVue/Commands/BuildPolyfill.php
+++ b/plugins/CoreVue/Commands/BuildPolyfill.php
@@ -21,7 +21,7 @@ class BuildPolyfill extends ConsoleCommand
         $this->addNoValueOption('clear-webpack-cache');
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return \Piwik\Development::isEnabled();
     }
diff --git a/plugins/DBStats/Reports/Base.php b/plugins/DBStats/Reports/Base.php
index 5469b09..356633d 100644
--- a/plugins/DBStats/Reports/Base.php
+++ b/plugins/DBStats/Reports/Base.php
@@ -19,7 +19,7 @@ use Piwik\Plugins\DBStats\DBStats;
 
 abstract class Base extends \Piwik\Plugin\Report
 {
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Piwik::hasUserSuperUserAccess();
     }
diff --git a/plugins/Ecommerce/Reports/Base.php b/plugins/Ecommerce/Reports/Base.php
index ddf3e94..8e4029f 100644
--- a/plugins/Ecommerce/Reports/Base.php
+++ b/plugins/Ecommerce/Reports/Base.php
@@ -24,7 +24,7 @@ abstract class Base extends Report
         $this->onlineGuideUrl = Url::addCampaignParametersToMatomoLink('https://matomo.org/docs/ecommerce-analytics/');
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         $idSite = Common::getRequestVar('idSite', false, 'int');
 
diff --git a/plugins/Ecommerce/Widgets/ProductsByDimension.php b/plugins/Ecommerce/Widgets/ProductsByDimension.php
index 3b87f4d..fe4e6c2 100644
--- a/plugins/Ecommerce/Widgets/ProductsByDimension.php
+++ b/plugins/Ecommerce/Widgets/ProductsByDimension.php
@@ -21,7 +21,7 @@ class ProductsByDimension extends WidgetContainerConfig
     protected $categoryId = 'Goals_Ecommerce';
     protected $subcategoryId = 'Goals_Products';
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         $idSite = Common::getRequestVar('idSite', false, 'int');
 
diff --git a/plugins/ExampleReport/Reports/GetExampleReport.php b/plugins/ExampleReport/Reports/GetExampleReport.php
index 7bbe971..e10e626 100644
--- a/plugins/ExampleReport/Reports/GetExampleReport.php
+++ b/plugins/ExampleReport/Reports/GetExampleReport.php
@@ -99,7 +99,7 @@ class GetExampleReport extends Base
      * limit the audience by overwriting this method.
      *
      * @return bool
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Piwik::hasUserSuperUserAccess()
     }
diff --git a/plugins/GeoIp2/Commands/ConvertRegionCodesToIso.php b/plugins/GeoIp2/Commands/ConvertRegionCodesToIso.php
index e9743fe..6a45555 100644
--- a/plugins/GeoIp2/Commands/ConvertRegionCodesToIso.php
+++ b/plugins/GeoIp2/Commands/ConvertRegionCodesToIso.php
@@ -28,7 +28,7 @@ class ConvertRegionCodesToIso extends ConsoleCommand
         $this->setDescription("Convert FIPS region codes saved by GeoIP legacy provider to ISO.");
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return (LocationProvider::getCurrentProvider() instanceof GeoIp2);
     }
diff --git a/plugins/GeoIp2/Commands/UpdateRegionCodes.php b/plugins/GeoIp2/Commands/UpdateRegionCodes.php
index 5a25019..90ff4d6 100644
--- a/plugins/GeoIp2/Commands/UpdateRegionCodes.php
+++ b/plugins/GeoIp2/Commands/UpdateRegionCodes.php
@@ -46,7 +46,7 @@ class UpdateRegionCodes extends ConsoleCommand
         $this->addOptionalValueOption('db-ip-csv', null, 'Uses the provided DB IP CSV database to iterate over all included IP ranges.');
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled();
     }
@@ -146,7 +146,7 @@ class UpdateRegionCodes extends ConsoleCommand
 //         'current' => <bool> indicating if the iso code is currently used
 //     ]
 // ]
-return 
+return
 CONTENT;
 
         $content .= var_export($newRegions, true) . ';';
diff --git a/plugins/Intl/Commands/GenerateIntl.php b/plugins/Intl/Commands/GenerateIntl.php
index d915a3c..e4d0805 100644
--- a/plugins/Intl/Commands/GenerateIntl.php
+++ b/plugins/Intl/Commands/GenerateIntl.php
@@ -28,7 +28,7 @@ class GenerateIntl extends ConsoleCommand
 {
     public $CLDRVersion = "43.0.0";
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled();
     }
diff --git a/plugins/LanguagesManager/Commands/TranslationBase.php b/plugins/LanguagesManager/Commands/TranslationBase.php
index 6f4ebe8..5cc09e0 100644
--- a/plugins/LanguagesManager/Commands/TranslationBase.php
+++ b/plugins/LanguagesManager/Commands/TranslationBase.php
@@ -16,7 +16,7 @@ use Piwik\Plugin\ConsoleCommand;
  */
 abstract class TranslationBase extends ConsoleCommand
 {
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled();
     }
diff --git a/plugins/Live/Reports/GetLastVisitsDetails.php b/plugins/Live/Reports/GetLastVisitsDetails.php
index 994e8e1..0a35e1b 100644
--- a/plugins/Live/Reports/GetLastVisitsDetails.php
+++ b/plugins/Live/Reports/GetLastVisitsDetails.php
@@ -46,7 +46,7 @@ class GetLastVisitsDetails extends Base
         $widgetsList->addWidgetConfig($widget);
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Live::isVisitorLogEnabled();
     }
diff --git a/plugins/Login/Security/BruteForceDetection.php b/plugins/Login/Security/BruteForceDetection.php
index 38647eb..a06efd0 100644
--- a/plugins/Login/Security/BruteForceDetection.php
+++ b/plugins/Login/Security/BruteForceDetection.php
@@ -55,7 +55,7 @@ class BruteForceDetection
         $this->model = $model;
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         $dbSchemaVersion = $this->updater->getCurrentComponentVersion('core');
         if ($dbSchemaVersion && version_compare($dbSchemaVersion, '3.8.0') == -1) {
@@ -100,7 +100,7 @@ class BruteForceDetection
         $sql = 'SELECT ip_address
                 FROM `' . $this->tablePrefixed . '`
                 WHERE attempted_at > ?
-                GROUP BY ip_address 
+                GROUP BY ip_address
                 HAVING count(*) > ' . (int) $this->maxLogAttempts;
         $rows = Db::get()->fetchAll($sql, array($this->getStartTimeRange()));
 
diff --git a/plugins/Marketplace/UpdateCommunication.php b/plugins/Marketplace/UpdateCommunication.php
index a31006a..412d147 100644
--- a/plugins/Marketplace/UpdateCommunication.php
+++ b/plugins/Marketplace/UpdateCommunication.php
@@ -40,7 +40,7 @@ class UpdateCommunication
      *
      * @return bool
      */
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         if (!self::canBeEnabled()) {
             return false;
diff --git a/plugins/Monolog/Formatter/ConsoleFormatter.php b/plugins/Monolog/Formatter/ConsoleFormatter.php
index 07028c6..0691b2f 100644
--- a/plugins/Monolog/Formatter/ConsoleFormatter.php
+++ b/plugins/Monolog/Formatter/ConsoleFormatter.php
@@ -9,14 +9,120 @@
 
 namespace Piwik\Plugins\Monolog\Formatter;
 
-use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter as SymfonyConsoleFormatter;
+use Monolog\Formatter\FormatterInterface;
+use Monolog\Level;
 use Monolog\LogRecord;
+use Symfony\Component\Console\Formatter\OutputFormatter;
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Cloner\Stub;
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+use Symfony\Component\VarDumper\Dumper\CliDumper;
 
-class ConsoleFormatter extends SymfonyConsoleFormatter
+/**
+ * Formats incoming records for console output by coloring them depending on log level.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ * @author Tobias Schultze <http://tobion.de>
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ */
+class ConsoleFormatter implements FormatterInterface
 {
+    public const SIMPLE_FORMAT = "%datetime% %start_tag%%level_name%%end_tag% <comment>[%channel%]</> %message%%context%%extra%\n";
+    public const SIMPLE_DATE = 'H:i:s';
+
+    private const LEVEL_COLOR_MAP = [
+        Level::Debug->value => 'fg=white',
+        Level::Info->value => 'fg=green',
+        Level::Notice->value => 'fg=blue',
+        Level::Warning->value => 'fg=cyan',
+        Level::Error->value => 'fg=yellow',
+        Level::Critical->value => 'fg=red',
+        Level::Alert->value => 'fg=red',
+        Level::Emergency->value => 'fg=white;bg=red',
+    ];
+
+    private array $options;
+    private VarCloner $cloner;
+
+    /**
+     * @var resource|null
+     */
+    private $outputBuffer;
+
+    private CliDumper $dumper;
+
+    /**
+     * Available options:
+     *   * format: The format of the outputted log string. The following placeholders are supported: %datetime%, %start_tag%, %level_name%, %end_tag%, %channel%, %message%, %context%, %extra%;
+     *   * date_format: The format of the outputted date string;
+     *   * colors: If true, the log string contains ANSI code to add color;
+     *   * multiline: If false, "context" and "extra" are dumped on one line.
+     */
+    public function __construct(array $options = [])
+    {
+        $this->options = array_replace([
+            'format' => self::SIMPLE_FORMAT,
+            'date_format' => self::SIMPLE_DATE,
+            'colors' => true,
+            'multiline' => false,
+            'level_name_format' => '%-9s',
+            'ignore_empty_context_and_extra' => true,
+        ], $options);
+
+        if (class_exists(VarCloner::class)) {
+            $this->cloner = new VarCloner();
+            $this->cloner->addCasters([
+                '*' => $this->castObject(...),
+            ]);
+
+            $this->outputBuffer = fopen('php://memory', 'r+');
+            if ($this->options['multiline']) {
+                $output = $this->outputBuffer;
+            } else {
+                $output = $this->echoLine(...);
+            }
+
+            $this->dumper = new CliDumper($output, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR);
+        }
+    }
+
+    public function formatBatch(array $records): mixed
+    {
+        foreach ($records as $key => $record) {
+            $records[$key] = $this->format($record);
+        }
+
+        return $records;
+    }
+
     public function format(LogRecord $record): mixed
     {
-        $formatted = parent::format($record);
+        $record = $this->replacePlaceHolder($record);
+
+        if (!$this->options['ignore_empty_context_and_extra'] || $record->context) {
+            $context = $record->context;
+            $context = ($this->options['multiline'] ? "\n" : ' ').$this->dumpData($context);
+        } else {
+            $context = '';
+        }
+
+        if (!$this->options['ignore_empty_context_and_extra'] || $record->extra) {
+            $extra = $record->extra;
+            $extra = ($this->options['multiline'] ? "\n" : ' ').$this->dumpData($extra);
+        } else {
+            $extra = '';
+        }
+
+        $formatted = strtr($this->options['format'], [
+            '%datetime%' => $record->datetime->format($this->options['date_format']),
+            '%start_tag%' => \sprintf('<%s>', self::LEVEL_COLOR_MAP[$record->level->value]),
+            '%level_name%' => \sprintf($this->options['level_name_format'], $record->level->getName()),
+            '%end_tag%' => '</>',
+            '%channel%' => $record->channel,
+            '%message%' => $this->replacePlaceHolder($record)->message,
+            '%context%' => $context,
+            '%extra%' => $extra,
+        ]);
 
         foreach ($record->extra as $var => $val) {
             if (false !== strpos($formatted, '%extra.' . $var . '%')) {
@@ -27,4 +133,79 @@ class ConsoleFormatter extends SymfonyConsoleFormatter
 
         return $formatted;
     }
+
+    /**
+     * @internal
+     */
+    public function echoLine(string $line, int $depth, string $indentPad): void
+    {
+        if (-1 !== $depth) {
+            fwrite($this->outputBuffer, $line);
+        }
+    }
+
+    /**
+     * @internal
+     */
+    public function castObject(mixed $v, array $a, Stub $s, bool $isNested): array
+    {
+        if ($this->options['multiline']) {
+            return $a;
+        }
+
+        if ($isNested && !$v instanceof \DateTimeInterface) {
+            $s->cut = -1;
+            $a = [];
+        }
+
+        return $a;
+    }
+
+    private function replacePlaceHolder(LogRecord $record): LogRecord
+    {
+        $message = $record->message;
+
+        if (!str_contains($message, '{')) {
+            return $record;
+        }
+
+        $context = $record->context;
+
+        $replacements = [];
+        foreach ($context as $k => $v) {
+            // Remove quotes added by the dumper around string.
+            $v = trim($this->dumpData($v, false), '"');
+            $v = OutputFormatter::escape($v);
+            $replacements['{'.$k.'}'] = \sprintf('<comment>%s</>', $v);
+        }
+
+        return $record->with(message: strtr($message, $replacements));
+    }
+
+    private function dumpData(mixed $data, ?bool $colors = null): string
+    {
+        if (!isset($this->dumper)) {
+            return '';
+        }
+
+        if (null === $colors) {
+            $this->dumper->setColors($this->options['colors']);
+        } else {
+            $this->dumper->setColors($colors);
+        }
+
+        if (\is_array($data) && ($data['data'] ?? null) instanceof Data) {
+            $data = $data['data'];
+        } elseif (!$data instanceof Data) {
+            $data = $this->cloner->cloneVar($data);
+        }
+        $data = $data->withRefHandles(false);
+        $this->dumper->dump($data);
+
+        $dump = stream_get_contents($this->outputBuffer, -1, 0);
+        rewind($this->outputBuffer);
+        ftruncate($this->outputBuffer, 0);
+
+        return rtrim($dump);
+    }
 }
diff --git a/plugins/TestRunner/Commands/SyncScreenshots.php b/plugins/TestRunner/Commands/SyncScreenshots.php
index 673ab29..3f1aada 100644
--- a/plugins/TestRunner/Commands/SyncScreenshots.php
+++ b/plugins/TestRunner/Commands/SyncScreenshots.php
@@ -37,7 +37,7 @@ class SyncScreenshots extends ConsoleCommand
         parent::__construct();
     }
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return Development::isEnabled();
     }
diff --git a/plugins/VisitsSummary/Widgets/Index.php b/plugins/VisitsSummary/Widgets/Index.php
index dd2b955..f003d67 100644
--- a/plugins/VisitsSummary/Widgets/Index.php
+++ b/plugins/VisitsSummary/Widgets/Index.php
@@ -20,7 +20,7 @@ class Index extends \Piwik\Widget\WidgetContainerConfig
     protected $id = 'VisitOverviewWithGraph';
     protected $isWidgetizable = true;
 
-    public function isEnabled()
+    public function isEnabled(): bool
     {
         return ReportsProvider::factory('VisitsSummary', 'get')->isEnabled();
     }
