Skip to content

Commit e0b5fb2

Browse files
committed
bug symfony#31326 fix ConsoleFormatter - call to a member function format() on string (keksa)
This PR was merged into the 3.4 branch. Discussion ---------- fix ConsoleFormatter - call to a member function format() on string | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | maybe | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - The ConsoleFormatter crashes when there is not a DateTime object in `$record['datetime']`. As this parameter is not documented anywhere (i.e. `FormatterInterface` does not say it must be a DateTime object), I think the proper fix is to check if there is DateTimeInterface object and only call the `format` method then. We use a custom LogProcessor (https://symfony.com/doc/current/logging/processors.html) to add some extra data and format the DateTime in the `$record['datetime']`. We need to format the DateTime in the processor, because we use `JsonFormatter` in prod environment and it does not support changing the date format. We use `ConsoleFormatter` only in dev environment and as the processor is called before the formatter, we get the crash. There were no tests whatsoever for `ConsoleFormatter`, so I've added a basic one, that passes before and after, and another one that tests the crash (failed before, passed after). There is a theoretical BC break, as someone could have sent an object with a `format` method to the formatter and it would have worked, but I'm not sure if it's considered BC break by Symfony, please let me know, if it is. Commits ------- 6488328 fix ConsoleFormatter - call to a member function format() on string
2 parents 885d08c + 6488328 commit e0b5fb2

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ public function format(array $record)
133133
}
134134

135135
$formatted = strtr($this->options['format'], [
136-
'%datetime%' => $record['datetime']->format($this->options['date_format']),
136+
'%datetime%' => $record['datetime'] instanceof \DateTimeInterface
137+
? $record['datetime']->format($this->options['date_format'])
138+
: $record['datetime'],
137139
'%start_tag%' => sprintf('<%s>', $levelColor),
138140
'%level_name%' => sprintf('%-9s', $record['level_name']),
139141
'%end_tag%' => '</>',
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Monolog\Tests\Formatter;
13+
14+
use Monolog\Logger;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter;
17+
18+
class ConsoleFormatterTest extends TestCase
19+
{
20+
/**
21+
* @dataProvider providerFormatTests
22+
*/
23+
public function testFormat(array $record, $expectedMessage)
24+
{
25+
$formatter = new ConsoleFormatter();
26+
self::assertSame($expectedMessage, $formatter->format($record));
27+
}
28+
29+
/**
30+
* @return array
31+
*/
32+
public function providerFormatTests()
33+
{
34+
$currentDateTime = new \DateTime();
35+
36+
return [
37+
'record with DateTime object in datetime field' => [
38+
'record' => [
39+
'message' => 'test',
40+
'context' => [],
41+
'level' => Logger::WARNING,
42+
'level_name' => Logger::getLevelName(Logger::WARNING),
43+
'channel' => 'test',
44+
'datetime' => $currentDateTime,
45+
'extra' => [],
46+
],
47+
'expectedMessage' => sprintf(
48+
"%s <fg=cyan>WARNING </> <comment>[test]</> test\n",
49+
$currentDateTime->format(ConsoleFormatter::SIMPLE_DATE)
50+
),
51+
],
52+
'record with string in datetime field' => [
53+
'record' => [
54+
'message' => 'test',
55+
'context' => [],
56+
'level' => Logger::WARNING,
57+
'level_name' => Logger::getLevelName(Logger::WARNING),
58+
'channel' => 'test',
59+
'datetime' => '2019-01-01T00:42:00+00:00',
60+
'extra' => [],
61+
],
62+
'expectedMessage' => "2019-01-01T00:42:00+00:00 <fg=cyan>WARNING </> <comment>[test]</> test\n",
63+
],
64+
];
65+
}
66+
}

0 commit comments

Comments
 (0)