Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d1bf1ca

Browse files
ycerutonicolas-grekas
authored andcommitted
[ErrorHandler] help finish the PR
1 parent 6c9157b commit d1bf1ca

File tree

25 files changed

+174
-129
lines changed

25 files changed

+174
-129
lines changed

UPGRADE-4.4.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ Console
1818
Debug
1919
-----
2020

21-
* Deprecated the `FlattenException` class, use the one from the `ErrorRenderer` component instead
2221
* Deprecated the component in favor of the `ErrorHandler` component
2322

2423
Config
@@ -305,7 +304,7 @@ TwigBundle
305304
```
306305

307306
* Deprecated the `ExceptionController` and `PreviewErrorController` controllers, use `ErrorController` from the HttpKernel component instead
308-
* Deprecated all built-in error templates, use the error renderer mechanism of the `ErrorRenderer` component
307+
* Deprecated all built-in error templates, use the error renderer mechanism of the `ErrorHandler` component
309308
* Deprecated loading custom error templates in non-html formats. Custom HTML error pages based on Twig keep working as before:
310309

311310
Before (`templates/bundles/TwigBundle/Exception/error.json.twig`):

UPGRADE-5.0.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ Console
5757
Debug
5858
-----
5959

60-
* Removed the `FlattenException` class, use the one from the `ErrorRenderer` component instead
6160
* Removed the component in favor of the `ErrorHandler` component
6261

6362
DependencyInjection

src/Symfony/Bridge/Twig/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
4.4.0
55
-----
66

7+
* added a new `TwigErrorRenderer` for `html` format, integrated with the `ErrorHandler` component
78
* marked all classes extending twig as `@final`
89
* deprecated to pass `$rootDir` and `$fileLinkFormatter` as 5th and 6th argument respectively to the
910
`DebugCommand::__construct()` method, swap the variables position.

src/Symfony/Bundle/TwigBundle/ErrorRenderer/TwigHtmlErrorRenderer.php renamed to src/Symfony/Bridge/Twig/ErrorRenderer/TwigErrorRenderer.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\Bundle\TwigBundle\ErrorRenderer;
12+
namespace Symfony\Bridge\Twig\ErrorRenderer;
1313

1414
use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface;
1515
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
@@ -24,16 +24,16 @@
2424
*
2525
* @author Yonel Ceruto <[email protected]>
2626
*/
27-
class TwigHtmlErrorRenderer implements ErrorRendererInterface
27+
class TwigErrorRenderer implements ErrorRendererInterface
2828
{
2929
private $twig;
30-
private $htmlErrorRenderer;
30+
private $fallbackErrorRenderer;
3131
private $debug;
3232

33-
public function __construct(Environment $twig, HtmlErrorRenderer $htmlErrorRenderer, bool $debug = false)
33+
public function __construct(Environment $twig, HtmlErrorRenderer $fallbackErrorRenderer = null, bool $debug = false)
3434
{
3535
$this->twig = $twig;
36-
$this->htmlErrorRenderer = $htmlErrorRenderer;
36+
$this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer();
3737
$this->debug = $debug;
3838
}
3939

@@ -42,9 +42,9 @@ public function __construct(Environment $twig, HtmlErrorRenderer $htmlErrorRende
4242
*/
4343
public function render(\Throwable $exception): FlattenException
4444
{
45-
$exception = $this->htmlErrorRenderer->render($exception);
45+
$exception = $this->fallbackErrorRenderer->render($exception);
4646

47-
if ($this->debug || !$template = $this->findTemplate($exception->getStatusCode());
47+
if ($this->debug || !$template = $this->findTemplate($exception->getStatusCode())) {
4848
return $exception;
4949
}
5050

src/Symfony/Bundle/TwigBundle/Tests/ErrorRenderer/TwigHtmlErrorRendererTest.php renamed to src/Symfony/Bridge/Twig/Tests/ErrorRenderer/TwigErrorRendererTest.php

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\Bundle\TwigBundle\Tests\ErrorRenderer;
12+
namespace Symfony\Bridge\Twig\Tests\ErrorRenderer;
1313

1414
use PHPUnit\Framework\TestCase;
15-
use Symfony\Bundle\TwigBundle\ErrorRenderer\TwigHtmlErrorRenderer;
15+
use Symfony\Bridge\Twig\ErrorRenderer\TwigErrorRenderer;
1616
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
17+
use Symfony\Component\ErrorHandler\Exception\FlattenException;
1718
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
1819
use Twig\Environment;
1920
use Twig\Loader\ArrayLoader;
2021

21-
class TwigHtmlErrorRendererTest extends TestCase
22+
class TwigErrorRendererTest extends TestCase
2223
{
2324
public function testFallbackToNativeRendererIfDebugOn()
2425
{
@@ -32,7 +33,7 @@ public function testFallbackToNativeRendererIfDebugOn()
3233
->with($exception)
3334
;
3435

35-
(new TwigHtmlErrorRenderer($twig, $nativeRenderer, true))->render(new \Exception());
36+
(new TwigErrorRenderer($twig, $nativeRenderer, true))->render(new \Exception());
3637
}
3738

3839
public function testFallbackToNativeRendererIfCustomTemplateNotFound()
@@ -46,27 +47,19 @@ public function testFallbackToNativeRendererIfCustomTemplateNotFound()
4647
->expects($this->once())
4748
->method('render')
4849
->with($exception)
50+
->willReturn(FlattenException::createFromThrowable($exception))
4951
;
5052

51-
(new TwigHtmlErrorRenderer($twig, $nativeRenderer, false))->render($exception);
53+
(new TwigErrorRenderer($twig, $nativeRenderer, false))->render($exception);
5254
}
5355

5456
public function testRenderCustomErrorTemplate()
5557
{
56-
$exception = new NotFoundHttpException();
57-
5858
$twig = new Environment(new ArrayLoader([
5959
'@Twig/Exception/error404.html.twig' => '<h1>Page Not Found</h1>',
6060
]));
61+
$exception = (new TwigErrorRenderer($twig))->render(new NotFoundHttpException());
6162

62-
$nativeRenderer = $this->createMock(HtmlErrorRenderer::class);
63-
$nativeRenderer
64-
->expects($this->never())
65-
->method('render')
66-
;
67-
68-
$content = (new TwigHtmlErrorRenderer($twig, $nativeRenderer, false))->render($exception);
69-
70-
$this->assertSame('<h1>Page Not Found</h1>', $content->getAsString());
63+
$this->assertSame('<h1>Page Not Found</h1>', $exception->getAsString());
7164
}
7265
}

src/Symfony/Bridge/Twig/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@
2424
"egulias/email-validator": "^2.1.10",
2525
"symfony/asset": "^3.4|^4.0|^5.0",
2626
"symfony/dependency-injection": "^3.4|^4.0|^5.0",
27+
"symfony/error-handler": "^4.4|^5.0",
2728
"symfony/finder": "^3.4|^4.0|^5.0",
2829
"symfony/form": "^4.4|^5.0",
2930
"symfony/http-foundation": "^4.3|^5.0",
30-
"symfony/http-kernel": "^3.4|^4.0",
31+
"symfony/http-kernel": "^4.4",
3132
"symfony/mime": "^4.3|^5.0",
3233
"symfony/polyfill-intl-icu": "~1.0",
3334
"symfony/routing": "^3.4|^4.0|^5.0",

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616

1717
<service id="error_handler.error_renderer.serializer" class="Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer">
1818
<argument type="service" id="serializer" />
19-
<argument type="service" id="request_stack" />
19+
<argument type="service">
20+
<service>
21+
<factory class="Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer" method="getPreferredFormat" />
22+
<argument type="service" id="request_stack" />
23+
</service>
24+
</argument>
2025
<argument type="service" id="error_renderer.html" />
21-
<argument>%kernel.debug%</argument>
2226
</service>
2327

2428
<service id="error_renderer.html" alias="error_handler.error_renderer.html" />

src/Symfony/Bundle/TwigBundle/CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ CHANGELOG
66

77
* marked the `TemplateIterator` as `internal`
88
* added HTML comment to beginning and end of `exception_full.html.twig`
9-
* added a new `TwigHtmlErrorRenderer` for `html` format, integrated with the `ErrorHandler` component
109
* deprecated `ExceptionController` and `PreviewErrorController` controllers, use `ErrorController` from the `HttpKernel` component instead
1110
* deprecated all built-in error templates in favor of the new error renderer mechanism
1211
* deprecated `twig.exception_controller` configuration option, set it to "null" and use `framework.error_controller` configuration instead

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@
162162
<argument /> <!-- runtime locator -->
163163
</service>
164164

165-
<service id="twig.error_renderer.html" class="Symfony\Bundle\TwigBundle\ErrorRenderer\TwigHtmlErrorRenderer" decorates="error_renderer.html">
165+
<service id="twig.error_renderer.html" class="Symfony\Bridge\Twig\ErrorRenderer\TwigErrorRenderer" decorates="error_renderer.html">
166166
<argument type="service" id="twig" />
167167
<argument type="service" id="twig.error_renderer.html.inner" />
168168
<argument>%kernel.debug%</argument>

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
2424
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
2525
use Symfony\Component\DependencyInjection\Reference;
26+
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
2627

2728
class TwigExtensionTest extends TestCase
2829
{
@@ -302,6 +303,7 @@ public function testRuntimeLoader()
302303
$container->register('templating.locator', 'FooClass');
303304
$container->register('templating.name_parser', 'FooClass');
304305
$container->register('foo', '%foo%')->addTag('twig.runtime');
306+
$container->register('error_renderer.html', HtmlErrorRenderer::class);
305307
$container->addCompilerPass(new RuntimeLoaderPass(), PassConfig::TYPE_BEFORE_REMOVING);
306308
$container->getCompilerPassConfig()->setRemovingPasses([]);
307309
$container->getCompilerPassConfig()->setAfterRemovingPasses([]);

src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ protected function setUp(): void
5454
$this->kernel = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\KernelInterface')->getMock();
5555

5656
$this->container = new ContainerBuilder();
57-
$this->container->register('error_renderer.html', HtmlErrorRenderer::class)->setPublic(true);
57+
$this->container->register('error_handler.error_renderer.html', HtmlErrorRenderer::class)->setPublic(true);
5858
$this->container->register('event_dispatcher', EventDispatcher::class)->setPublic(true);
5959
$this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface'))->setPublic(true);
6060
$this->container->register('twig', 'Twig\Environment')->setPublic(true);

src/Symfony/Component/ErrorHandler/ErrorHandler.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer;
2222
use Symfony\Component\ErrorHandler\ErrorRenderer\CliErrorRenderer;
2323
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
24-
use Symfony\Component\ErrorHandler\Exception\FlattenException;
2524
use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
2625

2726
/**
@@ -580,7 +579,12 @@ public function handleException(\Throwable $exception)
580579
}
581580

582581
$exceptionHandler = $this->exceptionHandler;
583-
$this->exceptionHandler = null;
582+
$this->exceptionHandler = [$this, 'renderException'];
583+
584+
if (null === $exceptionHandler || $exceptionHandler === $this->exceptionHandler) {
585+
$this->exceptionHandler = null;
586+
}
587+
584588
try {
585589
if (null !== $exceptionHandler) {
586590
return $exceptionHandler($exception);
@@ -593,7 +597,14 @@ public function handleException(\Throwable $exception)
593597
throw $exception; // Give back $exception to the native handler
594598
}
595599

596-
$this->handleException($handlerException);
600+
$loggedErrors = $this->loggedErrors;
601+
$this->loggedErrors = $exception === $handlerException ? 0 : $this->loggedErrors;
602+
603+
try {
604+
$this->handleException($handlerException);
605+
} finally {
606+
$this->loggedErrors = $loggedErrors;
607+
}
597608
}
598609

599610
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function render(\Throwable $exception): FlattenException
3030
protected function supportsColors(): bool
3131
{
3232
$outputStream = $this->outputStream;
33-
$this->outputStream = STDOUT;
33+
$this->outputStream = fopen('php://stdout', 'w');
3434

3535
try {
3636
return parent::supportsColors();

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ private function renderException(FlattenException $exception, string $debugTempl
102102
'statusText' => $statusText,
103103
'statusCode' => $statusCode,
104104
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
105-
'currentContent' => $request ? $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level')) : '',
105+
'currentContent' => $request ? $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1)) : '',
106106
]);
107107
}
108108

109-
private function getAndCleanOutputBuffering(?int $startObLevel): string
109+
private function getAndCleanOutputBuffering(int $startObLevel): string
110110
{
111-
if (null === $startObLevel || ob_get_level() <= $startObLevel) {
111+
if (ob_get_level() <= $startObLevel) {
112112
return '';
113113
}
114114

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

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
namespace Symfony\Component\ErrorHandler\ErrorRenderer;
1313

14-
use Symfony\Component\ErrorRenderer\Exception\FlattenException;
14+
use Symfony\Component\ErrorHandler\Exception\FlattenException;
15+
use Symfony\Component\HttpFoundation\RequestStack;
1516
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
1617
use Symfony\Component\Serializer\SerializerInterface;
1718

@@ -20,31 +21,50 @@
2021
*
2122
* @author Nicolas Grekas <[email protected]>
2223
*/
23-
class SerializerErrorRenderer
24+
class SerializerErrorRenderer implements ErrorRendererInterface
2425
{
2526
private $serializer;
26-
private $requestStack;
27-
private $debug;
27+
private $format;
28+
private $fallbackErrorRenderer;
2829

29-
public function __construct(SerializerInterface $serializer, RequestStack $requestStack, bool $debug = true)
30+
/**
31+
* @param string|callable(FlattenException) $format The format as a string or a callable that should return it
32+
*/
33+
public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null)
3034
{
35+
if (!\is_string($format) && !\is_callable($format)) {
36+
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)));
37+
}
38+
3139
$this->serializer = $serializer;
32-
$this->requestStack = $requestStack;
33-
$this->debug = $debug;
40+
$this->format = $format;
41+
$this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer();
3442
}
3543

3644
/**
3745
* {@inheritdoc}
3846
*/
3947
public function render(\Throwable $exception): FlattenException
4048
{
41-
$format = $this->requestStack->getCurrentRequest()->getPreferredFormat();
4249
$flattenException = FlattenException::createFromThrowable($exception);
4350

4451
try {
52+
$format = \is_string($this->format) ? $this->format : ($this->format)($flattenException);
53+
4554
return $flattenException->setAsString($this->serializer->serialize($flattenException, $format, ['exception' => $exception]));
46-
} catch (NotEncodableValueException $_) {
47-
return (new HtmlErrorHandler($this->debug))->render($exception);
55+
} catch (NotEncodableValueException $e) {
56+
return $this->fallbackErrorRenderer->render($exception);
4857
}
4958
}
59+
60+
public static function getPreferredFormat(RequestStack $requestStack): \Closure
61+
{
62+
return static function () use ($requestStack) {
63+
if (!$request = $requestStack->getCurrentRequest()) {
64+
throw new NotEncodableValueException();
65+
}
66+
67+
return $request->getPreferredFormat();
68+
};
69+
}
5070
}

0 commit comments

Comments
 (0)