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 2065e00

Browse filesBrowse files
mpdudefabpot
authored andcommitted
[TwigBundle] Fix error page preview for custom twig.exception_controller
1 parent f288a69 commit 2065e00
Copy full SHA for 2065e00

File tree

6 files changed

+158
-64
lines changed
Filter options

6 files changed

+158
-64
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
+28-49Lines changed: 28 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,19 @@
1919
use Symfony\Component\Templating\TemplateReferenceInterface;
2020

2121
/**
22-
* ExceptionController.
22+
* ExceptionController renders error or exception pages for a given
23+
* FlattenException.
2324
*
2425
* @author Fabien Potencier <fabien@symfony.com>
2526
* @author Matthias Pigulla <mp@webfactory.de>
2627
*/
2728
class ExceptionController
2829
{
2930
protected $twig;
31+
32+
/**
33+
* @var bool Show error (false) or exception (true) pages by default.
34+
*/
3035
protected $debug;
3136

3237
public function __construct(\Twig_Environment $twig, $debug)
@@ -38,6 +43,10 @@ public function __construct(\Twig_Environment $twig, $debug)
3843
/**
3944
* Converts an Exception to a Response.
4045
*
46+
* A "showException" request parameter can be used to force display of an error page (when set to false) or
47+
* the exception page (when true). If it is not present, the "debug" value passed into the constructor will
48+
* be used.
49+
*
4150
* @param Request $request The request
4251
* @param FlattenException $exception A FlattenException instance
4352
* @param DebugLoggerInterface $logger A DebugLoggerInterface instance
@@ -49,25 +58,20 @@ public function __construct(\Twig_Environment $twig, $debug)
4958
public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
5059
{
5160
$currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
61+
$showException = $request->get('showException', $this->debug); // As opposed to an additional parameter, this maintains BC
5262

53-
return $this->createResponse($request, $exception, $this->debug, $logger, $currentContent);
54-
}
55-
56-
/**
57-
* Displays the error page for arbitrary status codes and formats.
58-
*
59-
* @param Request $request The request
60-
* @param int $code The HTTP status code to show the error page for.
61-
*
62-
* @return Response
63-
*
64-
* @throws \InvalidArgumentException When the error template does not exist
65-
*/
66-
public function testErrorPageAction(Request $request, $code)
67-
{
68-
$exception = FlattenException::create(new \Exception("Something has intentionally gone wrong."), $code);
63+
$code = $exception->getStatusCode();
6964

70-
return $this->createResponse($request, $exception, false);
65+
return new Response($this->twig->render(
66+
$this->findTemplate($request, $request->getRequestFormat(), $code, $showException),
67+
array(
68+
'status_code' => $code,
69+
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
70+
'exception' => $exception,
71+
'logger' => $logger,
72+
'currentContent' => $currentContent,
73+
)
74+
));
7175
}
7276

7377
/**
@@ -90,19 +94,19 @@ protected function getAndCleanOutputBuffering($startObLevel)
9094
* @param Request $request
9195
* @param string $format
9296
* @param int $code An HTTP response status code
93-
* @param bool $debug
97+
* @param bool $showException
9498
*
9599
* @return TemplateReferenceInterface
96100
*/
97-
protected function findTemplate(Request $request, $format, $code, $debug)
101+
protected function findTemplate(Request $request, $format, $code, $showException)
98102
{
99-
$name = $debug ? 'exception' : 'error';
100-
if ($debug && 'html' == $format) {
103+
$name = $showException ? 'exception' : 'error';
104+
if ($showException && 'html' == $format) {
101105
$name = 'exception_full';
102106
}
103107

104-
// when not in debug, try to find a template for the specific HTTP status code and format
105-
if (!$debug) {
108+
// For error pages, try to find a template for the specific HTTP status code and format
109+
if (!$showException) {
106110
$template = new TemplateReference('TwigBundle', 'Exception', $name.$code, $format, 'twig');
107111
if ($this->templateExists($template)) {
108112
return $template;
@@ -138,29 +142,4 @@ protected function templateExists($template)
138142

139143
return false;
140144
}
141-
142-
/**
143-
* @param Request $request
144-
* @param FlattenException $exception
145-
* @param bool $debug
146-
* @param DebugLoggerInterface $logger
147-
* @param string $currentContent
148-
*
149-
* @return Response
150-
*/
151-
protected function createResponse(Request $request, FlattenException $exception, $debug, DebugLoggerInterface $logger = null, $currentContent = '')
152-
{
153-
$code = $exception->getStatusCode();
154-
155-
return new Response($this->twig->render(
156-
(string) $this->findTemplate($request, $request->getRequestFormat(), $code, $debug),
157-
array(
158-
'status_code' => $code,
159-
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
160-
'exception' => $exception,
161-
'logger' => $logger,
162-
'currentContent' => $currentContent,
163-
)
164-
));
165-
}
166145
}
+56Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\TwigBundle\Controller;
13+
14+
use Symfony\Component\HttpKernel\Exception\FlattenException;
15+
use Symfony\Component\HttpKernel\HttpKernelInterface;
16+
use Symfony\Component\HttpFoundation\Request;
17+
18+
/**
19+
* PreviewErrorController can be used to test error pages.
20+
*
21+
* It will create a test exception and forward it to another controller.
22+
*
23+
* @author Matthias Pigulla <mp@webfactory.de>
24+
*/
25+
class PreviewErrorController
26+
{
27+
protected $kernel;
28+
protected $controller;
29+
30+
public function __construct(HttpKernelInterface $kernel, $controller)
31+
{
32+
$this->kernel = $kernel;
33+
$this->controller = $controller;
34+
}
35+
36+
public function previewErrorPageAction(Request $request, $code)
37+
{
38+
$exception = FlattenException::create(new \Exception("Something has intentionally gone wrong."), $code);
39+
40+
/*
41+
* This Request mimics the parameters set by
42+
* \Symfony\Component\HttpKernel\EventListener\ExceptionListener::duplicateRequest, with
43+
* the additional "showException" flag.
44+
*/
45+
46+
$subRequest = $request->duplicate(null, null, array(
47+
'_controller' => $this->controller,
48+
'exception' => $exception,
49+
'logger' => null,
50+
'format' => $request->getRequestFormat(),
51+
'showException' => false,
52+
));
53+
54+
return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
55+
}
56+
}

‎src/Symfony/Bundle/TwigBundle/Resources/config/routing/errors.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Resources/config/routing/errors.xml
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
66

77
<route id="_twig_error_test" path="/{code}.{_format}">
8-
<default key="_controller">twig.controller.exception:testErrorPageAction</default>
8+
<default key="_controller">twig.controller.preview_error:previewErrorPageAction</default>
99
<default key="_format">html</default>
1010
<requirement key="code">\d+</requirement>
1111
</route>

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<parameter key="twig.translation.extractor.class">Symfony\Bridge\Twig\Translation\TwigExtractor</parameter>
2626
<parameter key="twig.exception_listener.class">Symfony\Component\HttpKernel\EventListener\ExceptionListener</parameter>
2727
<parameter key="twig.controller.exception.class">Symfony\Bundle\TwigBundle\Controller\ExceptionController</parameter>
28+
<parameter key="twig.controller.preview_error.class">Symfony\Bundle\TwigBundle\Controller\PreviewErrorController</parameter>
2829
</parameters>
2930

3031
<services>
@@ -133,5 +134,10 @@
133134
<argument type="service" id="twig" />
134135
<argument>%kernel.debug%</argument>
135136
</service>
137+
138+
<service id="twig.controller.preview_error" class="%twig.controller.preview_error.class%">
139+
<argument type="service" id="http_kernel" />
140+
<argument>%twig.exception_listener.controller%</argument>
141+
</service>
136142
</services>
137143
</container>

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

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

1414
use Symfony\Bundle\TwigBundle\Tests\TestCase;
1515
use Symfony\Bundle\TwigBundle\Controller\ExceptionController;
16+
use Symfony\Component\HttpKernel\Exception\FlattenException;
1617
use Symfony\Component\HttpFoundation\Request;
1718

1819
class ExceptionControllerTest extends TestCase
@@ -42,27 +43,22 @@ public function testOnlyClearOwnOutputBuffers()
4243
$controller->showAction($request, $flatten);
4344
}
4445

45-
public function testErrorPagesInDebugMode()
46+
public function testShowActionCanBeForcedToShowErrorPage()
4647
{
4748
$twig = new \Twig_Environment(
4849
new \Twig_Loader_Array(array(
49-
'TwigBundle:Exception:error404.html.twig' => '
50-
{%- if exception is defined and status_text is defined and status_code is defined -%}
51-
OK
52-
{%- else -%}
53-
"exception" variable is missing
54-
{%- endif -%}
55-
',
50+
'TwigBundle:Exception:error404.html.twig' => 'ok',
5651
))
5752
);
5853

59-
$request = Request::create('whatever');
54+
$request = Request::create('whatever', 'GET', array('showException' => false));
55+
$exception = FlattenException::create(new \Exception(), 404);
56+
$controller = new ExceptionController($twig, /* "showException" defaults to --> */ true);
6057

61-
$controller = new ExceptionController($twig, /* "debug" set to --> */ true);
62-
$response = $controller->testErrorPageAction($request, 404);
58+
$response = $controller->showAction($request, $exception, null);
6359

6460
$this->assertEquals(200, $response->getStatusCode()); // successful request
65-
$this->assertEquals('OK', $response->getContent()); // content of the error404.html template
61+
$this->assertEquals('ok', $response->getContent()); // content of the error404.html template
6662
}
6763

6864
public function testFallbackToHtmlIfNoTemplateForRequestedFormat()
@@ -75,9 +71,10 @@ public function testFallbackToHtmlIfNoTemplateForRequestedFormat()
7571

7672
$request = Request::create('whatever');
7773
$request->setRequestFormat('txt');
78-
74+
$exception = FlattenException::create(new \Exception());
7975
$controller = new ExceptionController($twig, false);
80-
$response = $controller->testErrorPageAction($request, 42);
76+
77+
$response = $controller->showAction($request, $exception);
8178

8279
$this->assertEquals('html', $request->getRequestFormat());
8380
}
+56Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\TwigBundle\Tests\Controller;
13+
14+
use Symfony\Bundle\TwigBundle\Controller\PreviewErrorController;
15+
use Symfony\Bundle\TwigBundle\Tests\TestCase;
16+
use Symfony\Component\HttpFoundation\Response;
17+
use Symfony\Component\HttpFoundation\Request;
18+
use Symfony\Component\HttpKernel\HttpKernelInterface;
19+
20+
class PreviewErrorControllerTest extends TestCase
21+
{
22+
public function testForwardRequestToConfiguredController()
23+
{
24+
$self = $this;
25+
26+
$request = Request::create('whatever');
27+
$response = new Response("");
28+
$code = 123;
29+
$logicalControllerName = 'foo:bar:baz';
30+
31+
$kernel = $this->getMock('\Symfony\Component\HttpKernel\HttpKernelInterface');
32+
$kernel
33+
->expects($this->once())
34+
->method('handle')
35+
->with(
36+
$this->callback(function (Request $request) use ($self, $logicalControllerName, $code) {
37+
38+
$self->assertEquals($logicalControllerName, $request->attributes->get('_controller'));
39+
40+
$exception = $request->attributes->get('exception');
41+
$self->assertInstanceOf('Symfony\Component\HttpKernel\Exception\FlattenException', $exception);
42+
$self->assertEquals($code, $exception->getStatusCode());
43+
44+
$self->assertFalse($request->attributes->get('showException'));
45+
46+
return true;
47+
}),
48+
$this->equalTo(HttpKernelInterface::SUB_REQUEST)
49+
)
50+
->will($this->returnValue($response));
51+
52+
$controller = new PreviewErrorController($kernel, $logicalControllerName);
53+
54+
$this->assertSame($response, $controller->previewErrorPageAction($request, $code));
55+
}
56+
}

0 commit comments

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