Skip to content

Commit d72133e

Browse files
bug #34619 Restores preview mode support for Html and Serializer error renderers (yceruto)
This PR was merged into the 4.4 branch. Discussion ---------- Restores preview mode support for Html and Serializer error renderers | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #34602 | License | MIT | Doc PR | - This restores the preview mode support for all error renderers. Commits ------- 38493b3 Add preview mode support for Html and Serializer error renderers
2 parents ac20382 + 38493b3 commit d72133e

File tree

5 files changed

+85
-25
lines changed

5 files changed

+85
-25
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/error_renderer.xml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,22 @@
66

77
<services>
88
<service id="error_handler.error_renderer.html" class="Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer">
9-
<argument>%kernel.debug%</argument>
9+
<argument type="service">
10+
<service>
11+
<factory class="Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer" method="isDebug" />
12+
<argument type="service" id="request_stack" />
13+
<argument>%kernel.debug%</argument>
14+
</service>
15+
</argument>
1016
<argument>%kernel.charset%</argument>
1117
<argument type="service" id="debug.file_link_formatter" on-invalid="null" />
1218
<argument>%kernel.project_dir%</argument>
13-
<argument type="service" id="request_stack" />
19+
<argument type="service">
20+
<service>
21+
<factory class="Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer" method="getAndCleanOutputBuffer" />
22+
<argument type="service" id="request_stack" />
23+
</service>
24+
</argument>
1425
<argument type="service" id="logger" on-invalid="null" />
1526
</service>
1627

src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@
163163
</service>
164164
</argument>
165165
<argument type="service" id="error_renderer.html" />
166+
<argument type="service">
167+
<service>
168+
<factory class="Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer" method="isDebug" />
169+
<argument type="service" id="request_stack" />
170+
<argument>%kernel.debug%</argument>
171+
</service>
172+
</argument>
166173
</service>
167174
</services>
168175
</container>

src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,28 @@ class HtmlErrorRenderer implements ErrorRendererInterface
3636
private $charset;
3737
private $fileLinkFormat;
3838
private $projectDir;
39-
private $requestStack;
39+
private $outputBuffer;
4040
private $logger;
4141

42-
public function __construct(bool $debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, RequestStack $requestStack = null, LoggerInterface $logger = null)
42+
/**
43+
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
44+
* @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it
45+
*/
46+
public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null)
4347
{
48+
if (!\is_bool($debug) && !\is_callable($debug)) {
49+
throw new \TypeError(sprintf('Argument 1 passed to %s() must be a boolean or a callable, %s given.', __METHOD__, \is_object($debug) ? \get_class($debug) : \gettype($debug)));
50+
}
51+
52+
if (!\is_string($outputBuffer) && !\is_callable($outputBuffer)) {
53+
throw new \TypeError(sprintf('Argument 5 passed to %s() must be a string or a callable, %s given.', __METHOD__, \is_object($outputBuffer) ? \get_class($outputBuffer) : \gettype($outputBuffer)));
54+
}
55+
4456
$this->debug = $debug;
4557
$this->charset = $charset ?: (ini_get('default_charset') ?: 'UTF-8');
4658
$this->fileLinkFormat = $fileLinkFormat ?: (ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'));
4759
$this->projectDir = $projectDir;
48-
$this->requestStack = $requestStack;
60+
$this->outputBuffer = $outputBuffer;
4961
$this->logger = $logger;
5062
}
5163

@@ -57,7 +69,7 @@ public function render(\Throwable $exception): FlattenException
5769
$exception = FlattenException::createFromThrowable($exception, null, [
5870
'Content-Type' => 'text/html; charset='.$this->charset,
5971
]);
60-
72+
6173
return $exception->setAsString($this->renderException($exception));
6274
}
6375

@@ -81,42 +93,61 @@ public function getStylesheet(): string
8193
return $this->include('assets/css/exception.css');
8294
}
8395

96+
public static function isDebug(RequestStack $requestStack, bool $debug): \Closure
97+
{
98+
return static function () use ($requestStack, $debug): bool {
99+
if (!$request = $requestStack->getCurrentRequest()) {
100+
return $debug;
101+
}
102+
103+
return $debug && $request->attributes->getBoolean('showException', true);
104+
};
105+
}
106+
107+
public static function getAndCleanOutputBuffer(RequestStack $requestStack): \Closure
108+
{
109+
return static function () use ($requestStack): string {
110+
if (!$request = $requestStack->getCurrentRequest()) {
111+
return '';
112+
}
113+
114+
$startObLevel = $request->headers->get('X-Php-Ob-Level', -1);
115+
116+
if (ob_get_level() <= $startObLevel) {
117+
return '';
118+
}
119+
120+
Response::closeOutputBuffers($startObLevel + 1, true);
121+
122+
return ob_get_clean();
123+
};
124+
}
125+
84126
private function renderException(FlattenException $exception, string $debugTemplate = 'views/exception_full.html.php'): string
85127
{
128+
$debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception);
86129
$statusText = $this->escape($exception->getStatusText());
87130
$statusCode = $this->escape($exception->getStatusCode());
88131

