Repository: symfony/monolog-bundle (php)

Issue:
Handle deprecation of the `actionLevel` argument in finger crossed strategies
Form Symfony 6, the `actionLevel` must be an inner strategy instead of plain old value / string / int.

To prevent the deprecation, when creating the definition of the bridge's strategy, we should probably wrap the action level in an inner strategy as is done in the bridges ?

See https://github.com/symfony/monolog-bridge/blob/5.x/Handler/FingersCrossed/HttpCodeActivationStrategy.php#L39-L44 and https://github.com/symfony/monolog-bridge/blob/5.x/Handler/FingersCrossed/NotFoundActivationStrategy.php#L39-L44

Pull request:
Use `ActivationStrategy` instead of `actionLevel` when available
Take over #336

Fixes #369 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0f015c..ae76144 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,6 @@
 ## 3.7.0 (xxxx-xx-xx)
 
+* Use `ActivationStrategy` instead of `actionLevel` when available 
 * Register resettable processors (`ResettableInterface`) for autoconfiguration (tag: `kernel.reset`)
 * Drop support for Symfony 3.4
 
diff --git a/DependencyInjection/MonologExtension.php b/DependencyInjection/MonologExtension.php
index 1a7c312..12a84dd 100644
--- a/DependencyInjection/MonologExtension.php
+++ b/DependencyInjection/MonologExtension.php
@@ -11,11 +11,13 @@
 
 namespace Symfony\Bundle\MonologBundle\DependencyInjection;
 
+use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
 use Monolog\Logger;
 use Monolog\Processor\ProcessorInterface;
 use Monolog\Handler\HandlerInterface;
 use Monolog\ResettableInterface;
 use Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy;
+use Symfony\Bridge\Monolog\Processor\SwitchUserTokenProcessor;
 use Symfony\Bridge\Monolog\Processor\TokenProcessor;
 use Symfony\Bridge\Monolog\Processor\WebProcessor;
 use Symfony\Bundle\FullStack;
@@ -399,6 +401,11 @@ class MonologExtension extends Extension
             $nestedHandlerId = $this->getHandlerId($handler['handler']);
             $this->markNestedHandler($nestedHandlerId);
 
