Skip to content

Commit dafcc21

Browse files
committed
Added native ErrorRenderer as fallback system and deprecating templates
1 parent 22c73a9 commit dafcc21

File tree

19 files changed

+116
-35
lines changed

19 files changed

+116
-35
lines changed

src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,6 @@ public function testDefaultJsonLoginBadRequest()
7070

7171
$this->assertSame(400, $response->getStatusCode());
7272
$this->assertSame('application/json', $response->headers->get('Content-Type'));
73-
$this->assertArraySubset(['error' => ['code' => 400, 'message' => 'Bad Request']], json_decode($response->getContent(), true));
73+
$this->assertArraySubset(['title' => 'Bad Request', 'status' => 400, 'detail' => 'Invalid JSON.'], json_decode($response->getContent(), true));
7474
}
7575
}

src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/bundles.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,5 @@
1212
return [
1313
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
1414
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
15-
new Symfony\Bundle\TwigBundle\TwigBundle(),
1615
new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLoginBundle\JsonLoginBundle(),
1716
];

src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
imports:
2-
- { resource: ./../config/default.yml }
2+
- { resource: ./../config/framework.yml }
33

44
security:
55
encoders:

src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/custom_handlers.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
imports:
2-
- { resource: ./../config/default.yml }
2+
- { resource: ./../config/framework.yml }
33

44
security:
55
encoders:

src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@
1111

1212
namespace Symfony\Bundle\TwigBundle\Controller;
1313

