Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Support for Symfony 4 #466

Merged
merged 1 commit into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ jobs:
php: [ '7.2', '7.3', '7.4', '8.0', '8.1' ]
monolog: [ '1.*', '2.*' ]
include:
- php: '7.1'
- php: '7.4'
deps: lowest
deprecations: max[self]=0
Expand Down
53 changes: 17 additions & 36 deletions DependencyInjection/Compiler/LoggerChannelPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,17 @@ public function process(ContainerBuilder $container)
}
$definition->setMethodCalls($calls);

if (\method_exists($definition, 'getBindings')) {
$binding = new BoundArgument(new Reference($loggerId));

// Mark the binding as used already, to avoid reporting it as unused if the service does not use a
// logger injected through the LoggerInterface alias.
$values = $binding->getValues();
$values[2] = true;
$binding->setValues($values);

$bindings = $definition->getBindings();
$bindings['Psr\Log\LoggerInterface'] = $binding;
$definition->setBindings($bindings);
}
$binding = new BoundArgument(new Reference($loggerId));

// Mark the binding as used already, to avoid reporting it as unused if the service does not use a
// logger injected through the LoggerInterface alias.
$values = $binding->getValues();
$values[2] = true;
$binding->setValues($values);

$bindings = $definition->getBindings();
$bindings['Psr\Log\LoggerInterface'] = $binding;
$definition->setBindings($bindings);
}
}

Expand Down Expand Up @@ -117,11 +115,9 @@ public function getChannels()
}

