diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 286a154..6079c26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,9 +13,7 @@ jobs: php: ['8.4'] sf_version: ['8.0.*'] include: - - php: '8.0' - sf_version: '5.4.*' - - php: '8.1' + - php: '8.2' sf_version: '6.4.*' - php: '8.2' sf_version: '7.4.*' @@ -49,7 +47,7 @@ jobs: - name: Set up PHP uses: shivammathur/setup-php@2.7.0 with: - php-version: 8.0 + php-version: 8.2 coverage: pcov - name: Checkout code @@ -60,5 +58,5 @@ jobs: - name: Run tests env: - PHP_VERSION: '8.0' + PHP_VERSION: '8.2' run: ./vendor/bin/phpunit -v --coverage-text diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index bddfbbd..ec99f91 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -26,7 +26,7 @@ jobs: - name: Set up PHP uses: shivammathur/setup-php@2.7.0 with: - php-version: 8.0 + php-version: 8.2 - name: Download dependencies run: composer update --no-interaction --prefer-dist --no-progress --no-suggest --dev diff --git a/composer.json b/composer.json index 87e724d..1b9d560 100644 --- a/composer.json +++ b/composer.json @@ -22,9 +22,10 @@ } }, "require": { - "php": ">=8.0", - "bref/bref": "^1.2|^2.0|^3.0", + "php": ">=8.2", + "bref/bref": "^2.0|^3", "bref/monolog-bridge": "^1.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0|^8.0", "symfony/filesystem": "^5.4|^6.0|^7.0|^8.0", "symfony/http-kernel": "^5.4|^6.0|^7.0|^8.0", "symfony/psr-http-message-bridge": "^2.1|^6.4|^7.0|^8.0", @@ -34,11 +35,17 @@ "mnapoli/hard-mode": "^0.3.0", "phpstan/phpstan": "^1.3", "phpunit/phpunit": "^8.5.22", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/framework-bundle": "^5.4|^6.0|^7.0", - "symfony/phpunit-bridge": "^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0" + "symfony/config": "^5.4|^6.0|^7.0|^8.0", + "symfony/framework-bundle": "^5.4|^6.0|^7.0|^8.0", + "symfony/phpunit-bridge": "^6.0|^7.0|^8.0", + "symfony/process": "^5.4|^6.0|^7.0|^8.0" + }, + "extra": { + "symfony": { + "bundles": { + "Bref\\SymfonyBridge\\BrefBundle": ["all"] + } + } }, "config": { "sort-packages": true, diff --git a/src/BrefBundle.php b/src/BrefBundle.php new file mode 100644 index 0000000..8d0ca73 --- /dev/null +++ b/src/BrefBundle.php @@ -0,0 +1,14 @@ +addCompilerPass(new CloudWatchMonologFormatterPass); + } +} diff --git a/src/CloudWatchMonologFormatterPass.php b/src/CloudWatchMonologFormatterPass.php new file mode 100644 index 0000000..1ad25f4 --- /dev/null +++ b/src/CloudWatchMonologFormatterPass.php @@ -0,0 +1,41 @@ +has('bref.cloudwatch_formatter')) { + $container->register('bref.cloudwatch_formatter', CloudWatchFormatter::class); + } + + $formatterRef = new Reference('bref.cloudwatch_formatter'); + + foreach ($container->getDefinitions() as $id => $definition) { + if (! str_starts_with($id, 'monolog.handler.')) { + continue; + } + + // Don't override formatter if explicitly set by the user + foreach ($definition->getMethodCalls() as [$method]) { + if ($method === 'setFormatter') { + continue 2; + } + } + + $definition->addMethodCall('setFormatter', [$formatterRef]); + } + } +} diff --git a/tests/Unit/CloudWatchMonologFormatterPassTest.php b/tests/Unit/CloudWatchMonologFormatterPassTest.php new file mode 100644 index 0000000..3e5f9a1 --- /dev/null +++ b/tests/Unit/CloudWatchMonologFormatterPassTest.php @@ -0,0 +1,76 @@ +register('monolog.handler.main', StreamHandler::class); + $container->register('monolog.handler.console', StreamHandler::class); + + $pass = new CloudWatchMonologFormatterPass; + $pass->process($container); + + self::assertTrue($container->has('bref.cloudwatch_formatter')); + self::assertSame(CloudWatchFormatter::class, $container->getDefinition('bref.cloudwatch_formatter')->getClass()); + + // Both handlers should have the formatter set + $mainCalls = $container->getDefinition('monolog.handler.main')->getMethodCalls(); + self::assertCount(1, $mainCalls); + self::assertSame('setFormatter', $mainCalls[0][0]); + self::assertInstanceOf(Reference::class, $mainCalls[0][1][0]); + self::assertSame('bref.cloudwatch_formatter', (string) $mainCalls[0][1][0]); + + $consoleCalls = $container->getDefinition('monolog.handler.console')->getMethodCalls(); + self::assertCount(1, $consoleCalls); + self::assertSame('setFormatter', $consoleCalls[0][0]); + } + + public function testDoesNotOverrideExplicitFormatter() + { + $container = new ContainerBuilder; + + $handler = $container->register('monolog.handler.main', StreamHandler::class); + $handler->addMethodCall('setFormatter', [new Reference('my_custom_formatter')]); + + $pass = new CloudWatchMonologFormatterPass; + $pass->process($container); + + // Should still have only the original formatter + $calls = $container->getDefinition('monolog.handler.main')->getMethodCalls(); + self::assertCount(1, $calls); + self::assertSame('my_custom_formatter', (string) $calls[0][1][0]); + } + + public function testDoesNotTouchNonMonologServices() + { + $container = new ContainerBuilder; + $container->register('app.my_service', StreamHandler::class); + + $pass = new CloudWatchMonologFormatterPass; + $pass->process($container); + + self::assertEmpty($container->getDefinition('app.my_service')->getMethodCalls()); + } + + public function testDoesNothingWhenNoMonologHandlersExist() + { + $container = new ContainerBuilder; + $container->register('app.my_service', StreamHandler::class); + + $pass = new CloudWatchMonologFormatterPass; + $pass->process($container); + + // Formatter service should still be registered (it's harmless) + self::assertTrue($container->has('bref.cloudwatch_formatter')); + } +}