Skip to content

Commit 778b1de

Browse files
[ErrorHandler] Rewrite logic to dump exception properties and fix serializing FlattenException
1 parent cb1f52b commit 778b1de

File tree

4 files changed

+54
-29
lines changed

4 files changed

+54
-29
lines changed

ErrorRenderer/HtmlErrorRenderer.php

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use Symfony\Component\HttpFoundation\Response;
1818
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
1919
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
20-
use Symfony\Component\VarDumper\Cloner\VarCloner;
20+
use Symfony\Component\VarDumper\Cloner\Data;
2121
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
2222

2323
/**
@@ -69,7 +69,7 @@ public function render(\Throwable $exception): FlattenException
6969
$headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine();
7070
}
7171

72-
$exception = FlattenException::createFromThrowable($exception, null, $headers);
72+
$exception = FlattenException::createWithDataRepresentation($exception, null, $headers);
7373

7474
return $exception->setAsString($this->renderException($exception));
7575
}
@@ -149,21 +149,12 @@ private function renderException(FlattenException $exception, string $debugTempl
149149
]);
150150
}
151151

152-
private function dumpValue(mixed $value): string
152+
private function dumpValue(Data $value): string
153153
{
154-
$cloner = new VarCloner();
155-
$data = $cloner->cloneVar($value);
156-
157154
$dumper = new HtmlDumper();
158155
$dumper->setTheme('light');
159-
$dumper->setOutput($output = fopen('php://memory', 'r+'));
160-
$dumper->dump($data);
161-
162-
$dump = stream_get_contents($output, -1, 0);
163-
rewind($output);
164-
ftruncate($output, 0);
165156

166-
return $dump;
157+
return $dumper->dump($value, true);
167158
}
168159

169160
private function formatArgs(array $args): string

Exception/FlattenException.php

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
1515
use Symfony\Component\HttpFoundation\Response;
1616
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
17+
use Symfony\Component\VarDumper\Caster\Caster;
18+
use Symfony\Component\VarDumper\Cloner\Data;
19+
use Symfony\Component\VarDumper\Cloner\Stub;
20+
use Symfony\Component\VarDumper\Cloner\VarCloner;
1721

1822
/**
1923
* FlattenException wraps a PHP Error or Exception to be able to serialize it.
@@ -36,7 +40,7 @@ class FlattenException
3640
private string $file;
3741
private int $line;
3842
private ?string $asString = null;
39-
private array $properties = [];
43+
private Data $dataRepresentation;
4044

4145
public static function create(\Exception $exception, int $statusCode = null, array $headers = []): static
4246
{
@@ -78,14 +82,34 @@ public static function createFromThrowable(\Throwable $exception, int $statusCod
7882
$e->setPrevious(static::createFromThrowable($previous));
7983
}
8084

81-
if ((new \ReflectionClass($exception::class))->isUserDefined()) {
82-
$getProperties = \Closure::bind(fn (\Throwable $e) => get_object_vars($e), null, $exception::class);
83-
$properties = $getProperties($exception);
84-
unset($properties['message'], $properties['code'], $properties['file'], $properties['line']);
85-
$e->properties = $properties;
85+
return $e;
86+
}
87+
88+
public static function createWithDataRepresentation(\Throwable $throwable, int $statusCode = null, array $headers = [], VarCloner $cloner = null): static
89+
{
90+
$e = static::createFromThrowable($throwable, $statusCode, $headers);
91+
92+
static $defaultCloner;
93+
94+
if (!$cloner ??= $defaultCloner) {
95+
$cloner = $defaultCloner = new VarCloner();
96+
$cloner->addCasters([
97+
\Throwable::class => function (\Throwable $e, array $a, Stub $s, bool $isNested): array {
98+
if (!$isNested) {
99+
unset($a[Caster::PREFIX_PROTECTED.'message']);
100+
unset($a[Caster::PREFIX_PROTECTED.'code']);
101+
unset($a[Caster::PREFIX_PROTECTED.'file']);
102+
unset($a[Caster::PREFIX_PROTECTED.'line']);
103+
unset($a["\0Error\0trace"], $a["\0Exception\0trace"]);
104+
unset($a["\0Error\0previous"], $a["\0Exception\0previous"]);
105+
}
106+
107+
return $a;
108+
},
109+
]);
86110
}
87111

88-
return $e;
112+
return $e->setDataRepresentation($cloner->cloneVar($throwable));
89113
}
90114

91115
public function toArray(): array
@@ -96,7 +120,7 @@ public function toArray(): array
96120
'message' => $exception->getMessage(),
97121
'class' => $exception->getClass(),
98122
'trace' => $exception->getTrace(),
99-
'properties' => $exception->getProperties(),
123+
'data' => $exception->getDataRepresentation(),
100124
];
101125
}
102126

@@ -230,11 +254,6 @@ public function setCode(int|string $code): static
230254
return $this;
231255
}
232256

233-
public function getProperties(): array
234-
{
235-
return $this->properties;
236-
}
237-
238257
public function getPrevious(): ?self
239258
{
240259
return $this->previous;
@@ -319,6 +338,21 @@ public function setTrace(array $trace, ?string $file, ?int $line): static
319338
return $this;
320339
}
321340

341+
public function getDataRepresentation(): ?Data
342+
{
343+
return $this->dataRepresentation ?? null;
344+
}
345+
346+
/**
347+
* @return $this
348+
*/
349+
public function setDataRepresentation(Data $data): static
350+
{
351+
$this->dataRepresentation = $data;
352+
353+
return $this;
354+
}
355+
322356
private function flattenArgs(array $args, int $level = 0, int &$count = 0): array
323357
{
324358
$result = [];

Resources/views/traces.html.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
<p class="break-long-words trace-message"><?= $this->escape($exception['message']); ?></p>
2626
<?php } ?>
2727
</div>
28-
<?php if ($exception['properties']) { ?>
28+
<?php if (\count($exception['data'] ?? [])) { ?>
2929
<details class="exception-properties-wrapper">
3030
<summary>Show exception properties</summary>
3131
<div class="exception-properties">
32-
<?= $this->dumpValue($exception['properties']) ?>
32+
<?= $this->dumpValue($exception['data']) ?>
3333
</div>
3434
</details>
3535
<?php } ?>

Tests/Exception/FlattenExceptionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ public function testToArray(\Throwable $exception, string $expectedClass)
209209
'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123,
210210
'args' => [],
211211
]],
212-
'properties' => [],
212+
'data' => null,
213213
],
214214
], $flattened->toArray());
215215
}

0 commit comments

Comments
 (0)