+            $activation = $handler['action_level'];
+            if (class_exists(SwitchUserTokenProcessor::class)) {
+                $activation = new Definition(ErrorLevelActivationStrategy::class, [$activation]);
+            }
+
             if (isset($handler['activation_strategy'])) {
                 $activation = new Reference($handler['activation_strategy']);
             } elseif (!empty($handler['excluded_404s'])) {
@@ -408,7 +415,7 @@ class MonologExtension extends Extension
                 $activationDef = new Definition('Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy', [
                     new Reference('request_stack'),
                     $handler['excluded_404s'],
-                    $handler['action_level']
+                    $activation
                 ]);
                 $container->setDefinition($handlerId.'.not_found_strategy', $activationDef);
                 $activation = new Reference($handlerId.'.not_found_strategy');
@@ -419,12 +426,10 @@ class MonologExtension extends Extension
                 $activationDef = new Definition('Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy', [
                     new Reference('request_stack'),
                     $handler['excluded_http_codes'],
-                    $handler['action_level']
+                    $activation
                 ]);
                 $container->setDefinition($handlerId.'.http_code_strategy', $activationDef);
                 $activation = new Reference($handlerId.'.http_code_strategy');
-            } else {
-                $activation = $handler['action_level'];
             }
 
             $definition->setArguments([


Test patch:
diff --git a/Tests/DependencyInjection/FixtureMonologExtensionTest.php b/Tests/DependencyInjection/FixtureMonologExtensionTest.php
index 310a47c..a84cdf5 100644
--- a/Tests/DependencyInjection/FixtureMonologExtensionTest.php
+++ b/Tests/DependencyInjection/FixtureMonologExtensionTest.php
@@ -11,15 +11,36 @@
 
 namespace Symfony\Bundle\MonologBundle\Tests\DependencyInjection;
 
-use Symfony\Bundle\MonologBundle\DependencyInjection\MonologExtension;
+use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
+use Symfony\Bridge\Monolog\Processor\SwitchUserTokenProcessor;
 use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\LoggerChannelPass;
+use Symfony\Bundle\MonologBundle\DependencyInjection\MonologExtension;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\Reference;
 
 abstract class FixtureMonologExtensionTest extends DependencyInjectionTest
 {
+    /** @group legacy */
+    public function testLegacyLoadWithSeveralHandlers()
+    {
+        if (class_exists(SwitchUserTokenProcessor::class)) {
+            $this->markTestSkipped('Symfony MonologBridge < 5.2 is needed.');
+        }
+
+        $this->doTestLoadWithSeveralHandlers(\Monolog\Logger::ERROR);
+    }
+
     public function testLoadWithSeveralHandlers()
+    {
+        if (!class_exists(SwitchUserTokenProcessor::class)) {
+            $this->markTestSkipped('Symfony MonologBridge >= 5.2 is needed.');
+        }
+
+        $this->doTestLoadWithSeveralHandlers(new Definition(ErrorLevelActivationStrategy::class, [\Monolog\Logger::ERROR]));
+    }
+
+    private function doTestLoadWithSeveralHandlers($activation)
     {
         $container = $this->getContainer('multiple_handlers');
 
@@ -41,14 +62,33 @@ abstract class FixtureMonologExtensionTest extends DependencyInjectionTest
 
         $handler = $container->getDefinition('monolog.handler.main');
         $this->assertDICDefinitionClass($handler, 'Monolog\Handler\FingersCrossedHandler');
-        $this->assertDICConstructorArguments($handler, [new Reference('monolog.handler.nested'), \Monolog\Logger::ERROR, 0, true, true, \Monolog\Logger::NOTICE]);
+        $this->assertDICConstructorArguments($handler, [new Reference('monolog.handler.nested'), $activation, 0, true, true, \Monolog\Logger::NOTICE]);
 
         $handler = $container->getDefinition('monolog.handler.filtered');
         $this->assertDICDefinitionClass($handler, 'Monolog\Handler\FilterHandler');
         $this->assertDICConstructorArguments($handler, [new Reference('monolog.handler.nested2'), [\Monolog\Logger::WARNING, \Monolog\Logger::ERROR], \Monolog\Logger::EMERGENCY, true]);
     }
 
+    /** @group legacy */
+    public function testLegacyLoadWithOverwriting()
+    {
+        if (class_exists(SwitchUserTokenProcessor::class)) {
+            $this->markTestSkipped('Symfony MonologBridge < 5.2 is needed.');
+        }
+
+        $this->doTestLoadWithOverwriting(\Monolog\Logger::ERROR);
+    }
+
     public function testLoadWithOverwriting()
+    {
+        if (!class_exists(SwitchUserTokenProcessor::class)) {
+            $this->markTestSkipped('Symfony MonologBridge >= 5.2 is needed.');
+        }
+
+        $this->doTestLoadWithOverwriting(new Definition(ErrorLevelActivationStrategy::class, [\Monolog\Logger::ERROR]));
+    }
+
+    private function doTestLoadWithOverwriting($activation)
     {
         $container = $this->getContainer('overwriting');
 
@@ -69,7 +109,7 @@ abstract class FixtureMonologExtensionTest extends DependencyInjectionTest
 
         $handler = $container->getDefinition('monolog.handler.main');
         $this->assertDICDefinitionClass($handler, 'Monolog\Handler\FingersCrossedHandler');
-        $this->assertDICConstructorArguments($handler, [new Reference('monolog.handler.nested'), \Monolog\Logger::ERROR, 0, true, true, null]);
+        $this->assertDICConstructorArguments($handler, [new Reference('monolog.handler.nested'), $activation, 0, true, true, null]);
     }
 
     public function testLoadWithNewAtEnd()
diff --git a/Tests/DependencyInjection/MonologExtensionTest.php b/Tests/DependencyInjection/MonologExtensionTest.php
index fe40818..581be79 100644
--- a/Tests/DependencyInjection/MonologExtensionTest.php
+++ b/Tests/DependencyInjection/MonologExtensionTest.php
@@ -12,9 +12,11 @@
 namespace Symfony\Bundle\MonologBundle\Tests\DependencyInjection;
 
 use InvalidArgumentException;
+use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
 use Monolog\Handler\RollbarHandler;
 use Monolog\Logger;
 use Monolog\Processor\UidProcessor;
+use Symfony\Bridge\Monolog\Processor\SwitchUserTokenProcessor;
 use Symfony\Bundle\MonologBundle\DependencyInjection\MonologExtension;
 use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\LoggerChannelPass;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -495,8 +497,27 @@ class MonologExtensionTest extends DependencyInjectionTest
         $this->assertDICDefinitionMethodCallAt(1, $handler, 'setTag', ['foo,bar']);
     }
 
+    /** @group legacy */
+    public function testLegacyFingersCrossedHandlerWhenExcluded404sAreSpecified()
+    {
+        if (class_exists(SwitchUserTokenProcessor::class)) {
+            $this->markTestSkipped('Symfony MonologBridge < 5.2 is needed.');
+        }
+
+        $this->doTestFingersCrossedHandlerWhenExcluded404sAreSpecified(\Monolog\Logger::WARNING);
+    }
+
     /** @group legacy */
     public function testFingersCrossedHandlerWhenExcluded404sAreSpecified()
+    {
+        if (!class_exists(SwitchUserTokenProcessor::class)) {
+            $this->markTestSkipped('Symfony MonologBridge >= 5.2 is needed.');
+        }
+
+        $this->doTestFingersCrossedHandlerWhenExcluded404sAreSpecified(new Definition(ErrorLevelActivationStrategy::class, [\Monolog\Logger::WARNING]));
+    }
+
+    private function doTestFingersCrossedHandlerWhenExcluded404sAreSpecified($activation)
     {
         $container = $this->getContainer([['handlers' => [
             'main' => ['type' => 'fingers_crossed', 'handler' => 'nested', 'excluded_404s' => ['^/foo', '^/bar']],
@@ -514,14 +535,33 @@ class MonologExtensionTest extends DependencyInjectionTest
 
         $strategy = $container->getDefinition('monolog.handler.main.not_found_strategy');
         $this->assertDICDefinitionClass($strategy, 'Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy');
-        $this->assertDICConstructorArguments($strategy, [new Reference('request_stack'), ['^/foo', '^/bar'], \Monolog\Logger::WARNING]);
+        $this->assertDICConstructorArguments($strategy, [new Reference('request_stack'), ['^/foo', '^/bar'], $activation]);
 
         $handler = $container->getDefinition('monolog.handler.main');
         $this->assertDICDefinitionClass($handler, 'Monolog\Handler\FingersCrossedHandler');
         $this->assertDICConstructorArguments($handler, [new Reference('monolog.handler.nested'), new Reference('monolog.handler.main.not_found_strategy'), 0, true, true, null]);
     }
 
+    /** @group legacy */
+    public function testLegacyFingersCrossedHandlerWhenExcludedHttpCodesAreSpecified()
+    {
+        if (class_exists(SwitchUserTokenProcessor::class)) {
+            $this->markTestSkipped('Symfony MonologBridge < 5.2 is needed.');
+        }
+
+        $this->doTestFingersCrossedHandlerWhenExcludedHttpCodesAreSpecified(\Monolog\Logger::WARNING);
+    }
+
     public function testFingersCrossedHandlerWhenExcludedHttpCodesAreSpecified()
+    {
+        if (!class_exists(SwitchUserTokenProcessor::class)) {
+            $this->markTestSkipped('Symfony MonologBridge >= 5.2 is needed.');
+        }
+
+        $this->doTestFingersCrossedHandlerWhenExcludedHttpCodesAreSpecified(new Definition(ErrorLevelActivationStrategy::class, [\Monolog\Logger::WARNING]));
+    }
+
+    private function doTestFingersCrossedHandlerWhenExcludedHttpCodesAreSpecified($activation)
     {
         if (!class_exists('Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy')) {
             $this->markTestSkipped('Symfony Monolog 4.1+ is needed.');
@@ -554,7 +594,7 @@ class MonologExtensionTest extends DependencyInjectionTest
                 ['code' => 404, 'urls' => []],
                 ['code' => 405, 'urls' => ['^/foo', '^/bar']]
             ],
-            \Monolog\Logger::WARNING
+            $activation,
         ]);
 
         $handler = $container->getDefinition('monolog.handler.main');