Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 752e607

Browse filesBrowse files
committed
Added native ErrorRenderer as fallback system and deprecating templates
1 parent 22c73a9 commit 752e607
Copy full SHA for 752e607

15 files changed

+113
-31
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
+67-28Lines 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.3
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.3, 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Controller/PreviewErrorController.php
-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
+1Lines 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">
+1Lines 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.3, will be removed in 4.4.' %}
12
{{ include('@Twig/Exception/error.xml.twig') }}

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.js.twig
+1Lines 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.3, will be removed in 4.4.' %}
12
/*
23
{{ status_code }} {{ status_text }}
34

+1Lines 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.3, will be removed in 4.4.' %}
12
{{ { 'error': { 'code': status_code, 'message': status_text } }|json_encode|raw }}
+1Lines 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.3, will be removed in 4.4.' %}
12
{{ include('@Twig/Exception/error.xml.twig') }}

‎src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.txt.twig

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.txt.twig
+1Lines 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.3, will be removed in 4.4.' %}
12
Oops! An Error Occurred
23
=======================
34

+1Lines 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.3, will be removed in 4.4.' %}
12
<?xml version="1.0" encoding="{{ _charset }}" ?>
23

34
<error code="{{ status_code }}" message="{{ status_text }}" />
+1Lines 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.3, will be removed in 4.4.' %}
12
/*
23
{{ include('@Twig/Exception/exception.txt.twig', { exception: exception }) }}
34
*/
+1Lines 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.3, will be removed in 4.4.' %}
12
{{ { 'error': { 'code': status_code, 'message': status_text, 'exception': exception.toarray } }|json_encode|raw }}
+1Lines 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.3, will be removed in 4.4.' %}
12
{{ include('@Twig/Exception/exception.xml.twig', { exception: exception }) }}

‎src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.txt.twig

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.txt.twig
+1Lines 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.3, will be removed in 4.4.' %}
12
[exception] {{ status_code ~ ' | ' ~ status_text ~ ' | ' ~ exception.class }}
23
[message] {{ exception.message }}
34
{% for i, e in exception.toarray %}

‎src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.xml.twig

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.xml.twig
+1Lines 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.3, will be removed in 4.4.' %}
12
<?xml version="1.0" encoding="{{ _charset }}" ?>
23

34
<error code="{{ status_code }}" message="{{ status_text }}">

‎src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php
+34-2Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use Symfony\Bundle\TwigBundle\Controller\ExceptionController;
1515
use Symfony\Bundle\TwigBundle\Tests\TestCase;
16+
use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRenderer;
17+
use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface;
1618
use Symfony\Component\ErrorHandler\Exception\FlattenException;
1719
use Symfony\Component\HttpFoundation\Request;
1820
use Twig\Environment;
@@ -35,11 +37,27 @@ public function testShowActionCanBeForcedToShowErrorPage()
3537
$this->assertEquals('<html>not found</html>', $response->getContent());
3638
}
3739

40+
public function testFallbackToErrorRendererIfNoTemplateForRequestedFormat()
41+
{
42+
$twig = $this->createTwigEnv(['@Twig/Exception/error.html.twig' => '<html></html>']);
43+
44+
$request = $this->createRequest('foo');
45+
$exception = FlattenException::create(new \Exception('bar'));
46+
$errorRenderer = new ErrorRenderer([
47+
new FooErrorRenderer(),
48+
]);
49+
$controller = new ExceptionController($twig, false, $errorRenderer);
50+
$response = $controller->showAction($request, $exception);
51+
52+
$this->assertSame('foo', $request->getRequestFormat());
53+
$this->assertSame('bar', $response->getContent());
54+
}
55+
3856
public function testFallbackToHtmlIfNoTemplateForRequestedFormat()
3957
{
4058
$twig = $this->createTwigEnv(['@Twig/Exception/error.html.twig' => '<html></html>']);
4159

42-
$request = $this->createRequest('txt');
60+
$request = $this->createRequest('foo');
4361
$exception = FlattenException::create(new \Exception());
4462
$controller = new ExceptionController($twig, false);
4563

@@ -52,7 +70,7 @@ public function testFallbackToHtmlWithFullExceptionIfNoTemplateForRequestedForma
5270
{
5371
$twig = $this->createTwigEnv(['@Twig/Exception/exception_full.html.twig' => '<html></html>']);
5472

55-
$request = $this->createRequest('txt');
73+
$request = $this->createRequest('foo');
5674
$request->attributes->set('showException', true);
5775
$exception = FlattenException::create(new \Exception());
5876
$controller = new ExceptionController($twig, false);
@@ -90,3 +108,17 @@ private function createTwigEnv(array $templates)
90108
return new Environment(new ArrayLoader($templates));
91109
}
92110
}
111+
112+
113+
class FooErrorRenderer implements ErrorRendererInterface
114+
{
115+
public static function getFormat(): string
116+
{
117+
return 'foo';
118+
}
119+
120+
public function render(FlattenException $exception): string
121+
{
122+
return $exception->getMessage();
123+
}
124+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.