/**
* @param array $configuration
*
* @return array
*/
protected function processChannels($configuration)
protected function processChannels(?array $configuration)
{
if (null === $configuration) {
return $this->channels;
Expand All @@ -137,11 +133,9 @@ protected function processChannels($configuration)
/**
* Create new logger from the monolog.logger_prototype
*
* @param string $channel
* @param string $loggerId
* @param ContainerBuilder $container
* @return void
*/
protected function createLogger($channel, $loggerId, ContainerBuilder $container)
protected function createLogger(string $channel, string $loggerId, ContainerBuilder $container)
{
if (!in_array($channel, $this->channels)) {
$logger = new ChildDefinition('monolog.logger_prototype');
Expand All @@ -150,29 +144,16 @@ protected function createLogger($channel, $loggerId, ContainerBuilder $container
$this->channels[] = $channel;
}

// Allows only for Symfony 4.2+
if (\method_exists($container, 'registerAliasForArgument')) {
$parameterName = $channel . 'Logger';
$parameterName = $channel . 'Logger';

$container->registerAliasForArgument($loggerId, LoggerInterface::class, $parameterName);
}
$container->registerAliasForArgument($loggerId, LoggerInterface::class, $parameterName);
}

/**
* Creates a copy of a reference and alters the service ID.
*
* @param Reference $reference
* @param string $serviceId
*
* @return Reference
*/
private function changeReference(Reference $reference, $serviceId)
private function changeReference(Reference $reference, string $serviceId): Reference
{
if (method_exists($reference, 'isStrict')) {
// Stay compatible with Symfony 2
return new Reference($serviceId, $reference->getInvalidBehavior(), $reference->isStrict(false));
}

return new Reference($serviceId, $reference->getInvalidBehavior());
}
}
27 changes: 2 additions & 25 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ class Configuration implements ConfigurationInterface
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('monolog');
$rootNode = method_exists(TreeBuilder::class, 'getRootNode') ? $treeBuilder->getRootNode() : $treeBuilder->root('monolog');
$rootNode = $treeBuilder->getRootNode();

$handlers = $rootNode
->fixXmlConfig('channel')
Expand Down Expand Up @@ -602,7 +602,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
// console
->variableNode('console_formater_options')
->setDeprecated(...$this->getDeprecationMsg('"%path%.%node%" is deprecated, use "%path%.console_formatter_options" instead.', 3.7))
->setDeprecated('symfony/monolog-bundle', 3.7, '"%path%.%node%" is deprecated, use "%path%.console_formatter_options" instead.')
->validate()
->ifTrue(function ($v) {
return !is_array($v);
Expand Down Expand Up @@ -1135,27 +1135,4 @@ private function addChannelsSection(ArrayNodeDefinition $handerNode)
->end()
;
}

/**
* Returns the correct deprecation param's as an array for setDeprecated.
*
* Symfony/Config v5.1 introduces a deprecation notice when calling
* setDeprecation() with less than 3 args and the getDeprecation method was
* introduced at the same time. By checking if getDeprecation() exists,
* we can determine the correct param count to use when calling setDeprecated.
*
* @return array{0:string}|array{0:string, 1: numeric-string, string}
*/
private function getDeprecationMsg(string $message, string $version): array
{
if (method_exists(BaseNode::class, 'getDeprecation')) {
return [
'symfony/monolog-bundle',
$version,
$message,
];
}

return [$message];
}
}
50 changes: 18 additions & 32 deletions DependencyInjection/MonologExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\Log\DebugLoggerConfigurator;
use Symfony\Contracts\HttpClient\HttpClientInterface;

Expand All @@ -56,10 +55,6 @@ class MonologExtension extends Extension
*/
public function load(array $configs, ContainerBuilder $container)
{
if (class_exists(FullStack::class) && Kernel::MAJOR_VERSION < 5 && Logger::API >= 2) {
throw new \RuntimeException('Symfony 5 is required for Monolog 2 support. Please downgrade Monolog to version 1.');
}

$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);

Expand Down Expand Up @@ -107,29 +102,27 @@ public function load(array $configs, ContainerBuilder $container)

$container->setParameter('monolog.additional_channels', isset($config['channels']) ? $config['channels'] : []);

if (method_exists($container, 'registerForAutoconfiguration')) {
if (interface_exists(ProcessorInterface::class)) {
$container->registerForAutoconfiguration(ProcessorInterface::class)
->addTag('monolog.processor');
} else {
$container->registerForAutoconfiguration(WebProcessor::class)
->addTag('monolog.processor');
}
if (interface_exists(ResettableInterface::class)) {
$container->registerForAutoconfiguration(ResettableInterface::class)
->addTag('kernel.reset', ['method' => 'reset']);
}
$container->registerForAutoconfiguration(TokenProcessor::class)
if (interface_exists(ProcessorInterface::class)) {
$container->registerForAutoconfiguration(ProcessorInterface::class)
->addTag('monolog.processor');
if (interface_exists(HttpClientInterface::class)) {
$handlerAutoconfiguration = $container->registerForAutoconfiguration(HandlerInterface::class);
$handlerAutoconfiguration->setBindings($handlerAutoconfiguration->getBindings() + [
HttpClientInterface::class => new BoundArgument(new Reference('monolog.http_client'), false),
]);
}
} else {
$container->registerForAutoconfiguration(WebProcessor::class)
->addTag('monolog.processor');
}
if (interface_exists(ResettableInterface::class)) {
$container->registerForAutoconfiguration(ResettableInterface::class)
->addTag('kernel.reset', ['method' => 'reset']);
}
$container->registerForAutoconfiguration(TokenProcessor::class)
->addTag('monolog.processor');
if (interface_exists(HttpClientInterface::class)) {
$handlerAutoconfiguration = $container->registerForAutoconfiguration(HandlerInterface::class);
$handlerAutoconfiguration->setBindings($handlerAutoconfiguration->getBindings() + [
HttpClientInterface::class => new BoundArgument(new Reference('monolog.http_client'), false),
]);
}

if (80000 <= \PHP_VERSION_ID && method_exists($container, 'registerAttributeForAutoconfiguration')) {
if (80000 <= \PHP_VERSION_ID) {
$container->registerAttributeForAutoconfiguration(AsMonologProcessor::class, static function (ChildDefinition $definition, AsMonologProcessor $attribute, \Reflector $reflector): void {
$tagAttributes = get_object_vars($attribute);
if ($reflector instanceof \ReflectionMethod) {
Expand Down Expand Up @@ -431,9 +424,6 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
$container->setDefinition($handlerId.'.not_found_strategy', $activationDef);
$activation = new Reference($handlerId.'.not_found_strategy');
} elseif (!empty($handler['excluded_http_codes'])) {
if (!class_exists('Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy')) {
throw new \LogicException('"excluded_http_codes" cannot be used as your version of Monolog bridge does not support it.');
}
$activationDef = new Definition('Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy', [
new Reference('request_stack'),
$handler['excluded_http_codes'],
Expand Down Expand Up @@ -888,10 +878,6 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
]);
break;
case 'server_log':
if (!class_exists('Symfony\Bridge\Monolog\Handler\ServerLogHandler')) {
throw new \RuntimeException('The ServerLogHandler is not available. Please update "symfony/monolog-bridge" to 3.3.');
}

$definition->setArguments([
$handler['host'],
$handler['level'],
Expand Down
7 changes: 4 additions & 3 deletions MonologBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,22 @@
*/
class MonologBundle extends Bundle
{
/**
* @return void
*/
public function build(ContainerBuilder $container)
{
parent::build($container);

$container->addCompilerPass($channelPass = new LoggerChannelPass());
if (!class_exists('Symfony\Bridge\Monolog\Processor\DebugProcessor') || !class_exists('Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass')) {
$container->addCompilerPass(new DebugHandlerPass($channelPass));
}
$container->addCompilerPass(new FixEmptyLoggerPass($channelPass));
$container->addCompilerPass(new AddProcessorsPass());
$container->addCompilerPass(new AddSwiftMailerTransportPass());
}

/**
* @internal
* @return void
*/
public static function includeStacktraces(HandlerInterface $handler)
{
Expand Down
16 changes: 0 additions & 16 deletions Tests/DependencyInjection/Compiler/LoggerChannelPassTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ public function testProcess()

public function testTypeHintedAliasesExistForEachChannel()
{
if (!\method_exists(ContainerBuilder::class, 'registerAliasForArgument')) {
$this->markTestSkipped('Need DependencyInjection 4.2+ to register type-hinted aliases for channels.');
}

$container = $this->getContainer();
$expectedChannels = ['test', 'foo', 'bar', 'additional'];

Expand All @@ -81,10 +77,6 @@ public function testProcessSetters()

public function testAutowiredLoggerArgumentsAreReplacedWithChannelLogger()
{
if (!\method_exists('Symfony\Component\DependencyInjection\Definition', 'getBindings')) {
$this->markTestSkipped('Need DependencyInjection 3.4+ to autowire channel logger.');
}

$container = $this->getFunctionalContainer();

$dummyService = $container->register('dummy_service', 'Symfony\Bundle\MonologBundle\Tests\DependencyInjection\Compiler\DummyService')
Expand All @@ -99,10 +91,6 @@ public function testAutowiredLoggerArgumentsAreReplacedWithChannelLogger()

public function testAutowiredLoggerArgumentsAreReplacedWithChannelLoggerWhenAutoconfigured()
{
if (!\method_exists('Symfony\Component\DependencyInjection\Definition', 'getBindings')) {
$this->markTestSkipped('Need DependencyInjection 3.4+ to autowire channel logger.');
}

$container = $this->getFunctionalContainer();

$container->registerForAutoconfiguration('Symfony\Bundle\MonologBundle\Tests\DependencyInjection\Compiler\DummyService')
Expand All @@ -121,10 +109,6 @@ public function testAutowiredLoggerArgumentsAreReplacedWithChannelLoggerWhenAuto

public function testAutowiredLoggerArgumentsAreNotReplacedWithChannelLoggerIfLoggerArgumentIsConfiguredExplicitly()
{
if (!\method_exists('Symfony\Component\DependencyInjection\Definition', 'getBindings')) {
$this->markTestSkipped('Need DependencyInjection 3.4+ to autowire channel logger.');
}

$container = $this->getFunctionalContainer();

$dummyService = $container->register('dummy_service', 'Symfony\Bundle\MonologBundle\Tests\DependencyInjection\Compiler\DummyService')
Expand Down
44 changes: 2 additions & 42 deletions Tests/DependencyInjection/FixtureMonologExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,9 @@

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('ERROR');
}

public function testLoadWithSeveralHandlers()
{
if (!class_exists(SwitchUserTokenProcessor::class)) {
$this->markTestSkipped('Symfony MonologBridge >= 5.2 is needed.');
}

$this->doTestLoadWithSeveralHandlers(new Definition(ErrorLevelActivationStrategy::class, ['ERROR']));
}

private function doTestLoadWithSeveralHandlers($activation)
{
$activation = new Definition(ErrorLevelActivationStrategy::class, ['ERROR']);
$container = $this->getContainer('multiple_handlers');

$this->assertTrue($container->hasDefinition('monolog.logger'));
Expand Down Expand Up @@ -70,27 +52,9 @@ private function doTestLoadWithSeveralHandlers($activation)
$this->assertDICConstructorArguments($handler, [new Reference('monolog.handler.nested2'), ['WARNING', 'ERROR'], 'EMERGENCY', true]);
}

/** @group legacy */
public function testLegacyLoadWithOverwriting()
{
if (class_exists(SwitchUserTokenProcessor::class)) {
$this->markTestSkipped('Symfony MonologBridge < 5.2 is needed.');
}

$this->doTestLoadWithOverwriting('ERROR');
}

public function testLoadWithOverwriting()
{
if (!class_exists(SwitchUserTokenProcessor::class)) {
$this->markTestSkipped('Symfony MonologBridge >= 5.2 is needed.');
}

$this->doTestLoadWithOverwriting(new Definition(ErrorLevelActivationStrategy::class, ['ERROR']));
}

private function doTestLoadWithOverwriting($activation)
{
$activation = new Definition(ErrorLevelActivationStrategy::class, ['ERROR']);
$container = $this->getContainer('overwriting');

$this->assertTrue($container->hasDefinition('monolog.logger'));
Expand Down Expand Up @@ -202,10 +166,6 @@ public function testSingleEmailRecipient()

public function testServerLog()
{
if (!class_exists('Symfony\Bridge\Monolog\Handler\ServerLogHandler')) {
$this->markTestSkipped('The ServerLogHandler is not available.');
}

$container = $this->getContainer('server_log');

$this->assertEquals([
Expand Down