14+
use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRenderer;
15+
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
16+
use Symfony\Component\ErrorHandler\ErrorRenderer\JsonErrorRenderer;
17+
use Symfony\Component\ErrorHandler\ErrorRenderer\TxtErrorRenderer;
18+
use Symfony\Component\ErrorHandler\ErrorRenderer\XmlErrorRenderer;
19+
use Symfony\Component\ErrorHandler\Exception\ErrorRendererNotFoundException;
1420
use Symfony\Component\ErrorHandler\Exception\FlattenException;
1521
use Symfony\Component\HttpFoundation\Request;
1622
use Symfony\Component\HttpFoundation\Response;
17-
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
1823
use Twig\Environment;
1924
use Twig\Error\LoaderError;
2025
use Twig\Loader\ExistsLoaderInterface;
@@ -30,15 +35,22 @@ class ExceptionController
3035
{
3136
protected $twig;
3237
protected $debug;
38+
private $errorRenderer;
3339

3440
/**
3541
* @param Environment $twig
3642
* @param bool $debug Show error (false) or exception (true) pages by default
3743
*/
38-
public function __construct(Environment $twig, bool $debug)
44+
public function __construct(Environment $twig, bool $debug, ErrorRenderer $errorRenderer = null)
3945
{
4046
$this->twig = $twig;
4147
$this->debug = $debug;
48+
$this->errorRenderer = $errorRenderer ?? new ErrorRenderer([
49+
new HtmlErrorRenderer($debug),
50+
new JsonErrorRenderer($debug),
51+
new XmlErrorRenderer($debug),
52+
new TxtErrorRenderer($debug),
53+
]);
4254
}
4355

4456
/**
@@ -49,26 +61,12 @@ public function __construct(Environment $twig, bool $debug)
4961
* be used.
5062
*
5163
* @return Response
52-
*
53-
* @throws \InvalidArgumentException When the exception template does not exist
5464
*/
55-
public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
65+
public function showAction(Request $request, FlattenException $exception)
5666
{
57-
$currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
58-
$showException = $request->attributes->get('showException', $this->debug); // As opposed to an additional parameter, this maintains BC
59-
60-
$code = $exception->getStatusCode();
61-
62-
return new Response($this->twig->render(
63-
(string) $this->findTemplate($request, $request->getRequestFormat(), $code, $showException),
64-
[
65-
'status_code' => $code,
66-
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
67-
'exception' => $exception,
68-
'logger' => $logger,
69-
'currentContent' => $currentContent,
70-
]
71-
), 200, ['Content-Type' => $request->getMimeType($request->getRequestFormat()) ?: 'text/html']);
67+
return new Response($this->render($exception, $request), 200, [
68+
'Content-Type' => $request->getMimeType($request->getRequestFormat())
69+
]);
7270
}
7371

7472
/**
@@ -94,32 +92,45 @@ protected function getAndCleanOutputBuffering($startObLevel)
9492
* @param bool $showException
9593
*
9694
* @return string
95+
*
96+
* @deprecated since Symfony 4.4
9797
*/
9898
protected function findTemplate(Request $request, $format, $code, $showException)
9999
{
100-
$name = $showException ? 'exception' : 'error';
101-
if ($showException && 'html' == $format) {
102-
$name = 'exception_full';
100+
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.4, use "findTwigTemplate()" method instead.', __METHOD__), E_USER_DEPRECATED);
101+
102+
if ($template = $this->findTwigTemplate($code, $format, $showException)) {
103+
return $template;
103104
}
104105

106+
// default to a generic HTML exception
107+
$request->setRequestFormat('html');
108+
109+
return sprintf('@Twig/Exception/%s.html.twig', $showException ? 'exception_full' : 'error');
110+
}
111+
112+
protected function findTwigTemplate(int $statusCode, string $format, bool $showException): ?string
113+
{
105114
// For error pages, try to find a template for the specific HTTP status code and format
106115
if (!$showException) {
107-
$template = sprintf('@Twig/Exception/%s%s.%s.twig', $name, $code, $format);
116+
$template = sprintf('@Twig/Exception/error%s.%s.twig', $statusCode, $format);
108117
if ($this->templateExists($template)) {
109118
return $template;
110119
}
111120
}
112121

122+
$name = 'error';
123+
if ($showException) {
124+
$name = 'html' === $format ? 'exception_full' : 'exception';
125+
}
126+
113127
// try to find a template for the given format
114128
$template = sprintf('@Twig/Exception/%s.%s.twig', $name, $format);
115129
if ($this->templateExists($template)) {
116130
return $template;
117131
}
118132

119-
// default to a generic HTML exception
120-
$request->setRequestFormat('html');
121-
122-
return sprintf('@Twig/Exception/%s.html.twig', $showException ? 'exception_full' : $name);
133+
return null;
123134
}
124135

125136
// to be removed when the minimum required version of Twig is >= 3.0
@@ -141,4 +152,32 @@ protected function templateExists($template)
141152

142153
return false;
143154
}
155+
156+
private function render(FlattenException $exception, Request $request): string
157+
{
158+
$statusCode = $exception->getStatusCode();
159+
$logger = $request->attributes->get('logger');
160+
$showException = $request->attributes->get('showException', $this->debug);
161+
$currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
162+
163+
$template = $this->findTwigTemplate($statusCode, $request->getRequestFormat(), $showException);
164+
165+
if (null === $template) {
166+
try {
167+
// fallback to the native renderer system
168+
return $this->errorRenderer->render($exception, $request->getRequestFormat());
169+
} catch (ErrorRendererNotFoundException $e) {
170+
$request->setRequestFormat('html');
171+
$template = sprintf('@Twig/Exception/%s.html.twig', $showException ? 'exception_full' : 'error');
172+
}
173+
}
174+
175+
return $this->twig->render($template, [
176+
'status_code' => $statusCode,
177+
'status_text' => Response::$statusTexts[$statusCode] ?? '',
178+
'exception' => $exception,
179+
'logger' => $logger,
180+
'currentContent' => $currentContent,
181+
]);
182+
}
144183
}

src/Symfony/Bundle/TwigBundle/Controller/PreviewErrorController.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ public function previewErrorPageAction(Request $request, $code)
4747
'_controller' => $this->controller,
4848
'exception' => $exception,
4949
'logger' => null,
50-
'format' => $request->getRequestFormat(),
5150
'showException' => false,
5251
]);
5352

src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
<service id="twig.controller.exception" class="Symfony\Bundle\TwigBundle\Controller\ExceptionController" public="true">
141141
<argument type="service" id="twig" />
142142
<argument>%kernel.debug%</argument>
143+
<argument type="service" id="error_handler.error_renderer" on-invalid="null" />
143144
</service>
144145

145146
<service id="twig.controller.preview_error" class="Symfony\Bundle\TwigBundle\Controller\PreviewErrorController" public="true">
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
12
{{ include('@Twig/Exception/error.xml.twig') }}

src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.js.twig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
12
/*
23
{{ status_code }} {{ status_text }}
34

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
12
{{ { 'error': { 'code': status_code, 'message': status_text } }|json_encode|raw }}

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