89-
if (!$this->debug) {
132+
if (!$debug) {
90133
return $this->include('views/error.html.php', [
91134
'statusText' => $statusText,
92135
'statusCode' => $statusCode,
93136
]);
94137
}
95138

96139
$exceptionMessage = $this->escape($exception->getMessage());
97-
$request = $this->requestStack ? $this->requestStack->getCurrentRequest() : null;
98140

99141
return $this->include($debugTemplate, [
100142
'exception' => $exception,
101143
'exceptionMessage' => $exceptionMessage,
102144
'statusText' => $statusText,
103145
'statusCode' => $statusCode,
104146
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
105-
'currentContent' => $request ? $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1)) : '',
147+
'currentContent' => \is_string($this->outputBuffer) ? $this->outputBuffer : ($this->outputBuffer)(),
106148
]);
107149
}
108150

109-
private function getAndCleanOutputBuffering(int $startObLevel): string
110-
{
111-
if (ob_get_level() <= $startObLevel) {
112-
return '';
113-
}
114-
115-
Response::closeOutputBuffers($startObLevel + 1, true);
116-
117-
return ob_get_clean();
118-
}
119-
120151
/**
121152
* Formats an array as a string.
122153
*/
@@ -312,7 +343,7 @@ private function include(string $name, array $context = []): string
312343
{
313344
extract($context, EXTR_SKIP);
314345
ob_start();
315-
include __DIR__ . '/../Resources/' .$name;
346+
include __DIR__.'/../Resources/'.$name;
316347

317348
return trim(ob_get_clean());
318349
}

src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,26 @@ class SerializerErrorRenderer implements ErrorRendererInterface
2626
private $serializer;
2727
private $format;
2828
private $fallbackErrorRenderer;
29+
private $debug;
2930

3031
/**
3132
* @param string|callable(FlattenException) $format The format as a string or a callable that should return it
33+
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
3234
*/
33-
public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null)
35+
public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false)
3436
{
3537
if (!\is_string($format) && !\is_callable($format)) {
3638
throw new \TypeError(sprintf('Argument 2 passed to %s() must be a string or a callable, %s given.', __METHOD__, \is_object($format) ? \get_class($format) : \gettype($format)));
3739
}
3840

41+
if (!\is_bool($debug) && !\is_callable($debug)) {
42+
throw new \TypeError(sprintf('Argument 4 passed to %s() must be a boolean or a callable, %s given.', __METHOD__, \is_object($debug) ? \get_class($debug) : \gettype($debug)));
43+
}
44+
3945
$this->serializer = $serializer;
4046
$this->format = $format;
4147
$this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer();
48+
$this->debug = $debug;
4249
}
4350

4451
/**
@@ -51,7 +58,10 @@ public function render(\Throwable $exception): FlattenException
5158
try {
5259
$format = \is_string($this->format) ? $this->format : ($this->format)($flattenException);
5360

54-
return $flattenException->setAsString($this->serializer->serialize($flattenException, $format, ['exception' => $exception]));
61+
return $flattenException->setAsString($this->serializer->serialize($flattenException, $format, [
62+
'exception' => $exception,
63+
'debug' => \is_bool($this->debug) ? $this->debug : ($this->debug)($exception),
64+
]));
5565
} catch (NotEncodableValueException $e) {
5666
return $this->fallbackErrorRenderer->render($exception);
5767
}

src/Symfony/Component/Serializer/Normalizer/ProblemNormalizer.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,15 @@ public function __construct(bool $debug = false, array $defaultContext = [])
4141
public function normalize($exception, $format = null, array $context = [])
4242
{
4343
$context += $this->defaultContext;
44+
$debug = $this->debug && $context['debug'] ?? true;
4445

4546
$data = [
4647
'type' => $context['type'],
4748
'title' => $context['title'],
4849
'status' => $context['status'] ?? $exception->getStatusCode(),
49-
'detail' => $this->debug ? $exception->getMessage() : $exception->getStatusText(),
50+
'detail' => $debug ? $exception->getMessage() : $exception->getStatusText(),
5051
];
51-
if ($this->debug) {
52+
if ($debug) {
5253
$data['class'] = $exception->getClass();
5354
$data['trace'] = $exception->getTrace();
5455
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy