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

Skip to content

Commit 480da75

Browse files
author
Alexey Deriyenko
committed
squashing
1 parent 4e7e429 commit 480da75

File tree

7 files changed

+164
-11
lines changed

7 files changed

+164
-11
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,13 +452,16 @@ public function load(array $configs, ContainerBuilder $container)
452452
$this->registerSecretsConfiguration($config['secrets'], $container, $loader);
453453

454454
$container->getDefinition('exception_listener')->replaceArgument(3, $config['exceptions']);
455+
$container->getDefinition('error_handler.error_renderer.html')->replaceArgument(6, $config['exceptions']);
455456

456457
if ($this->isConfigEnabled($container, $config['serializer'])) {
457458
if (!class_exists(\Symfony\Component\Serializer\Serializer::class)) {
458459
throw new LogicException('Serializer support cannot be enabled as the Serializer component is not installed. Try running "composer require symfony/serializer-pack".');
459460
}
460461

461462
$this->registerSerializerConfiguration($config['serializer'], $container, $loader);
463+
464+
$container->getDefinition('error_handler.error_renderer.serializer')->replaceArgument(4, $config['exceptions']);
462465
}
463466

464467
if ($propertyInfoEnabled) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
->factory([HtmlErrorRenderer::class, 'getAndCleanOutputBuffer'])
3131
->args([service('request_stack')]),
3232
service('logger')->nullOnInvalid(),
33+
abstract_arg('an exceptions to log & status code mapping'),
3334
])
3435

3536
->alias('error_renderer.html', 'error_handler.error_renderer.html')

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
inline_service()
209209
->factory([HtmlErrorRenderer::class, 'isDebug'])
210210
->args([service('request_stack'), param('kernel.debug')]),
211+
abstract_arg('an exceptions to log & status code mapping'),
211212
])
212213
;
213214

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,17 @@ class HtmlErrorRenderer implements ErrorRendererInterface
3939
private $projectDir;
4040
private $outputBuffer;
4141
private $logger;
42+
private $exceptionsMapping;
4243

4344
private static $template = 'views/error.html.php';
4445

4546
/**
46-
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
47+
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
4748
* @param string|FileLinkFormatter|null $fileLinkFormat
48-
* @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it
49+
* @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it
50+
* @param array $exceptionsMapping An exceptions to log & status code mapping
4951
*/
50-
public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null)
52+
public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null, array $exceptionsMapping = [])
5153
{
5254
if (!\is_bool($debug) && !\is_callable($debug)) {
5355
throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, \gettype($debug)));
@@ -63,6 +65,7 @@ public function __construct($debug = false, string $charset = null, $fileLinkFor
6365
$this->projectDir = $projectDir;
6466
$this->outputBuffer = $outputBuffer;
6567
$this->logger = $logger;
68+
$this->exceptionsMapping = $exceptionsMapping;
6669
}
6770

6871
/**
@@ -76,7 +79,14 @@ public function render(\Throwable $exception): FlattenException
7679
$headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine();
7780
}
7881

79-
$exception = FlattenException::createFromThrowable($exception, null, $headers);
82+
$statusCode = 500;
83+
foreach ($this->exceptionsMapping as $class => $config) {
84+
if ($exception instanceof $class && $config['status_code']) {
85+
$statusCode = $config['status_code'];
86+
break;
87+
}
88+
}
89+
$exception = FlattenException::createFromThrowable($exception, $statusCode, $headers);
8090

8191
return $exception->setAsString($this->renderException($exception));
8292
}
@@ -262,8 +272,6 @@ private function formatFile(string $file, int $line, string $text = null): strin
262272
* @param string $file A file path
263273
* @param int $line The selected line number
264274
* @param int $srcContext The number of displayed lines around or -1 for the whole file
265-
*
266-
* @return string
267275
*/
268276
private function fileExcerpt(string $file, int $line, int $srcContext = 3): string
269277
{

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ class SerializerErrorRenderer implements ErrorRendererInterface
2828
private $format;
2929
private $fallbackErrorRenderer;
3030
private $debug;
31+
private $exceptionsMapping;
3132

3233
/**
33-
* @param string|callable(FlattenException) $format The format as a string or a callable that should return it
34-
* formats not supported by Request::getMimeTypes() should be given as mime types
35-
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
34+
* @param string|callable(FlattenException) $format The format as a string or a callable that should return it
35+
* formats not supported by Request::getMimeTypes() should be given as mime types
36+
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
37+
* @param array $exceptionsMapping An exceptions to log & status code mapping
3638
*/
37-
public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false)
39+
public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false, array $exceptionsMapping = [])
3840
{
3941
if (!\is_string($format) && !\is_callable($format)) {
4042
throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be a string or a callable, "%s" given.', __METHOD__, \gettype($format)));
@@ -48,6 +50,7 @@ public function __construct(SerializerInterface $serializer, $format, ErrorRende
4850
$this->format = $format;
4951
$this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer();
5052
$this->debug = $debug;
53+
$this->exceptionsMapping = $exceptionsMapping;
5154
}
5255

5356
/**
@@ -62,7 +65,15 @@ public function render(\Throwable $exception): FlattenException
6265
$headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine();
6366
}
6467

65-
$flattenException = FlattenException::createFromThrowable($exception, null, $headers);
68+
$statusCode = 500;
69+
foreach ($this->exceptionsMapping as $class => $config) {
70+
if ($exception instanceof $class && $config['status_code']) {
71+
$statusCode = $config['status_code'];
72+
break;
73+
}
74+
}
75+
76+
$flattenException = FlattenException::createFromThrowable($exception, $statusCode, $headers);
6677

6778
try {
6879
$format = \is_string($this->format) ? $this->format : ($this->format)($flattenException);

src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,22 @@ public function getRenderData(): iterable
4040
<html>
4141
%A<title>An Error Occurred: Internal Server Error</title>
4242
%A<h2>The server returned a "500 Internal Server Error".</h2>%A
43+
HTML;
44+
45+
$expectedDebugWithStatusCode = <<<HTML
46+
<!-- Foo (418 I'm a teapot) -->
47+
<!DOCTYPE html>
48+
<html lang="en">
49+
%A<title>Foo (418 I'm a teapot)</title>
50+
%A<div class="trace trace-as-html" id="trace-box-1">%A
51+
<!-- Foo (418 I'm a teapot) -->
52+
HTML;
53+
54+
$expectedNonDebugWithStatusCode = <<<HTML
55+
<!DOCTYPE html>
56+
<html>
57+
%A<title>An Error Occurred: I'm a teapot</title>
58+
%A<h2>The server returned a "418 I'm a teapot".</h2>%A
4359
HTML;
4460

4561
yield '->render() returns the HTML content WITH stack traces in debug mode' => [
@@ -53,5 +69,27 @@ public function getRenderData(): iterable
5369
new HtmlErrorRenderer(false),
5470
$expectedNonDebug,
5571
];
72+
73+
yield '->render() returns the HTML content WITH stack traces in debug mode and contains the correct status code' => [
74+
new \RuntimeException('Foo'),
75+
new HtmlErrorRenderer(true, null, null, null, '', null, [
76+
\RuntimeException::class => [
77+
'status_code' => 418,
78+
'log_level' => null,
79+
],
80+
]),
81+
$expectedDebugWithStatusCode,
82+
];
83+
84+
yield '->render() returns the HTML content WITHOUT stack traces in non-debug mode and contains the correct status code' => [
85+
new \RuntimeException('Foo'),
86+
new HtmlErrorRenderer(false, null, null, null, '', null, [
87+
\RuntimeException::class => [
88+
'status_code' => 418,
89+
'log_level' => null,
90+
],
91+
]),
92+
$expectedNonDebugWithStatusCode,
93+
];
5694
}
5795
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
/*
3+
* This file is part of the Symfony package.
4+
*
5+
* (c) Fabien Potencier <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace Symfony\Component\Serializer\Tests\ErrorRenderer;
12+
13+
use function json_decode;
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer;
16+
use Symfony\Component\Serializer\Encoder\JsonEncoder;
17+
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
18+
use Symfony\Component\Serializer\Serializer;
19+
20+
/**
21+
* @author Alexey Deriyenko <[email protected]>
22+
*/
23+
class SerializerErrorRendererTest extends TestCase
24+
{
25+
/**
26+
* @dataProvider getRenderData
27+
*/
28+
public function testRenderReturnsJson(\Throwable $exception, SerializerErrorRenderer $serializerErrorRenderer)
29+
{
30+
$this->assertJson($serializerErrorRenderer->render($exception)->getAsString());
31+
}
32+
33+
/**
34+
* @dataProvider getRenderData
35+
*/
36+
public function testRenderReturnsJsonWithCorrectStatusCode(\Throwable $exception, SerializerErrorRenderer $serializerErrorRenderer, int $expectedStatusCode)
37+
{
38+
$statusCodeFromJson = json_decode($serializerErrorRenderer->render($exception)->getAsString())->statusCode;
39+
$this->assertEquals($expectedStatusCode, $statusCodeFromJson);
40+
}
41+
42+
/**
43+
* @dataProvider getRenderData
44+
*/
45+
public function testRenderReturnsJsonWithCorrectStatusText(\Throwable $exception, SerializerErrorRenderer $serializerErrorRenderer, int $expectedStatusCode, string $expectedStatusText)
46+
{
47+
$statusTextFromJson = json_decode($serializerErrorRenderer->render($exception)->getAsString())->statusText;
48+
$this->assertEquals($expectedStatusText, $statusTextFromJson);
49+
}
50+
51+
public function getRenderData(): iterable
52+
{
53+
yield '->render() returns the JSON content WITH stack traces in debug mode' => [
54+
new \RuntimeException('Foo'),
55+
new SerializerErrorRenderer(new Serializer([new ObjectNormalizer()], [new JsonEncoder()]), 'json', null, true),
56+
500,
57+
'Internal Server Error',
58+
];
59+
60+
yield '->render() returns the JSON content WITHOUT stack traces in non-debug mode' => [
61+
new \RuntimeException('Foo'),
62+
new SerializerErrorRenderer(new Serializer([new ObjectNormalizer()], [new JsonEncoder()]), 'json', null, false),
63+
500,
64+
'Internal Server Error',
65+
];
66+
67+
yield '->render() returns the JSON content WITH stack traces in debug mode and contains the correct status code' => [
68+
new \RuntimeException('Foo'),
69+
new SerializerErrorRenderer(new Serializer([new ObjectNormalizer()], [new JsonEncoder()]), 'json', null, true, [
70+
\RuntimeException::class => [
71+
'status_code' => 418,
72+
'log_level' => null,
73+
],
74+
]),
75+
418,
76+
'I\'m a teapot',
77+
];
78+
79+
yield '->render() returns the JSON content WITHOUT stack traces in non-debug mode and contains the correct status code' => [
80+
new \RuntimeException('Foo'),
81+
new SerializerErrorRenderer(new Serializer([new ObjectNormalizer()], [new JsonEncoder()]), 'json', null, true, [
82+
\RuntimeException::class => [
83+
'status_code' => 418,
84+
'log_level' => null,
85+
],
86+
]),
87+
418,
88+
'I\'m a teapot',
89+
];
90+
}
91+
}

0 commit comments

Comments
 (0)