From 5713142aa35f63cc82659f3f04f4212786afc81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 23 Sep 2017 14:20:05 +0100 Subject: [PATCH 1/4] [HttpKernel][FrameworkBundle] Add a minimalist default PSR-3 logger --- composer.json | 3 + .../Bundle/FrameworkBundle/CHANGELOG.md | 1 + .../FrameworkBundle/FrameworkBundle.php | 2 + .../Console/Logger/ConsoleLogger.php | 2 + src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + .../DependencyInjection/LoggerPass.php | 45 ++++ .../Component/HttpKernel/Log/Logger.php | 99 ++++++++ .../DependencyInjection/LoggerPassTest.php | 68 ++++++ .../HttpKernel/Tests/Log/LoggerTest.php | 212 ++++++++++++++++++ .../Component/HttpKernel/composer.json | 3 + 10 files changed, 436 insertions(+) create mode 100644 src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php create mode 100644 src/Symfony/Component/HttpKernel/Log/Logger.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php diff --git a/composer.json b/composer.json index 00039be77db9b..11c9efb6261c4 100644 --- a/composer.json +++ b/composer.json @@ -101,6 +101,9 @@ "symfony/security-acl": "~2.8|~3.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0" }, + "provide": { + "psr/log-implementation": "1.0.0" + }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", "phpdocumentor/type-resolver": "<0.2.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 0c7581e7c0b7d..b76987b6c1291 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * Always register a minimalist logger that writes in `stderr` * Deprecated `profiler.matcher` option * Added support for `EventSubscriberInterface` on `MicroKernelTrait` * Removed `doctrine/cache` from the list of required dependencies in `composer.json` diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index c6936d35be83d..06dc51f653922 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\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; @@ -119,6 +120,7 @@ public function build(ContainerBuilder $container) $this->addCompilerPassIfExists($container, FormPass::class); $container->addCompilerPass(new WorkflowGuardListenerPass()); $container->addCompilerPass(new ResettableServicePass()); + $container->addCompilerPass(new LoggerPass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); diff --git a/src/Symfony/Component/Console/Logger/ConsoleLogger.php b/src/Symfony/Component/Console/Logger/ConsoleLogger.php index 27c9b6b278e17..d7bcdfad003f5 100644 --- a/src/Symfony/Component/Console/Logger/ConsoleLogger.php +++ b/src/Symfony/Component/Console/Logger/ConsoleLogger.php @@ -101,6 +101,8 @@ public function log($level, $message, array $context = array()) /** * Returns true when any messages have been logged at error levels. + * + * @return bool */ public function hasErrored() { diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 66e3b38e25ce6..76a2f39735fd5 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added a minimalist PSR-3 `Logger` class that writes in `stderr` * made kernels implementing `CompilerPassInterface` able to process the container * deprecated bundle inheritance * added `RebootableInterface` and implemented it in `Kernel` diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php new file mode 100644 index 0000000000000..2cffb99b321ec --- /dev/null +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use Symfony\Component\HttpKernel\Log\Logger; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Registers the default logger if necessary. + * + * @author Kévin Dunglas + */ +class LoggerPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $alias = $container->setAlias(LoggerInterface::class, 'logger'); + $alias->setPublic(false); + + if ($container->has('logger')) { + return; + } + + $loggerDefinition = $container->register('logger', Logger::class); + $loggerDefinition->setPublic(false); + if ($container->getParameter('kernel.debug')) { + $loggerDefinition->addArgument(LogLevel::DEBUG); + } + } +} diff --git a/src/Symfony/Component/HttpKernel/Log/Logger.php b/src/Symfony/Component/HttpKernel/Log/Logger.php new file mode 100644 index 0000000000000..08120f02a2183 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Log/Logger.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Log; + +use Psr\Log\AbstractLogger; +use Psr\Log\InvalidArgumentException; +use Psr\Log\LogLevel; + +/** + * Minimalist PSR-3 logger designed to write in stderr or any other stream. + * + * @internal + * + * @author Kévin Dunglas + */ +final class Logger extends AbstractLogger +{ + private static $levels = array( + LogLevel::DEBUG => 0, + LogLevel::INFO => 1, + LogLevel::NOTICE => 2, + LogLevel::WARNING => 3, + LogLevel::ERROR => 4, + LogLevel::CRITICAL => 5, + LogLevel::ALERT => 6, + LogLevel::EMERGENCY => 7, + ); + + private $minLevelIndex; + private $formatter; + private $handle; + + public function __construct($minLevel = LogLevel::WARNING, $output = 'php://stderr', callable $formatter = null) + { + if (!isset(self::$levels[$minLevel])) { + throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $minLevel)); + } + + $this->minLevelIndex = self::$levels[$minLevel]; + $this->formatter = $formatter ?: array($this, 'format'); + if (false === $this->handle = @fopen($output, 'a')) { + throw new InvalidArgumentException(sprintf('Unable to open "%s".', $output)); + } + } + + /** + * {@inheritdoc} + */ + public function log($level, $message, array $context = array()) + { + if (!isset(self::$levels[$level])) { + throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); + } + + if (self::$levels[$level] < $this->minLevelIndex) { + return; + } + + $formatter = $this->formatter; + fwrite($this->handle, $formatter($level, $message, $context)); + } + + /** + * @param string $level + * @param string $message + * + * @return string + */ + private function format($level, $message, array $context) + { + if (false !== strpos($message, '{')) { + $replacements = array(); + foreach ($context as $key => $val) { + if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { + $replacements["{{$key}}"] = $val; + } elseif ($val instanceof \DateTimeInterface) { + $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); + } elseif (\is_object($val)) { + $replacements["{{$key}}"] = '[object '.\get_class($val).']'; + } else { + $replacements["{{$key}}"] = '['.\gettype($val).']'; + } + } + + $message = strtr($message, $replacements); + } + + return sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message).\PHP_EOL; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php new file mode 100644 index 0000000000000..d018929b2a830 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; +use Symfony\Component\HttpKernel\Log\Logger; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Kévin Dunglas + */ +class LoggerPassTest extends TestCase +{ + public function testAlwaysSetAutowiringAlias() + { + $container = new ContainerBuilder(); + $container->register('logger', 'Foo'); + + (new LoggerPass())->process($container); + + $this->assertFalse($container->getAlias(LoggerInterface::class)->isPublic()); + } + + public function testDoNotOverrideExistingLogger() + { + $container = new ContainerBuilder(); + $container->register('logger', 'Foo'); + + (new LoggerPass())->process($container); + + $this->assertSame('Foo', $container->getDefinition('logger')->getClass()); + } + + public function testRegisterLogger() + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', false); + + (new LoggerPass())->process($container); + + $definition = $container->getDefinition('logger'); + $this->assertSame(Logger::class, $definition->getClass()); + $this->assertFalse($definition->isPublic()); + } + + public function testSetMinLevelWhenDebugging() + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', true); + + (new LoggerPass())->process($container); + + $definition = $container->getDefinition('logger'); + $this->assertSame(LogLevel::DEBUG, $definition->getArgument(0)); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php new file mode 100644 index 0000000000000..952a5ff9eddc9 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Log; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use Symfony\Component\HttpKernel\Log\Logger; + +/** + * @author Kévin Dunglas + * @author Jordi Boggiano + */ +class LoggerTest extends TestCase +{ + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @var string + */ + private $tmpFile; + + protected function setUp() + { + $this->tmpFile = sys_get_temp_dir().'/log'; + $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile); + } + + protected function tearDown() + { + unlink($this->tmpFile); + } + + private function assertLogsMatch(array $expected, array $given) + { + foreach ($given as $k => $line) { + if (!preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\+[0-9]{2}:[0-9]{2} '.preg_quote($expected[$k]).'/', $line)) { + throw new \Exception("$line do not match expected pattern $expected[$k]"); + } + } + } + + /** + * Return the log messages in order. + * + * @return string[] + */ + public function getLogs() + { + return file($this->tmpFile, FILE_IGNORE_NEW_LINES); + } + + public function testImplements() + { + $this->assertInstanceOf(LoggerInterface::class, $this->logger); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $this->logger->{$level}($message, array('user' => 'Bob')); + $this->logger->log($level, $message, array('user' => 'Bob')); + + $expected = array( + "[$level] message of level $level with context: Bob", + "[$level] message of level $level with context: Bob", + ); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages() + { + return array( + LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), + LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), + LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), + LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), + LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), + LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), + LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), + LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), + ); + } + + public function testLogLevelDisabled() + { + $this->logger = new Logger(LogLevel::INFO, $this->tmpFile); + + $this->logger->debug('test', array('user' => 'Bob')); + $this->logger->log(LogLevel::DEBUG, 'test', array('user' => 'Bob')); + + // Will always be true, but asserts than an exception isn't thrown + $this->assertLogsMatch(array(), $this->getLogs()); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidLevel() + { + $this->logger->log('invalid level', 'Foo'); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidMinLevel() + { + new Logger('invalid'); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testInvalidOutput() + { + new Logger(LogLevel::DEBUG, '/'); + } + + public function testContextReplacement() + { + $logger = $this->logger; + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('[info] {Message {nothing} Bob Bar a}'); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + if (method_exists($this, 'createPartialMock')) { + $dummy = $this->createPartialMock(DummyTest::class, array('__toString')); + } else { + $dummy = $this->getMock(DummyTest::class, array('__toString')); + } + $dummy->expects($this->atLeastOnce()) + ->method('__toString') + ->will($this->returnValue('DUMMY')); + + $this->logger->warning($dummy); + + $expected = array('[warning] DUMMY'); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function testContextCanContainAnything() + { + $context = array( + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => array('with object' => new DummyTest()), + 'object' => new \DateTime(), + 'resource' => fopen('php://memory', 'r'), + ); + + $this->logger->warning('Crazy context data', $context); + + $expected = array('[warning] Crazy context data'); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $logger = $this->logger; + $logger->warning('Random message', array('exception' => 'oops')); + $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + + $expected = array( + '[warning] Random message', + '[critical] Uncaught Exception!', + ); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function testFormatter() + { + $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile, function ($level, $message, $context) { + return json_encode(array('level' => $level, 'message' => $message, 'context' => $context)).\PHP_EOL; + }); + + $this->logger->error('An error', array('foo' => 'bar')); + $this->logger->warning('A warning', array('baz' => 'bar')); + $this->assertSame(array( + '{"level":"error","message":"An error","context":{"foo":"bar"}}', + '{"level":"warning","message":"A warning","context":{"baz":"bar"}}', + ), $this->getLogs()); + } +} + +class DummyTest +{ + public function __toString() + { + } +} diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 3c051bb5f7b33..9032522eb2f4e 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -40,6 +40,9 @@ "symfony/var-dumper": "~3.3|~4.0", "psr/cache": "~1.0" }, + "provide": { + "psr/log-implementation": "1.0.0" + }, "conflict": { "symfony/config": "<2.8", "symfony/dependency-injection": "<3.4", From 9dde784f49fc6a887304b315f7249828291c7a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 29 Sep 2017 00:29:53 +0200 Subject: [PATCH 2/4] Remove final and @internal. Change pass priority. --- src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php | 2 +- src/Symfony/Component/HttpKernel/Log/Logger.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 06dc51f653922..aab3ac6d594cf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -86,6 +86,7 @@ public function build(ContainerBuilder $container) { parent::build($container); + $container->addCompilerPass(new LoggerPass()); $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass()); $container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING); $container->addCompilerPass(new RoutingResolverPass()); @@ -120,7 +121,6 @@ public function build(ContainerBuilder $container) $this->addCompilerPassIfExists($container, FormPass::class); $container->addCompilerPass(new WorkflowGuardListenerPass()); $container->addCompilerPass(new ResettableServicePass()); - $container->addCompilerPass(new LoggerPass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); diff --git a/src/Symfony/Component/HttpKernel/Log/Logger.php b/src/Symfony/Component/HttpKernel/Log/Logger.php index 08120f02a2183..ed7e49b79fa2b 100644 --- a/src/Symfony/Component/HttpKernel/Log/Logger.php +++ b/src/Symfony/Component/HttpKernel/Log/Logger.php @@ -18,11 +18,9 @@ /** * Minimalist PSR-3 logger designed to write in stderr or any other stream. * - * @internal - * * @author Kévin Dunglas */ -final class Logger extends AbstractLogger +class Logger extends AbstractLogger { private static $levels = array( LogLevel::DEBUG => 0, From 87df1f1ce141cf1c2f243d6d757ac92bdc7c4a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 29 Sep 2017 00:41:03 +0200 Subject: [PATCH 3/4] Add @param. Change pass priority --- src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php | 2 +- src/Symfony/Component/HttpKernel/Log/Logger.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index aab3ac6d594cf..fc314ead31ea4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -86,7 +86,7 @@ public function build(ContainerBuilder $container) { parent::build($container); - $container->addCompilerPass(new LoggerPass()); + $container->addCompilerPass(new LoggerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass()); $container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING); $container->addCompilerPass(new RoutingResolverPass()); diff --git a/src/Symfony/Component/HttpKernel/Log/Logger.php b/src/Symfony/Component/HttpKernel/Log/Logger.php index ed7e49b79fa2b..cf20ca258a322 100644 --- a/src/Symfony/Component/HttpKernel/Log/Logger.php +++ b/src/Symfony/Component/HttpKernel/Log/Logger.php @@ -70,6 +70,7 @@ public function log($level, $message, array $context = array()) /** * @param string $level * @param string $message + * @param array $context * * @return string */ From e5e9eb8da91a1bdf20494de5e81c94c9f43e8cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 29 Sep 2017 07:57:20 +0200 Subject: [PATCH 4/4] Fix tests --- composer.json | 4 +--- .../Bundle/FrameworkBundle/FrameworkBundle.php | 2 +- .../Component/HttpKernel/Tests/Log/LoggerTest.php | 14 +++++++------- src/Symfony/Component/HttpKernel/composer.json | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index 11c9efb6261c4..7b55e30efd330 100644 --- a/composer.json +++ b/composer.json @@ -101,9 +101,6 @@ "symfony/security-acl": "~2.8|~3.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0" }, - "provide": { - "psr/log-implementation": "1.0.0" - }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", "phpdocumentor/type-resolver": "<0.2.0", @@ -112,6 +109,7 @@ "provide": { "psr/cache-implementation": "1.0", "psr/container-implementation": "1.0", + "psr/log-implementation": "1.0", "psr/simple-cache-implementation": "1.0" }, "autoload": { diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index fc314ead31ea4..85569070f3c1e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -18,7 +18,6 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolClearerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPrunerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; -use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; @@ -32,6 +31,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass; use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass; use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; +use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass; use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; diff --git a/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php index 952a5ff9eddc9..ecf67af78c115 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php @@ -34,21 +34,21 @@ class LoggerTest extends TestCase protected function setUp() { - $this->tmpFile = sys_get_temp_dir().'/log'; + $this->tmpFile = sys_get_temp_dir().DIRECTORY_SEPARATOR.'log'; $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile); } protected function tearDown() { - unlink($this->tmpFile); + if (!@unlink($this->tmpFile)) { + file_put_contents($this->tmpFile, ''); + } } - private function assertLogsMatch(array $expected, array $given) + public static function assertLogsMatch(array $expected, array $given) { foreach ($given as $k => $line) { - if (!preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\+[0-9]{2}:[0-9]{2} '.preg_quote($expected[$k]).'/', $line)) { - throw new \Exception("$line do not match expected pattern $expected[$k]"); - } + self::assertThat(1 === preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[\+-][0-9]{2}:[0-9]{2} '.preg_quote($expected[$k]).'/', $line), self::isTrue(), "\"$line\" do not match expected pattern \"$expected[$k]\""); } } @@ -104,7 +104,7 @@ public function testLogLevelDisabled() $this->logger->log(LogLevel::DEBUG, 'test', array('user' => 'Bob')); // Will always be true, but asserts than an exception isn't thrown - $this->assertLogsMatch(array(), $this->getLogs()); + $this->assertSame(array(), $this->getLogs()); } /** diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 9032522eb2f4e..a372edb588601 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -41,7 +41,7 @@ "psr/cache": "~1.0" }, "provide": { - "psr/log-implementation": "1.0.0" + "psr/log-implementation": "1.0" }, "conflict": { "symfony/config": "<2.8",