Browse Source

Add a TextRenderer and integrate it into Debugger

Use this simple implementation as a proof-of-concept for how the new
rendering sub-system can replace existing features in Debugger
(eventually).
Mark Story 4 years ago
parent
commit
b497aff700

+ 26 - 2
src/Error/Debugger.php

@@ -31,6 +31,7 @@ use Cake\Error\Debug\ReferenceNode;
 use Cake\Error\Debug\ScalarNode;
 use Cake\Error\Debug\SpecialNode;
 use Cake\Error\Debug\TextFormatter;
+use Cake\Error\Renderer\TextRenderer;
 use Cake\Log\Log;
 use Cake\Utility\Hash;
 use Cake\Utility\Security;
@@ -111,6 +112,19 @@ class Debugger
     ];
 
     /**
+     * Mapping for error renderers.
+     *
+     * Error renderers are replacing output formatting with
+     * an object based system. Having Debugger handle and render errors
+     * will be deprecated and the new ErrorTrap system should be used instead.
+     *
+     * @array <string, class-string>
+     */
+    protected $renderers = [
+        'txt' => TextRenderer::class,
+    ];
+
+    /**
      * A map of editors to their link templates.
      *
      * @var array<string, string|callable>
@@ -443,7 +457,7 @@ class Debugger
                 continue;
             }
             if ($options['format'] === 'points' && $trace['file'] !== '[internal]') {
-                $back[] = ['file' => $trace['file'], 'line' => $trace['line']];
+                $back[] = ['file' => $trace['file'], 'line' => $trace['line'], 'reference' => $reference];
             } elseif ($options['format'] === 'array') {
                 $back[] = $trace;
             } else {
@@ -922,6 +936,16 @@ class Debugger
         ];
         $data += $defaults;
 
+        $outputFormat = $this->_outputFormat;
+        if (isset($this->renderers[$outputFormat])) {
+            $trace = static::trace(['start' => $data['start'], 'format' => 'points']);
+            $error = new PhpError($data['code'], $data['description'], $data['file'], $data['line'], $trace);
+            $renderer = new $this->renderers[$outputFormat]();
+            echo $renderer->render($error);
+
+            return;
+        }
+
         $files = static::trace(['start' => $data['start'], 'format' => 'points']);
         $code = '';
         $file = null;
@@ -956,7 +980,7 @@ class Debugger
 
         $data['trace'] = $trace;
         $data['id'] = 'cakeErr' . uniqid();
-        $tpl = $this->_templates[$this->_outputFormat] + $this->_templates['base'];
+        $tpl = $this->_templates[$outputFormat] + $this->_templates['base'];
 
         if (isset($tpl['links'])) {
             foreach ($tpl['links'] as $key => $val) {

+ 1 - 1
src/Error/PhpError.php

@@ -24,7 +24,7 @@ class PhpError
     /**
      * @var int
      */
-    private $level;
+    private $code;
 
     /**
      * @var string

+ 31 - 0
src/Error/Renderer/TextRenderer.php

@@ -0,0 +1,31 @@
+<?php
+declare(strict_types=1);
+
+namespace Cake\Error\Renderer;
+
+use Cake\Error\ErrorRendererInterface;
+use Cake\Error\PhpError;
+
+/**
+ * Plain text error rendering with a stack trace.
+ *
+ * Useful in CLI and log file contexts.
+ */
+class TextRenderer implements ErrorRendererInterface
+{
+    /**
+     * @inheritDoc
+     */
+    public function render(PhpError $error): string
+    {
+        return sprintf(
+            "%s: %s :: %s on line %s of %s\nTrace:\n%s",
+            $error->getLabel(),
+            $error->getCode(),
+            $error->getMessage(),
+            $error->getLine(),
+            $error->getFile(),
+            $error->getTraceAsString(),
+        );
+    }
+}

+ 26 - 0
tests/TestCase/Error/DebuggerTest.php

@@ -202,6 +202,32 @@ class DebuggerTest extends TestCase
     }
 
     /**
+     * Test plain text output format.
+     */
+    public function testOutputErrorText(): void
+    {
+        Debugger::setOutputFormat('txt');
+
+        ob_start();
+        $debugger = Debugger::getInstance();
+        $data = [
+            'level' => E_NOTICE,
+            'code' => E_NOTICE,
+            'file' => __FILE__,
+            'line' => __LINE__,
+            'description' => 'Error description',
+            'start' => 1,
+        ];
+        $debugger->outputError($data);
+        $result = ob_get_clean();
+
+        $this->assertStringContainsString('notice: 8 :: Error description', $result);
+        $this->assertStringContainsString("on line {$data['line']} of {$data['file']}", $result);
+        $this->assertStringContainsString('Trace:', $result);
+        $this->assertStringContainsString('Cake\Test\TestCase\Error\DebuggerTest::testOutputErrorText()', $result);
+    }
+
+    /**
      * Tests that changes in output formats using Debugger::output() change the templates used.
      */
     public function testAddFormat(): void