Przeglądaj źródła

Catch json_encode recursion error

Benjamin Grandfond 13 lat temu
rodzic
commit
0945fcdccb

+ 12 - 0
src/Monolog/Formatter/WildfireFormatter.php

@@ -54,16 +54,24 @@ class WildfireFormatter extends NormalizerFormatter
 
         $record = $this->normalize($record);
         $message = array('message' => $record['message']);
+        $handleError = false;
         if ($record['context']) {
             $message['context'] = $record['context'];
+            $handleError = true;
         }
         if ($record['extra']) {
             $message['extra'] = $record['extra'];
+            $handleError = true;
         }
         if (count($message) === 1) {
             $message = reset($message);
         }
 
+        // Handle json_encode recursion error
+        if ($handleError) {
+            set_error_handler(function () { });
+        }
+
         // Create JSON object describing the appearance of the message in the console
         $json = json_encode(array(
             array(
@@ -75,6 +83,10 @@ class WildfireFormatter extends NormalizerFormatter
             $message,
         ));
 
+        if ($handleError) {
+            restore_error_handler();
+        }
+
         // The message itself is a serialization of the above JSON object + it's length
         return sprintf(
             '%s|%s|',

+ 37 - 0
tests/Monolog/Formatter/WildfireFormatterTest.php

@@ -108,4 +108,41 @@ class WildfireFormatterTest extends \PHPUnit_Framework_TestCase
 
         $wildfire->formatBatch(array($record));
     }
+
+    /**
+     * Test issue #137 (https://github.com/Seldaek/monolog/pull/137)
+     */
+    public function testFormatWithObjectsInContext()
+    {
+        // Set up the recursion
+        $foo = new \stdClass();
+        $bar = new \stdClass();
+
+        $foo->bar = $bar;
+        $bar->foo = $foo;
+
+        $record = array(
+            'message'    => "foo",
+            'level'      => 300,
+            'channel'    => 'foo',
+            'context'    => array(
+                'stack'  => array(
+                    array($foo),
+                    array($bar),
+                ),
+            ),
+            'extra'      => array(),
+        );
+
+        // Set an error handler to assert that the error is not raised anymore
+        $that = $this;
+        set_error_handler(function ($level, $message, $file, $line, $context) use ($that) {
+           $that->fail("$message should not be raised anymore");
+        });
+
+        $wildfire = new WildfireFormatter();
+        $wildfire->format($record);
+
+        restore_error_handler();
+    }
 }