From aa3994489e12831435d995ac629de08a7a4ef9d3 Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Wed, 15 Nov 2017 12:11:01 +0100 Subject: [PATCH 1/7] [FrameworkBundle] [DI] Automatically add "setLogger" method call. --- .../Compiler/LoggerAwarePass.php | 50 +++++++++++++++++++ .../FrameworkBundle/FrameworkBundle.php | 2 + .../Compiler/LoggerAwarePassTest.php | 50 +++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php new file mode 100644 index 0000000000000..343569553479b --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Psr\Log\LoggerAwareInterface; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Automatically add setLogger method call to any service that implements Psr\Log\LoggerAwareInterface. + * + * @see http://www.php-fig.org/psr/psr-3/ + * + * @author Gary PEGEOT + */ +class LoggerAwarePass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('logger') && !$container->hasAlias('logger')) { + return; + } + + $reference = new Reference('logger'); + + foreach ($container->getDefinitions() as $definition) { + if (!class_exists($definition->getClass())) { + continue; + } + + $refl = new \ReflectionClass($definition->getClass()); + if ($refl->implementsInterface(LoggerAwareInterface::class) && !$definition->hasMethodCall('setLogger')) { + $definition->addMethodCall('setLogger', [$reference]); + } + } + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 0cebbc3f49ae0..fbf791e52569b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -18,6 +18,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolClearerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPrunerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggerAwarePass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; @@ -114,6 +115,7 @@ public function build(ContainerBuilder $container) $this->addCompilerPassIfExists($container, FormPass::class); $container->addCompilerPass(new WorkflowGuardListenerPass()); $container->addCompilerPass(new ResettableServicePass()); + $container->addCompilerPass(new LoggerAwarePass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php new file mode 100644 index 0000000000000..d9d6f0ebb7930 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerInterface; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggerAwarePass; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Unit tests for App\DependencyInjection\Compiler\LoggerAwarePass + * + * @author Gary PEGEOT + */ +class LoggerAwarePassTest extends TestCase +{ + /** + * @covers \Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggerAwarePass::process() + */ + public function testProcess() + { + $container = new ContainerBuilder(); + $container->register('logger', LoggerInterface::class); + + $definition = $container->register('foo', get_class($this->createMock(LoggerAwareInterface::class))); + $container->register('bar', 'stdClass'); + $this->assertFalse( + $definition->hasMethodCall('setLogger'), + 'Service should not have "setLogger" method call before Pass execution.' + ); + + (new LoggerAwarePass())->process($container); + + $this->assertTrue($definition->hasMethodCall('setLogger'), 'Service should have "setLogger" method call.'); + $this->assertFalse( + $container->findDefinition('bar')->hasMethodCall('setLogger'), + '"bar" service should not be affected' + ); + } +} From 1eb32d365d0af00e2648b5a66339313e58bc478c Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Wed, 15 Nov 2017 12:13:46 +0100 Subject: [PATCH 2/7] Fix email --- .../Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php index d9d6f0ebb7930..ff0f7a7ba3401 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php @@ -20,7 +20,7 @@ /** * Unit tests for App\DependencyInjection\Compiler\LoggerAwarePass * - * @author Gary PEGEOT + * @author Gary PEGEOT */ class LoggerAwarePassTest extends TestCase { From 0d415d32e58c9ad4ec27f0e5400d9afc74127ce6 Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Wed, 15 Nov 2017 12:19:27 +0100 Subject: [PATCH 3/7] Fabbot.io fixes. --- .../DependencyInjection/Compiler/LoggerAwarePass.php | 2 +- .../Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php index 343569553479b..4e0eaf86e308a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php @@ -43,7 +43,7 @@ public function process(ContainerBuilder $container) $refl = new \ReflectionClass($definition->getClass()); if ($refl->implementsInterface(LoggerAwareInterface::class) && !$definition->hasMethodCall('setLogger')) { - $definition->addMethodCall('setLogger', [$reference]); + $definition->addMethodCall('setLogger', array($reference)); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php index ff0f7a7ba3401..6cfc1760d21f7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php @@ -18,7 +18,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; /** - * Unit tests for App\DependencyInjection\Compiler\LoggerAwarePass + * Unit tests for Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggerAwarePass. * * @author Gary PEGEOT */ From b4bc0dc4ae3d33f918539c82565d1f7f0dc6226a Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Wed, 15 Nov 2017 15:07:24 +0100 Subject: [PATCH 4/7] Disable for service without autoconfiguration enabled. --- .../DependencyInjection/Compiler/LoggerAwarePass.php | 2 +- .../DependencyInjection/Compiler/LoggerAwarePassTest.php | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php index 4e0eaf86e308a..743c834dbc663 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php @@ -37,7 +37,7 @@ public function process(ContainerBuilder $container) $reference = new Reference('logger'); foreach ($container->getDefinitions() as $definition) { - if (!class_exists($definition->getClass())) { + if (!class_exists($definition->getClass()) || !$definition->isAutoconfigured()) { continue; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php index 6cfc1760d21f7..c9fde146d972c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php @@ -33,7 +33,10 @@ public function testProcess() $container->register('logger', LoggerInterface::class); $definition = $container->register('foo', get_class($this->createMock(LoggerAwareInterface::class))); + $definition->setAutoconfigured(true); + $container->register('bar', 'stdClass'); + $container->register('not.autowired', LoggerInterface::class)->setAutoconfigured(false); $this->assertFalse( $definition->hasMethodCall('setLogger'), 'Service should not have "setLogger" method call before Pass execution.' @@ -42,9 +45,15 @@ public function testProcess() (new LoggerAwarePass())->process($container); $this->assertTrue($definition->hasMethodCall('setLogger'), 'Service should have "setLogger" method call.'); + $this->assertFalse( $container->findDefinition('bar')->hasMethodCall('setLogger'), '"bar" service should not be affected' ); + + $this->assertFalse( + $container->findDefinition('not.autowired')->hasMethodCall('setLogger'), + 'Not autoconfigured service should not be affected.' + ); } } From 4d167f894a71f6773fdaf00cdac537fd699518f7 Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Wed, 15 Nov 2017 15:19:24 +0100 Subject: [PATCH 5/7] Small fixes --- .../DependencyInjection/Compiler/LoggerAwarePass.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php index 743c834dbc663..74369a23fd0c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php @@ -37,12 +37,13 @@ public function process(ContainerBuilder $container) $reference = new Reference('logger'); foreach ($container->getDefinitions() as $definition) { - if (!class_exists($definition->getClass()) || !$definition->isAutoconfigured()) { + $class = $definition->getClass(); + if (!class_exists($class) || !$definition->isAutoconfigured() || $definition->hasMethodCall('setLogger')) { continue; } - $refl = new \ReflectionClass($definition->getClass()); - if ($refl->implementsInterface(LoggerAwareInterface::class) && !$definition->hasMethodCall('setLogger')) { + $refl = $container->getReflectionClass($class); + if ($refl->implementsInterface(LoggerAwareInterface::class)) { $definition->addMethodCall('setLogger', array($reference)); } } From 6a3a5bc71b35edb58350289159bc690a5ed3b6eb Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Wed, 15 Nov 2017 15:39:14 +0100 Subject: [PATCH 6/7] Use reflection class instead of class_exists --- .../DependencyInjection/Compiler/LoggerAwarePass.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php index 74369a23fd0c9..4b9927e63fb4f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php @@ -37,13 +37,13 @@ public function process(ContainerBuilder $container) $reference = new Reference('logger'); foreach ($container->getDefinitions() as $definition) { - $class = $definition->getClass(); - if (!class_exists($class) || !$definition->isAutoconfigured() || $definition->hasMethodCall('setLogger')) { + $class = $container->getReflectionClass($definition->getClass(), true); + + if (!$class || !$definition->isAutoconfigured() || $definition->hasMethodCall('setLogger')) { continue; } - $refl = $container->getReflectionClass($class); - if ($refl->implementsInterface(LoggerAwareInterface::class)) { + if ($class->implementsInterface(LoggerAwareInterface::class)) { $definition->addMethodCall('setLogger', array($reference)); } } From 35404a98e39103798b25566286c29107de797945 Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Thu, 16 Nov 2017 11:14:39 +0100 Subject: [PATCH 7/7] Add tag for LoggerAwareInterface, add tagged services CP. --- .../DependencyInjection/Compiler/LoggerAwarePass.php | 11 ++++------- .../DependencyInjection/FrameworkExtension.php | 3 +++ .../Compiler/LoggerAwarePassTest.php | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php index 4b9927e63fb4f..59292bc98dcc1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggerAwarePass.php @@ -36,14 +36,11 @@ public function process(ContainerBuilder $container) $reference = new Reference('logger'); - foreach ($container->getDefinitions() as $definition) { - $class = $container->getReflectionClass($definition->getClass(), true); + foreach (\array_keys($container->findTaggedServiceIds('logger.aware')) as $id) { + $definition = $container->findDefinition($id); + $class = $container->getReflectionClass($definition->getClass()); - if (!$class || !$definition->isAutoconfigured() || $definition->hasMethodCall('setLogger')) { - continue; - } - - if ($class->implementsInterface(LoggerAwareInterface::class)) { + if (!$definition->hasMethodCall('setLogger') && $class && $class->implementsInterface(LoggerAwareInterface::class)) { $definition->addMethodCall('setLogger', array($reference)); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 1dcf47d9330a7..3966bd65e1a77 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; use Doctrine\Common\Annotations\Reader; +use Psr\Log\LoggerAwareInterface; use Symfony\Bridge\Monolog\Processor\DebugProcessor; use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand; use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand; @@ -294,6 +295,8 @@ public function load(array $configs, ContainerBuilder $container) ->addTag('kernel.event_subscriber'); $container->registerForAutoconfiguration(ResettableInterface::class) ->addTag('kernel.reset', array('method' => 'reset')); + $container->registerForAutoconfiguration(LoggerAwareInterface::class) + ->addTag('logger.aware'); $container->registerForAutoconfiguration(PropertyListExtractorInterface::class) ->addTag('property_info.list_extractor'); $container->registerForAutoconfiguration(PropertyTypeExtractorInterface::class) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php index c9fde146d972c..f1a89992845aa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggerAwarePassTest.php @@ -32,14 +32,14 @@ public function testProcess() $container = new ContainerBuilder(); $container->register('logger', LoggerInterface::class); - $definition = $container->register('foo', get_class($this->createMock(LoggerAwareInterface::class))); - $definition->setAutoconfigured(true); + $definition = $container->register('foo', get_class($this->createMock(LoggerAwareInterface::class))) + ->addTag('logger.aware'); $container->register('bar', 'stdClass'); - $container->register('not.autowired', LoggerInterface::class)->setAutoconfigured(false); + $container->register('not.autowired', LoggerInterface::class); $this->assertFalse( $definition->hasMethodCall('setLogger'), - 'Service should not have "setLogger" method call before Pass execution.' + 'Service should not have "setLogger" method call yet.' ); (new LoggerAwarePass())->process($container);