diff --git a/src/Monolog/Formatter/JsonFormatter.php b/src/Monolog/Formatter/JsonFormatter.php index ca3d7d27f..c1cf48dcd 100644 --- a/src/Monolog/Formatter/JsonFormatter.php +++ b/src/Monolog/Formatter/JsonFormatter.php @@ -188,6 +188,10 @@ protected function normalize(mixed $data, int $depth = 0): mixed return $data->__toString(); } + if (\get_class($data) === '__PHP_Incomplete_Class') { + return new \ArrayObject($data); + } + return $data; } diff --git a/src/Monolog/Handler/StreamHandler.php b/src/Monolog/Handler/StreamHandler.php index a87577c8d..f3e11c8c5 100644 --- a/src/Monolog/Handler/StreamHandler.php +++ b/src/Monolog/Handler/StreamHandler.php @@ -122,7 +122,9 @@ protected function write(LogRecord $record): void } $this->createDir($url); $this->errorMessage = null; - set_error_handler([$this, 'customErrorHandler']); + set_error_handler(function (...$args) { + return $this->customErrorHandler(...$args); + }); try { $stream = fopen($url, 'a'); if ($this->filePermission !== null) { @@ -193,7 +195,9 @@ private function createDir(string $url): void $dir = $this->getDirFromStream($url); if (null !== $dir && !is_dir($dir)) { $this->errorMessage = null; - set_error_handler([$this, 'customErrorHandler']); + set_error_handler(function (...$args) { + return $this->customErrorHandler(...$args); + }); $status = mkdir($dir, 0777, true); restore_error_handler(); if (false === $status && !is_dir($dir) && strpos((string) $this->errorMessage, 'File exists') === false) { diff --git a/tests/Monolog/Formatter/JsonFormatterTest.php b/tests/Monolog/Formatter/JsonFormatterTest.php index ebd4ae4d2..2d908e4de 100644 --- a/tests/Monolog/Formatter/JsonFormatterTest.php +++ b/tests/Monolog/Formatter/JsonFormatterTest.php @@ -274,6 +274,18 @@ public function testNormalizeHandleLargeArrays() $this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']); } + public function testCanNormalizeIncompleteObject(): void + { + $serialized = "O:17:\"Monolog\TestClass\":1:{s:23:\"\x00Monolog\TestClass\x00name\";s:4:\"test\";}"; + $object = unserialize($serialized); + + $formatter = new JsonFormatter(); + $record = $this->getRecord(context: ['object' => $object], datetime: new \DateTimeImmutable('2022-02-22 00:00:00')); + $result = $formatter->format($record); + + self::assertSame('{"message":"test","context":{"object":{"__PHP_Incomplete_Class_Name":"Monolog\\\\TestClass"}},"level":300,"level_name":"WARNING","channel":"test","datetime":"2022-02-22T00:00:00+00:00","extra":{}}'."\n", $result); + } + public function testEmptyContextAndExtraFieldsCanBeIgnored() { $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, true, true);