Просмотр исходного кода

Allow JsonFormatter maximum normalized depth and maximum number of items per level to be configured in the constructor.

Tom Rochette 8 лет назад
Родитель
Сommit
68cf3c69d1

+ 32 - 4
src/Monolog/Formatter/JsonFormatter.php

@@ -27,6 +27,8 @@ class JsonFormatter extends NormalizerFormatter
 
     protected $batchMode;
     protected $appendNewline;
+    protected $maxNormalizeDepth = 9;
+    protected $maxNormalizeItemCount = 1000;
 
     /**
      * @var bool
@@ -59,6 +61,32 @@ class JsonFormatter extends NormalizerFormatter
         return $this->appendNewline;
     }
 
+    /**
+     * The maximum number of normalization levels to go through
+     */
+    public function getMaxNormalizeDepth(): int
+    {
+        return $this->maxNormalizeDepth;
+    }
+
+    public function setMaxNormalizeDepth(int $maxNormalizeDepth): void
+    {
+        $this->maxNormalizeDepth = $maxNormalizeDepth;
+    }
+
+    /**
+     * The maximum number of items to normalize per level
+     */
+    public function getMaxNormalizeItemCount(): int
+    {
+        return $this->maxNormalizeItemCount;
+    }
+
+    public function setMaxNormalizeItemCount(int $maxNormalizeItemCount): void
+    {
+        $this->maxNormalizeItemCount = $maxNormalizeItemCount;
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -122,8 +150,8 @@ class JsonFormatter extends NormalizerFormatter
      */
     protected function normalize($data, int $depth = 0)
     {
-        if ($depth > 9) {
-            return 'Over 9 levels deep, aborting normalization';
+        if ($depth > $this->maxNormalizeDepth) {
+            return 'Over '.$this->maxNormalizeDepth.' levels deep, aborting normalization';
         }
 
         if (is_array($data) || $data instanceof \Traversable) {
@@ -131,8 +159,8 @@ class JsonFormatter extends NormalizerFormatter
 
             $count = 1;
             foreach ($data as $key => $value) {
-                if ($count++ >= 1000) {
-                    $normalized['...'] = 'Over 1000 items, aborting normalization';
+                if ($count++ >= $this->maxNormalizeItemCount) {
+                    $normalized['...'] = 'Over '.$this->maxNormalizeItemCount.' items, aborting normalization';
                     break;
                 }
                 $normalized[$key] = $this->normalize($value, $depth + 1);

+ 41 - 0
tests/Monolog/Formatter/JsonFormatterTest.php

@@ -110,6 +110,47 @@ class JsonFormatterTest extends TestCase
         $this->assertContextContainsFormattedException($formattedThrowable, $message);
     }
 
+    public function testMaxNormalizeDepth()
+    {
+        $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, true);
+        $formatter->setMaxNormalizeDepth(1);
+        $throwable = new \Error('Foo');
+
+        $message = $this->formatRecordWithExceptionInContext($formatter, $throwable);
+
+        $this->assertContextContainsFormattedException('"Over 1 levels deep, aborting normalization"', $message);
+    }
+
+    public function testMaxNormalizeItemCountWith0ItemsMax()
+    {
+        $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, true);
+        $formatter->setMaxNormalizeDepth(9);
+        $formatter->setMaxNormalizeItemCount(0);
+        $throwable = new \Error('Foo');
+
+        $message = $this->formatRecordWithExceptionInContext($formatter, $throwable);
+
+        $this->assertEquals(
+            '{"...":"Over 0 items, aborting normalization"}'."\n",
+            $message
+        );
+    }
+
+    public function testMaxNormalizeItemCountWith3ItemsMax()
+    {
+        $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, true);
+        $formatter->setMaxNormalizeDepth(9);
+        $formatter->setMaxNormalizeItemCount(3);
+        $throwable = new \Error('Foo');
+
+        $message = $this->formatRecordWithExceptionInContext($formatter, $throwable);
+
+        $this->assertEquals(
+            '{"level_name":"CRITICAL","channel":"core","...":"Over 3 items, aborting normalization"}'."\n",
+            $message
+        );
+    }
+
     /**
      * @param string $expected
      * @param string $actual