*
- * @deprecated since Symfony 4.4, use Symfony\Component\ErrorRenderer\Exception\FlattenException instead.
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\FlattenException instead.
*/
class FlattenException
{
diff --git a/src/Symfony/Component/ErrorHandler/BufferingLogger.php b/src/Symfony/Component/ErrorHandler/BufferingLogger.php
index 49c838f272..16e433dedf 100644
--- a/src/Symfony/Component/ErrorHandler/BufferingLogger.php
+++ b/src/Symfony/Component/ErrorHandler/BufferingLogger.php
@@ -34,4 +34,25 @@ class BufferingLogger extends AbstractLogger
return $logs;
}
+
+ public function __destruct()
+ {
+ foreach ($this->logs as [$level, $message, $context]) {
+ if (false !== strpos($message, '{')) {
+ foreach ($context as $key => $val) {
+ if (null === $val || is_scalar($val) || (\is_object($val) && \is_callable([$val, '__toString']))) {
+ $message = str_replace("{{$key}}", $val, $message);
+ } elseif ($val instanceof \DateTimeInterface) {
+ $message = str_replace("{{$key}}", $val->format(\DateTime::RFC3339), $message);
+ } elseif (\is_object($val)) {
+ $message = str_replace("{{$key}}", '[object '.\get_class($val).']', $message);
+ } else {
+ $message = str_replace("{{$key}}", '['.\gettype($val).']', $message);
+ }
+ }
+ }
+
+ error_log(sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message));
+ }
+ }
}
diff --git a/src/Symfony/Component/ErrorHandler/Debug.php b/src/Symfony/Component/ErrorHandler/Debug.php
index 6f75dbf60e..f95334e01a 100644
--- a/src/Symfony/Component/ErrorHandler/Debug.php
+++ b/src/Symfony/Component/ErrorHandler/Debug.php
@@ -18,39 +18,19 @@ namespace Symfony\Component\ErrorHandler;
*/
class Debug
{
- private static $enabled = false;
-
- /**
- * Enables the debug tools.
- *
- * This method registers an error handler and an exception handler.
- */
- public static function enable(int $errorReportingLevel = E_ALL, bool $displayErrors = true): void
+ public static function enable(): ErrorHandler
{
- if (static::$enabled) {
- return;
- }
-
- static::$enabled = true;
-
- if (null !== $errorReportingLevel) {
- error_reporting($errorReportingLevel);
- } else {
- error_reporting(E_ALL);
- }
+ error_reporting(-1);
if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
ini_set('display_errors', 0);
- } elseif ($displayErrors && (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log'))) {
+ } elseif (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log')) {
// CLI - display errors only if they're not already logged to STDERR
ini_set('display_errors', 1);
}
- if ($displayErrors) {
- ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
- } else {
- ErrorHandler::register()->throwAt(0, true);
- }
DebugClassLoader::enable();
+
+ return ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
}
}
diff --git a/src/Symfony/Component/ErrorHandler/ErrorHandler.php b/src/Symfony/Component/ErrorHandler/ErrorHandler.php
index ab6df70bd8..8144f0de66 100644
--- a/src/Symfony/Component/ErrorHandler/ErrorHandler.php
+++ b/src/Symfony/Component/ErrorHandler/ErrorHandler.php
@@ -19,9 +19,10 @@ use Symfony\Component\ErrorHandler\ErrorEnhancer\ClassNotFoundErrorEnhancer;
use Symfony\Component\ErrorHandler\ErrorEnhancer\ErrorEnhancerInterface;
use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer;
use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer;
+use Symfony\Component\ErrorHandler\ErrorRenderer\CliErrorRenderer;
+use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
/**
* A generic ErrorHandler for the PHP engine.
@@ -45,10 +46,8 @@ use Symfony\Component\ErrorRenderer\Exception\FlattenException;
*
* @author Nicolas Grekas
* @author Grégoire Pineau
- *
- * @final since Symfony 4.3
*/
-class ErrorHandler
+final class ErrorHandler
{
private $levels = [
E_DEPRECATED => 'Deprecated',
@@ -145,10 +144,8 @@ class ErrorHandler
$handler->setExceptionHandler($p);
$prev[0]->setExceptionHandler($p);
}
- } elseif (null === $prev && !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
- $handler->setExceptionHandler([$handler, 'sendPhpResponse']);
} else {
- $handler->setExceptionHandler($prev);
+ $handler->setExceptionHandler($prev ?? [$handler, 'renderException']);
}
$handler->throwAt(E_ALL & $handler->thrownErrors, true);
@@ -280,7 +277,7 @@ class ErrorHandler
/**
* Sets a user exception handler.
*
- * @param callable|null $handler A handler that must support \Throwable instances that will be called on Exception
+ * @param callable(\Throwable $e)|null $handler
*
* @return callable|null The previous exception handler
*/
@@ -583,11 +580,7 @@ class ErrorHandler
}
$exceptionHandler = $this->exceptionHandler;
- if ((!\is_array($exceptionHandler) || !$exceptionHandler[0] instanceof self || 'sendPhpResponse' !== $exceptionHandler[1]) && !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
- $this->exceptionHandler = [$this, 'sendPhpResponse'];
- } else {
- $this->exceptionHandler = null;
- }
+ $this->exceptionHandler = null;
try {
if (null !== $exceptionHandler) {
return $exceptionHandler($exception);
@@ -684,36 +677,26 @@ class ErrorHandler
}
/**
- * Sends the error associated with the given Exception as a plain PHP response.
+ * Renders the given exception.
*
- * As this method is mainly called during Kernel boot, where nothing is yet
- * available, the Response content is always HTML.
+ * As this method is mainly called during boot where nothing is yet available,
+ * the output is always either HTML or CLI depending where PHP runs.
*/
- private function sendPhpResponse(\Throwable $exception)
+ private function renderException(\Throwable $exception): void
{
- $charset = ini_get('default_charset') ?: 'UTF-8';
- $statusCode = 500;
- $headers = [];
+ $renderer = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliErrorRenderer() : new HtmlErrorRenderer(0 !== $this->scopedErrors);
- if (class_exists(HtmlErrorRenderer::class)) {
- $exception = FlattenException::createFromThrowable($exception);
- $statusCode = $exception->getStatusCode();
- $headers = $exception->getHeaders();
- $response = (new HtmlErrorRenderer(0 !== $this->scopedErrors))->render($exception);
- } else {
- $message = htmlspecialchars($exception->getMessage(), ENT_COMPAT | ENT_SUBSTITUTE, $charset);
- $response = sprintf('%s', $charset, $message);
- }
+ $exception = $renderer->render($exception);
if (!headers_sent()) {
- header(sprintf('HTTP/1.0 %s', $statusCode));
- foreach ($headers as $name => $value) {
+ http_response_code($exception->getStatusCode());
+
+ foreach ($exception->getHeaders() as $name => $value) {
header($name.': '.$value, false);
}
- header('Content-Type: text/html; charset='.$charset);
}
- echo $response;
+ echo $exception->getAsString();
}
/**
diff --git a/src/Symfony/Component/ErrorHandler/ErrorRenderer/CliErrorRenderer.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/CliErrorRenderer.php
new file mode 100644
index 0000000000..fbe0b5bb23
--- /dev/null
+++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/CliErrorRenderer.php
@@ -0,0 +1,46 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\ErrorHandler\ErrorRenderer;
+
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+use Symfony\Component\VarDumper\Dumper\CliDumper;
+
+/**
+ * @author Nicolas Grekas
+ */
+class CliErrorRenderer implements ErrorRendererInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function render(\Throwable $exception): FlattenException
+ {
+ $cloner = new VarCloner();
+ $dumper = new class() extends CliDumper {
+ protected function supportsColors(): bool
+ {
+ $outputStream = $this->outputStream;
+ $this->outputStream = STDOUT;
+
+ try {
+ return parent::supportsColors();
+ } finally {
+ $this->outputStream = $outputStream;
+ }
+ }
+ };
+
+ return FlattenException::createFromThrowable($exception)
+ ->setAsString($dumper->dump($cloner->cloneVar($exception), true));
+ }
+}
diff --git a/src/Symfony/Component/ErrorHandler/ErrorRenderer/ErrorRendererInterface.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/ErrorRendererInterface.php
new file mode 100644
index 0000000000..aba196603f
--- /dev/null
+++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/ErrorRendererInterface.php
@@ -0,0 +1,27 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\ErrorHandler\ErrorRenderer;
+
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
+
+/**
+ * Formats an exception to be used as response content.
+ *
+ * @author Yonel Ceruto
+ */
+interface ErrorRendererInterface
+{
+ /**
+ * Renders a Throwable as a FlattenException.
+ */
+ public function render(\Throwable $exception): FlattenException;
+}
diff --git a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/HtmlErrorRenderer.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php
similarity index 96%
rename from src/Symfony/Component/ErrorRenderer/ErrorRenderer/HtmlErrorRenderer.php
rename to src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php
index a9d0af516d..92eeba2cf0 100644
--- a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/HtmlErrorRenderer.php
+++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php
@@ -9,10 +9,10 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\ErrorRenderer\ErrorRenderer;
+namespace Symfony\Component\ErrorHandler\ErrorRenderer;
use Psr\Log\LoggerInterface;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
@@ -52,23 +52,17 @@ class HtmlErrorRenderer implements ErrorRendererInterface
/**
* {@inheritdoc}
*/
- public static function getFormat(): string
+ public function render(\Throwable $exception): FlattenException
{
- return 'html';
- }
-
- /**
- * {@inheritdoc}
- */
- public function render(FlattenException $exception): string
- {
- return $this->renderException($exception);
+ $exception = FlattenException::createFromThrowable($exception, null, [
+ 'Content-Type' => 'text/html; charset='.$this->charset,
+ ]);
+
+ return $exception->setAsString($this->renderException($exception));
}
/**
* Gets the HTML content associated with the given exception.
- *
- * @internal
*/
public function getBody(FlattenException $exception): string
{
@@ -77,8 +71,6 @@ class HtmlErrorRenderer implements ErrorRendererInterface
/**
* Gets the stylesheet associated with the given exception.
- *
- * @internal
*/
public function getStylesheet(): string
{
@@ -91,11 +83,10 @@ class HtmlErrorRenderer implements ErrorRendererInterface
private function renderException(FlattenException $exception, string $debugTemplate = 'views/exception_full.html.php'): string
{
- $debug = $this->debug && ($exception->getHeaders()['X-Debug'] ?? true);
- $statusText = $this->escape($exception->getTitle());
+ $statusText = $this->escape($exception->getStatusText());
$statusCode = $this->escape($exception->getStatusCode());
- if (!$debug) {
+ if (!$this->debug) {
return $this->include('views/error.html.php', [
'statusText' => $statusText,
'statusCode' => $statusCode,
@@ -111,13 +102,13 @@ class HtmlErrorRenderer implements ErrorRendererInterface
'statusText' => $statusText,
'statusCode' => $statusCode,
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
- 'currentContent' => $request ? $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level')) : null,
+ 'currentContent' => $request ? $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level')) : '',
]);
}
- private function getAndCleanOutputBuffering(int $startObLevel): string
+ private function getAndCleanOutputBuffering(?int $startObLevel): string
{
- if (ob_get_level() <= $startObLevel) {
+ if (null === $startObLevel || ob_get_level() <= $startObLevel) {
return '';
}
@@ -321,7 +312,7 @@ class HtmlErrorRenderer implements ErrorRendererInterface
{
extract($context, EXTR_SKIP);
ob_start();
- include __DIR__.'/../Resources/'.$name;
+ include __DIR__ . '/../Resources/' .$name;
return trim(ob_get_clean());
}
diff --git a/src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php
new file mode 100644
index 0000000000..2485ee3f3a
--- /dev/null
+++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php
@@ -0,0 +1,50 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\ErrorHandler\ErrorRenderer;
+
+use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\Serializer\Exception\NotEncodableValueException;
+use Symfony\Component\Serializer\SerializerInterface;
+
+/**
+ * Formats an exception using Serializer for rendering.
+ *
+ * @author Nicolas Grekas
+ */
+class SerializerErrorRenderer
+{
+ private $serializer;
+ private $requestStack;
+ private $debug;
+
+ public function __construct(SerializerInterface $serializer, RequestStack $requestStack, bool $debug = true)
+ {
+ $this->serializer = $serializer;
+ $this->requestStack = $requestStack;
+ $this->debug = $debug;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render(\Throwable $exception): FlattenException
+ {
+ $format = $this->requestStack->getCurrentRequest()->getPreferredFormat();
+ $flattenException = FlattenException::createFromThrowable($exception);
+
+ try {
+ return $flattenException->setAsString($this->serializer->serialize($flattenException, $format, ['exception' => $exception]));
+ } catch (NotEncodableValueException $_) {
+ return (new HtmlErrorHandler($this->debug))->render($exception);
+ }
+ }
+}
diff --git a/src/Symfony/Component/ErrorRenderer/Exception/FlattenException.php b/src/Symfony/Component/ErrorHandler/Exception/FlattenException.php
similarity index 93%
rename from src/Symfony/Component/ErrorRenderer/Exception/FlattenException.php
rename to src/Symfony/Component/ErrorHandler/Exception/FlattenException.php
index dd86f5b74b..61af8a7e1d 100644
--- a/src/Symfony/Component/ErrorRenderer/Exception/FlattenException.php
+++ b/src/Symfony/Component/ErrorHandler/Exception/FlattenException.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\ErrorRenderer\Exception;
+namespace Symfony\Component\ErrorHandler\Exception;
use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException;
use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
@@ -25,7 +25,6 @@ use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
*/
class FlattenException extends LegacyFlattenException
{
- private $title;
private $message;
private $code;
private $previous;
@@ -33,9 +32,11 @@ class FlattenException extends LegacyFlattenException
private $traceAsString;
private $class;
private $statusCode;
+ private $statusText;
private $headers;
private $file;
private $line;
+ private $asString;
public static function create(\Exception $exception, $statusCode = null, array $headers = []): self
{
@@ -60,12 +61,12 @@ class FlattenException extends LegacyFlattenException
}
if (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) {
- $title = Response::$statusTexts[$statusCode];
+ $statusText = Response::$statusTexts[$statusCode];
} else {
- $title = 'Whoops, looks like something went wrong.';
+ $statusText = 'Whoops, looks like something went wrong.';
}
- $e->setTitle($title);
+ $e->setStatusText($statusText);
$e->setStatusCode($statusCode);
$e->setHeaders($headers);
$e->setTraceFromThrowable($exception);
@@ -171,14 +172,14 @@ class FlattenException extends LegacyFlattenException
return $this;
}
- public function getTitle()
+ public function getStatusText()
{
- return $this->title;
+ return $this->statusText;
}
- public function setTitle(string $title): self
+ public function setStatusText(string $statusText): self
{
- $this->title = $title;
+ $this->statusText = $statusText;
return $this;
}
@@ -355,8 +356,19 @@ class FlattenException extends LegacyFlattenException
return $this->traceAsString;
}
+ public function setAsString(?string $asString)
+ {
+ $this->asString = $asString;
+
+ return $this;
+ }
+
public function getAsString()
{
+ if (null !== $this->asString) {
+ return $this->asString;
+ }
+
$message = '';
$next = false;
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/css/error.css b/src/Symfony/Component/ErrorHandler/Resources/assets/css/error.css
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/css/error.css
rename to src/Symfony/Component/ErrorHandler/Resources/assets/css/error.css
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/css/exception.css b/src/Symfony/Component/ErrorHandler/Resources/assets/css/exception.css
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/css/exception.css
rename to src/Symfony/Component/ErrorHandler/Resources/assets/css/exception.css
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/css/exception_full.css b/src/Symfony/Component/ErrorHandler/Resources/assets/css/exception_full.css
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/css/exception_full.css
rename to src/Symfony/Component/ErrorHandler/Resources/assets/css/exception_full.css
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/chevron-right.svg b/src/Symfony/Component/ErrorHandler/Resources/assets/images/chevron-right.svg
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/chevron-right.svg
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/chevron-right.svg
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/favicon.png.base64 b/src/Symfony/Component/ErrorHandler/Resources/assets/images/favicon.png.base64
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/favicon.png.base64
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/favicon.png.base64
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-book.svg b/src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-book.svg
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-book.svg
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-book.svg
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-minus-square-o.svg b/src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-minus-square-o.svg
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-minus-square-o.svg
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-minus-square-o.svg
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-minus-square.svg b/src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-minus-square.svg
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-minus-square.svg
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-minus-square.svg
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-plus-square-o.svg b/src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-plus-square-o.svg
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-plus-square-o.svg
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-plus-square-o.svg
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-plus-square.svg b/src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-plus-square.svg
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-plus-square.svg
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-plus-square.svg
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-support.svg b/src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-support.svg
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/icon-support.svg
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/icon-support.svg
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/symfony-ghost.svg.php b/src/Symfony/Component/ErrorHandler/Resources/assets/images/symfony-ghost.svg.php
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/symfony-ghost.svg.php
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/symfony-ghost.svg.php
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/images/symfony-logo.svg b/src/Symfony/Component/ErrorHandler/Resources/assets/images/symfony-logo.svg
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/images/symfony-logo.svg
rename to src/Symfony/Component/ErrorHandler/Resources/assets/images/symfony-logo.svg
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/assets/js/exception.js b/src/Symfony/Component/ErrorHandler/Resources/assets/js/exception.js
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/assets/js/exception.js
rename to src/Symfony/Component/ErrorHandler/Resources/assets/js/exception.js
diff --git a/src/Symfony/Component/ErrorHandler/Resources/stubs/Debug.php b/src/Symfony/Component/ErrorHandler/Resources/stubs/Debug.php
deleted file mode 100644
index 2a3f8bed79..0000000000
--- a/src/Symfony/Component/ErrorHandler/Resources/stubs/Debug.php
+++ /dev/null
@@ -1,25 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Debug;
-
-if (!class_exists(Debug::class, false)) {
- class_alias(\Symfony\Component\ErrorHandler\Debug::class, Debug::class);
-}
-
-if (false) {
- /**
- * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Debug instead.
- */
- class Debug extends \Symfony\Component\ErrorHandler\Debug
- {
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/views/error.html.php b/src/Symfony/Component/ErrorHandler/Resources/views/error.html.php
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/views/error.html.php
rename to src/Symfony/Component/ErrorHandler/Resources/views/error.html.php
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/views/exception.html.php b/src/Symfony/Component/ErrorHandler/Resources/views/exception.html.php
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/views/exception.html.php
rename to src/Symfony/Component/ErrorHandler/Resources/views/exception.html.php
diff --git a/src/Symfony/Component/ErrorHandler/Resources/views/exception_full.html.php b/src/Symfony/Component/ErrorHandler/Resources/views/exception_full.html.php
new file mode 100644
index 0000000000..4d46d59de5
--- /dev/null
+++ b/src/Symfony/Component/ErrorHandler/Resources/views/exception_full.html.php
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+ = $_message; ?>
+
+
+
+
+
+
+
+
+
= $this->include('assets/images/symfony-logo.svg'); ?> Symfony Exception
+
+
+
+
+
+
+
+
+ = $this->include('views/exception.html.php', $context); ?>
+
+
+
+
+
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/views/logs.html.php b/src/Symfony/Component/ErrorHandler/Resources/views/logs.html.php
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/views/logs.html.php
rename to src/Symfony/Component/ErrorHandler/Resources/views/logs.html.php
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/views/trace.html.php b/src/Symfony/Component/ErrorHandler/Resources/views/trace.html.php
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/views/trace.html.php
rename to src/Symfony/Component/ErrorHandler/Resources/views/trace.html.php
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/views/traces.html.php b/src/Symfony/Component/ErrorHandler/Resources/views/traces.html.php
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/views/traces.html.php
rename to src/Symfony/Component/ErrorHandler/Resources/views/traces.html.php
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/views/traces_text.html.php b/src/Symfony/Component/ErrorHandler/Resources/views/traces_text.html.php
similarity index 100%
rename from src/Symfony/Component/ErrorRenderer/Resources/views/traces_text.html.php
rename to src/Symfony/Component/ErrorHandler/Resources/views/traces_text.html.php
diff --git a/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/ErrorRendererTest.php b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/ErrorRendererTest.php
new file mode 100644
index 0000000000..6ac134b793
--- /dev/null
+++ b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/ErrorRendererTest.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\ErrorHandler\Tests\ErrorRenderer;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRenderer;
+use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRendererInterface;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
+use Symfony\Component\Serializer\Encoder\JsonEncoder;
+use Symfony\Component\Serializer\Normalizer\ProblemNormalizer;
+use Symfony\Component\Serializer\Serializer;
+
+class ErrorRendererTest extends TestCase
+{
+ public function testDefaultContent()
+ {
+ $errorRenderer = new ErrorRenderer();
+
+ self::assertStringContainsString('The server returned a "500 Internal Server Error".
', $errorRenderer->render(new \RuntimeException(), 'html'));
+ }
+
+ public function testCustomContent()
+ {
+ $errorRenderer = new ErrorRenderer(new CustomHtmlErrorRenderer());
+
+ $this->assertSame('Foo', $errorRenderer->render(new \RuntimeException('Foo'), 'html'));
+ }
+
+ public function testSerializerContent()
+ {
+ $exception = new \RuntimeException('Foo');
+ $errorRenderer = new ErrorRenderer(null, new Serializer([new ProblemNormalizer()], [new JsonEncoder()]));
+
+ $this->assertSame('{"type":"https:\/\/tools.ietf.org\/html\/rfc2616#section-10","title":"An error occurred","status":500,"detail":"Internal Server Error"}', $errorRenderer->render($exception, 'json'));
+ }
+}
+
+class CustomHtmlErrorRenderer implements HtmlErrorRendererInterface
+{
+ public function render(FlattenException $exception): string
+ {
+ return $exception->getMessage();
+ }
+}
diff --git a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/HtmlErrorRendererTest.php b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php
similarity index 58%
rename from src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/HtmlErrorRendererTest.php
rename to src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php
index 4868d215c4..e2b81f20e5 100644
--- a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/HtmlErrorRendererTest.php
+++ b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php
@@ -9,21 +9,20 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\ErrorRenderer\Tests\ErrorRenderer;
+namespace Symfony\Component\ErrorHandler\Tests\ErrorRenderer;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
class HtmlErrorRendererTest extends TestCase
{
/**
* @dataProvider getRenderData
*/
- public function testRender(FlattenException $exception, ErrorRendererInterface $errorRenderer, string $expected)
+ public function testRender(FlattenException $exception, HtmlErrorRenderer $errorRenderer, string $expected)
{
- $this->assertStringMatchesFormat($expected, $errorRenderer->render($exception));
+ $this->assertStringMatchesFormat($expected, $errorRenderer->render($exception)->getAsString());
}
public function getRenderData(): iterable
@@ -55,17 +54,5 @@ HTML;
new HtmlErrorRenderer(false),
$expectedNonDebug,
];
-
- yield '->render() returns the HTML content WITHOUT stack traces in debug mode FORCING non-debug via X-Debug header' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo'), null, ['X-Debug' => false]),
- new HtmlErrorRenderer(true),
- $expectedNonDebug,
- ];
-
- yield '->render() returns the HTML content WITHOUT stack traces in non-debug mode EVEN FORCING debug via X-Debug header' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo'), null, ['X-Debug' => true]),
- new HtmlErrorRenderer(false),
- $expectedNonDebug,
- ];
}
}
diff --git a/src/Symfony/Component/ErrorRenderer/Tests/Exception/FlattenExceptionTest.php b/src/Symfony/Component/ErrorHandler/Tests/Exception/FlattenExceptionTest.php
similarity index 99%
rename from src/Symfony/Component/ErrorRenderer/Tests/Exception/FlattenExceptionTest.php
rename to src/Symfony/Component/ErrorHandler/Tests/Exception/FlattenExceptionTest.php
index dad78d1525..3413bd484e 100644
--- a/src/Symfony/Component/ErrorRenderer/Tests/Exception/FlattenExceptionTest.php
+++ b/src/Symfony/Component/ErrorHandler/Tests/Exception/FlattenExceptionTest.php
@@ -9,10 +9,10 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\ErrorRenderer\Tests\Exception;
+namespace Symfony\Component\ErrorHandler\Tests\Exception;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
diff --git a/src/Symfony/Component/ErrorHandler/composer.json b/src/Symfony/Component/ErrorHandler/composer.json
index dd5e0d0679..bbde24ad91 100644
--- a/src/Symfony/Component/ErrorHandler/composer.json
+++ b/src/Symfony/Component/ErrorHandler/composer.json
@@ -17,20 +17,18 @@
],
"require": {
"php": "^7.1.3",
- "psr/log": "~1.0"
+ "psr/log": "~1.0",
+ "symfony/debug": "^4.4",
+ "symfony/var-dumper": "^4.4|^5.0"
},
"require-dev": {
- "symfony/http-kernel": "^3.4|^4.0|^5.0"
- },
- "suggest": {
- "symfony/error-renderer": "For better error rendering"
+ "symfony/http-kernel": "^4.4|^5.0"
},
"conflict": {
- "symfony/http-kernel": "<3.4"
+ "symfony/http-kernel": "<4.4"
},
"autoload": {
"psr-4": { "Symfony\\Component\\ErrorHandler\\": "" },
- "classmap": [ "Resources/stubs/Debug.php" ],
"exclude-from-classmap": [
"/Tests/"
]
diff --git a/src/Symfony/Component/ErrorRenderer/.gitattributes b/src/Symfony/Component/ErrorRenderer/.gitattributes
deleted file mode 100644
index ebb9287043..0000000000
--- a/src/Symfony/Component/ErrorRenderer/.gitattributes
+++ /dev/null
@@ -1,3 +0,0 @@
-/Tests export-ignore
-/phpunit.xml.dist export-ignore
-/.gitignore export-ignore
diff --git a/src/Symfony/Component/ErrorRenderer/.gitignore b/src/Symfony/Component/ErrorRenderer/.gitignore
deleted file mode 100644
index c49a5d8df5..0000000000
--- a/src/Symfony/Component/ErrorRenderer/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-vendor/
-composer.lock
-phpunit.xml
diff --git a/src/Symfony/Component/ErrorRenderer/CHANGELOG.md b/src/Symfony/Component/ErrorRenderer/CHANGELOG.md
deleted file mode 100644
index 094072510d..0000000000
--- a/src/Symfony/Component/ErrorRenderer/CHANGELOG.md
+++ /dev/null
@@ -1,7 +0,0 @@
-CHANGELOG
-=========
-
-4.4.0
------
-
- * added the component
diff --git a/src/Symfony/Component/ErrorRenderer/Command/DebugCommand.php b/src/Symfony/Component/ErrorRenderer/Command/DebugCommand.php
deleted file mode 100644
index 58cb57b68c..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Command/DebugCommand.php
+++ /dev/null
@@ -1,125 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\Command;
-
-use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Exception\InvalidArgumentException;
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Style\SymfonyStyle;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
-
-/**
- * A console command for retrieving information about error renderers.
- *
- * @author Yonel Ceruto
- *
- * @internal
- */
-class DebugCommand extends Command
-{
- protected static $defaultName = 'debug:error-renderer';
-
- private $renderers;
- private $fileLinkFormatter;
-
- /**
- * @param ErrorRendererInterface[] $renderers
- */
- public function __construct(array $renderers, FileLinkFormatter $fileLinkFormatter = null)
- {
- $this->renderers = $renderers;
- $this->fileLinkFormatter = $fileLinkFormatter;
-
- parent::__construct();
- }
-
- /**
- * {@inheritdoc}
- */
- protected function configure(): void
- {
- $this
- ->addArgument('format', InputArgument::OPTIONAL, sprintf('Outputs a sample in a specific format (one of %s)', implode(', ', array_keys($this->renderers))))
- ->setDescription('Displays all available error renderers and their formats.')
- ->setHelp(<<<'EOF'
-The %command.name% command displays all available error renderers and
-their formats:
-
- php %command.full_name%
-
-Or output a sample in a specific format:
-
- php %command.full_name% json
-
-EOF
- )
- ;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $io = new SymfonyStyle($input, $output);
- $renderers = $this->renderers;
-
- if ($format = $input->getArgument('format')) {
- if (!isset($renderers[$format])) {
- throw new InvalidArgumentException(sprintf('No error renderer found for format "%s". Known format are %s.', $format, implode(', ', array_keys($this->renderers))));
- }
-
- $exception = FlattenException::createFromThrowable(new \Exception('This is a sample exception.'), 500, ['X-Debug' => false]);
- $io->writeln($renderers[$format]->render($exception));
- } else {
- $tableRows = [];
- foreach ($renderers as $format => $renderer) {
- $tableRows[] = [sprintf('%s', $format), $this->formatClassLink(\get_class($renderer))];
- }
-
- $io->title('Error Renderers');
- $io->text('The following error renderers are available:');
- $io->newLine();
- $io->table(['Format', 'Class'], $tableRows);
- }
-
- return 0;
- }
-
- private function formatClassLink(string $class): string
- {
- if ('' === $fileLink = $this->getFileLink($class)) {
- return $class;
- }
-
- return sprintf('%s>', $fileLink, $class);
- }
-
- private function getFileLink(string $class): string
- {
- if (null === $this->fileLinkFormatter) {
- return '';
- }
-
- try {
- $r = new \ReflectionClass($class);
- } catch (\ReflectionException $e) {
- return '';
- }
-
- return $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine());
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/DependencyInjection/ErrorRendererPass.php b/src/Symfony/Component/ErrorRenderer/DependencyInjection/ErrorRendererPass.php
deleted file mode 100644
index 1e297b7de1..0000000000
--- a/src/Symfony/Component/ErrorRenderer/DependencyInjection/ErrorRendererPass.php
+++ /dev/null
@@ -1,71 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\DependencyInjection;
-
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
-
-/**
- * @author Yonel Ceruto
- */
-class ErrorRendererPass implements CompilerPassInterface
-{
- private $rendererService;
- private $rendererTag;
- private $debugCommandService;
-
- public function __construct(string $rendererService = 'error_renderer', string $rendererTag = 'error_renderer.renderer', string $debugCommandService = 'console.command.error_renderer_debug')
- {
- $this->rendererService = $rendererService;
- $this->rendererTag = $rendererTag;
- $this->debugCommandService = $debugCommandService;
- }
-
- /**
- * {@inheritdoc}
- */
- public function process(ContainerBuilder $container)
- {
- if (!$container->hasDefinition($this->rendererService)) {
- return;
- }
-
- $renderers = [];
- foreach ($container->findTaggedServiceIds($this->rendererTag, true) as $serviceId => $tags) {
- /** @var ErrorRendererInterface $class */
- $class = $container->getDefinition($serviceId)->getClass();
-
- foreach ($tags as $tag) {
- $format = $tag['format'] ?? $class::getFormat();
- $priority = $tag['priority'] ?? 0;
- if (!isset($renderers[$priority][$format])) {
- $renderers[$priority][$format] = new Reference($serviceId);
- }
- }
- }
-
- if ($renderers) {
- ksort($renderers);
- $renderers = array_merge(...$renderers);
- }
-
- $definition = $container->getDefinition($this->rendererService);
- $definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $renderers));
-
- if ($container->hasDefinition($this->debugCommandService)) {
- $container->getDefinition($this->debugCommandService)->replaceArgument(0, $renderers);
- }
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/DependencyInjection/LazyLoadingErrorRenderer.php b/src/Symfony/Component/ErrorRenderer/DependencyInjection/LazyLoadingErrorRenderer.php
deleted file mode 100644
index 82936a29af..0000000000
--- a/src/Symfony/Component/ErrorRenderer/DependencyInjection/LazyLoadingErrorRenderer.php
+++ /dev/null
@@ -1,44 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\DependencyInjection;
-
-use Psr\Container\ContainerInterface;
-use Symfony\Component\ErrorRenderer\ErrorRenderer;
-
-/**
- * Lazily loads error renderers from the dependency injection container.
- *
- * @author Yonel Ceruto
- */
-class LazyLoadingErrorRenderer extends ErrorRenderer
-{
- private $container;
- private $initialized = [];
-
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- }
-
- /**
- * {@inheritdoc}
- */
- public function render($exception, string $format = 'html'): string
- {
- if (!isset($this->initialized[$format]) && $this->container->has($format)) {
- $this->addRenderer($this->container->get($format), $format);
- $this->initialized[$format] = true;
- }
-
- return parent::render($exception, $format);
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/ErrorRenderer.php b/src/Symfony/Component/ErrorRenderer/ErrorRenderer.php
deleted file mode 100644
index da984bdd18..0000000000
--- a/src/Symfony/Component/ErrorRenderer/ErrorRenderer.php
+++ /dev/null
@@ -1,77 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer;
-
-use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
-use Symfony\Component\ErrorRenderer\Exception\ErrorRendererNotFoundException;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-/**
- * Formats an exception to be used as response content.
- *
- * It delegates to implementations of ErrorRendererInterface depending on the format.
- *
- * @see ErrorRendererInterface
- *
- * @author Yonel Ceruto
- */
-class ErrorRenderer
-{
- private $renderers = [];
-
- /**
- * @param ErrorRendererInterface[] $renderers
- */
- public function __construct(iterable $renderers)
- {
- foreach ($renderers as $renderer) {
- $this->addRenderer($renderer);
- }
- }
-
- /**
- * Registers an error renderer that is format specific.
- *
- * By passing an explicit format you can register a renderer for a different format than what
- * ErrorRendererInterface::getFormat() would return in order to register the same renderer for
- * several format aliases.
- */
- public function addRenderer(ErrorRendererInterface $renderer, string $format = null): self
- {
- $this->renderers[$format ?? $renderer::getFormat()] = $renderer;
-
- return $this;
- }
-
- /**
- * Renders an Exception and returns the Response content.
- *
- * @param \Throwable|FlattenException $exception A \Throwable or FlattenException instance
- * @param string $format The request format (html, json, xml, etc.)
- *
- * @return string The Response content as a string
- *
- * @throws ErrorRendererNotFoundException if no renderer is found
- */
- public function render($exception, string $format = 'html'): string
- {
- if (!isset($this->renderers[$format])) {
- throw new ErrorRendererNotFoundException(sprintf('No error renderer found for format "%s".', $format));
- }
-
- if ($exception instanceof \Throwable) {
- $exception = FlattenException::createFromThrowable($exception);
- }
-
- return $this->renderers[$format]->render($exception);
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/ErrorRendererInterface.php b/src/Symfony/Component/ErrorRenderer/ErrorRenderer/ErrorRendererInterface.php
deleted file mode 100644
index 5c0d580602..0000000000
--- a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/ErrorRendererInterface.php
+++ /dev/null
@@ -1,32 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\ErrorRenderer;
-
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-/**
- * Interface for classes that can render errors in a specific format.
- *
- * @author Yonel Ceruto
- */
-interface ErrorRendererInterface
-{
- /**
- * Gets the format this renderer can return errors as.
- */
- public static function getFormat(): string;
-
- /**
- * Returns the response content of the rendered exception.
- */
- public function render(FlattenException $exception): string;
-}
diff --git a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/JsonErrorRenderer.php b/src/Symfony/Component/ErrorRenderer/ErrorRenderer/JsonErrorRenderer.php
deleted file mode 100644
index d708fb0f15..0000000000
--- a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/JsonErrorRenderer.php
+++ /dev/null
@@ -1,60 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\ErrorRenderer;
-
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-/**
- * @author Yonel Ceruto
- */
-class JsonErrorRenderer implements ErrorRendererInterface
-{
- private $debug;
-
- public function __construct(bool $debug = false)
- {
- $this->debug = $debug;
- }
-
- /**
- * {@inheritdoc}
- */
- public static function getFormat(): string
- {
- return 'json';
- }
-
- /**
- * {@inheritdoc}
- */
- public function render(FlattenException $exception): string
- {
- $debug = $this->debug && ($exception->getHeaders()['X-Debug'] ?? true);
-
- if ($debug) {
- $message = $exception->getMessage();
- } else {
- $message = 404 === $exception->getStatusCode() ? 'Sorry, the page you are looking for could not be found.' : 'Whoops, looks like something went wrong.';
- }
-
- $content = [
- 'title' => $exception->getTitle(),
- 'status' => $exception->getStatusCode(),
- 'detail' => $message,
- ];
- if ($debug) {
- $content['exceptions'] = $exception->toArray();
- }
-
- return (string) json_encode($content, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS | JSON_PRESERVE_ZERO_FRACTION);
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/TxtErrorRenderer.php b/src/Symfony/Component/ErrorRenderer/ErrorRenderer/TxtErrorRenderer.php
deleted file mode 100644
index 2bafb2cfb4..0000000000
--- a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/TxtErrorRenderer.php
+++ /dev/null
@@ -1,104 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\ErrorRenderer;
-
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-/**
- * @author Yonel Ceruto
- */
-class TxtErrorRenderer implements ErrorRendererInterface
-{
- private $debug;
-
- public function __construct(bool $debug = false)
- {
- $this->debug = $debug;
- }
-
- /**
- * {@inheritdoc}
- */
- public static function getFormat(): string
- {
- return 'txt';
- }
-
- /**
- * {@inheritdoc}
- */
- public function render(FlattenException $exception): string
- {
- $debug = $this->debug && ($exception->getHeaders()['X-Debug'] ?? true);
-
- if ($debug) {
- $message = $exception->getMessage();
- } else {
- $message = 404 === $exception->getStatusCode() ? 'Sorry, the page you are looking for could not be found.' : 'Whoops, looks like something went wrong.';
- }
-
- $content = sprintf("[title] %s\n", $exception->getTitle());
- $content .= sprintf("[status] %s\n", $exception->getStatusCode());
- $content .= sprintf("[detail] %s\n", $message);
-
- if ($debug) {
- foreach ($exception->toArray() as $i => $e) {
- $content .= sprintf("[%d] %s: %s\n", $i + 1, $e['class'], $e['message']);
- foreach ($e['trace'] as $trace) {
- if ($trace['function']) {
- $content .= sprintf('at %s%s%s(%s) ', $trace['class'], $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
- }
- if (isset($trace['file'], $trace['line'])) {
- $content .= $this->formatPath($trace['file'], $trace['line']);
- }
- $content .= "\n";
- }
- }
- }
-
- return $content;
- }
-
- private function formatPath(string $path, int $line): string
- {
- $file = preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path;
-
- return sprintf('in %s %s', $path, 0 < $line ? ' line '.$line : '');
- }
-
- /**
- * Formats an array as a string.
- */
- private function formatArgs(array $args): string
- {
- $result = [];
- foreach ($args as $key => $item) {
- if ('object' === $item[0]) {
- $formattedValue = sprintf('object(%s)', $item[1]);
- } elseif ('array' === $item[0]) {
- $formattedValue = sprintf('array(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
- } elseif ('null' === $item[0]) {
- $formattedValue = 'null';
- } elseif ('boolean' === $item[0]) {
- $formattedValue = strtolower(var_export($item[1], true));
- } elseif ('resource' === $item[0]) {
- $formattedValue = 'resource';
- } else {
- $formattedValue = str_replace("\n", '', var_export($item[1], true));
- }
-
- $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
- }
-
- return implode(', ', $result);
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/XmlErrorRenderer.php b/src/Symfony/Component/ErrorRenderer/ErrorRenderer/XmlErrorRenderer.php
deleted file mode 100644
index 290e0a63ff..0000000000
--- a/src/Symfony/Component/ErrorRenderer/ErrorRenderer/XmlErrorRenderer.php
+++ /dev/null
@@ -1,125 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\ErrorRenderer;
-
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-/**
- * @author Yonel Ceruto
- */
-class XmlErrorRenderer implements ErrorRendererInterface
-{
- private $debug;
- private $charset;
-
- public function __construct(bool $debug = false, string $charset = null)
- {
- $this->debug = $debug;
- $this->charset = $charset ?: (ini_get('default_charset') ?: 'UTF-8');
- }
-
- /**
- * {@inheritdoc}
- */
- public static function getFormat(): string
- {
- return 'xml';
- }
-
- /**
- * {@inheritdoc}
- */
- public function render(FlattenException $exception): string
- {
- $debug = $this->debug && ($exception->getHeaders()['X-Debug'] ?? true);
- $title = $this->escapeXml($exception->getTitle());
- if ($debug) {
- $message = $this->escapeXml($exception->getMessage());
- } else {
- $message = 404 === $exception->getStatusCode() ? 'Sorry, the page you are looking for could not be found.' : 'Whoops, looks like something went wrong.';
- }
- $statusCode = $this->escapeXml($exception->getStatusCode());
- $charset = $this->escapeXml($this->charset);
-
- $exceptions = '';
- if ($debug) {
- $exceptions .= '';
- foreach ($exception->toArray() as $e) {
- $exceptions .= sprintf('', $e['class'], $this->escapeXml($e['message']));
- foreach ($e['trace'] as $trace) {
- $exceptions .= '';
- if ($trace['function']) {
- $exceptions .= sprintf('at %s%s%s(%s) ', $trace['class'], $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
- }
- if (isset($trace['file'], $trace['line'])) {
- $exceptions .= $this->formatPath($trace['file'], $trace['line']);
- }
- $exceptions .= '';
- }
- $exceptions .= '';
- }
- $exceptions .= '';
- }
-
- return <<
-
- {$title}
- {$statusCode}
- {$message}
- {$exceptions}
-
-EOF;
- }
-
- /**
- * XML-encodes a string.
- */
- private function escapeXml(string $str): string
- {
- return htmlspecialchars($str, ENT_COMPAT | ENT_SUBSTITUTE, $this->charset);
- }
-
- private function formatPath(string $path, int $line): string
- {
- $file = $this->escapeXml(preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path);
-
- return sprintf('in %s %s', $this->escapeXml($path), 0 < $line ? ' line '.$line : '');
- }
-
- /**
- * Formats an array as a string.
- */
- private function formatArgs(array $args): string
- {
- $result = [];
- foreach ($args as $key => $item) {
- if ('object' === $item[0]) {
- $formattedValue = sprintf('object(%s)', $item[1]);
- } elseif ('array' === $item[0]) {
- $formattedValue = sprintf('array(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
- } elseif ('null' === $item[0]) {
- $formattedValue = 'null';
- } elseif ('boolean' === $item[0]) {
- $formattedValue = strtolower(var_export($item[1], true));
- } elseif ('resource' === $item[0]) {
- $formattedValue = 'resource';
- } else {
- $formattedValue = str_replace("\n", '', $this->escapeXml(var_export($item[1], true)));
- }
-
- $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeXml($key), $formattedValue);
- }
-
- return implode(', ', $result);
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/Exception/ErrorRendererNotFoundException.php b/src/Symfony/Component/ErrorRenderer/Exception/ErrorRendererNotFoundException.php
deleted file mode 100644
index 4020ced161..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Exception/ErrorRendererNotFoundException.php
+++ /dev/null
@@ -1,16 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\Exception;
-
-class ErrorRendererNotFoundException extends \RuntimeException
-{
-}
diff --git a/src/Symfony/Component/ErrorRenderer/LICENSE b/src/Symfony/Component/ErrorRenderer/LICENSE
deleted file mode 100644
index 1a1869751d..0000000000
--- a/src/Symfony/Component/ErrorRenderer/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2019 Fabien Potencier
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is furnished
-to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/src/Symfony/Component/ErrorRenderer/README.md b/src/Symfony/Component/ErrorRenderer/README.md
deleted file mode 100644
index 272c2924d8..0000000000
--- a/src/Symfony/Component/ErrorRenderer/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-ErrorRenderer Component
-======================
-
-The ErrorRenderer component provides tools to display errors and exceptions.
-
-Resources
----------
-
- * [Contributing](https://symfony.com/doc/current/contributing/index.html)
- * [Report issues](https://github.com/symfony/symfony/issues) and
- [send Pull Requests](https://github.com/symfony/symfony/pulls)
- in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/src/Symfony/Component/ErrorRenderer/Resources/views/exception_full.html.php b/src/Symfony/Component/ErrorRenderer/Resources/views/exception_full.html.php
deleted file mode 100644
index 7ce8de0666..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Resources/views/exception_full.html.php
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
- = $_message; ?>
-
-
-
-
-
-
-
-
= $this->include('assets/images/symfony-logo.svg'); ?> Symfony Exception
-
-
-
-
-
-
-
- = $this->include('views/exception.html.php', $context); ?>
-
-
-
-
-
diff --git a/src/Symfony/Component/ErrorRenderer/Tests/Command/DebugCommandTest.php b/src/Symfony/Component/ErrorRenderer/Tests/Command/DebugCommandTest.php
deleted file mode 100644
index c5a9768c8b..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Tests/Command/DebugCommandTest.php
+++ /dev/null
@@ -1,88 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\Tests\Command;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Console\Application;
-use Symfony\Component\Console\Tester\CommandTester;
-use Symfony\Component\ErrorRenderer\Command\DebugCommand;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\JsonErrorRenderer;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\TxtErrorRenderer;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\XmlErrorRenderer;
-
-class DebugCommandTest extends TestCase
-{
- public function testAvailableRenderers()
- {
- $tester = $this->createCommandTester();
- $ret = $tester->execute([], ['decorated' => false]);
-
- $this->assertEquals(0, $ret, 'Returns 0 in case of success');
- $this->assertSame(<<getDisplay(true));
- }
-
- public function testFormatArgument()
- {
- $tester = $this->createCommandTester();
- $ret = $tester->execute(['format' => 'json'], ['decorated' => false]);
-
- $this->assertEquals(0, $ret, 'Returns 0 in case of success');
- $this->assertSame(<<getDisplay(true));
- }
-
- private function createCommandTester()
- {
- $command = new DebugCommand([
- 'json' => new JsonErrorRenderer(false),
- 'xml' => new XmlErrorRenderer(false),
- 'txt' => new TxtErrorRenderer(false),
- ]);
-
- $application = new Application();
- $application->add($command);
-
- return new CommandTester($application->find('debug:error-renderer'));
- }
-
- public function testInvalidFormat()
- {
- $this->expectException('Symfony\Component\Console\Exception\InvalidArgumentException');
- $this->expectExceptionMessage('No error renderer found for format "foo". Known format are json, xml, txt.');
- $tester = $this->createCommandTester();
- $tester->execute(['format' => 'foo'], ['decorated' => false]);
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/Tests/DependencyInjection/ErrorRendererPassTest.php b/src/Symfony/Component/ErrorRenderer/Tests/DependencyInjection/ErrorRendererPassTest.php
deleted file mode 100644
index e69fd860b8..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Tests/DependencyInjection/ErrorRendererPassTest.php
+++ /dev/null
@@ -1,67 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\Tests\DependencyInjection;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\DependencyInjection\ServiceLocator;
-use Symfony\Component\ErrorRenderer\DependencyInjection\ErrorRendererPass;
-use Symfony\Component\ErrorRenderer\DependencyInjection\LazyLoadingErrorRenderer;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\JsonErrorRenderer;
-
-class ErrorRendererPassTest extends TestCase
-{
- public function testProcess()
- {
- $container = new ContainerBuilder();
- $container->setParameter('kernel.debug', true);
- $definition = $container->register('error_renderer', LazyLoadingErrorRenderer::class)
- ->addArgument([])
- ;
- $container->register('error_renderer.renderer.html', HtmlErrorRenderer::class)
- ->addTag('error_renderer.renderer')
- ;
- $container->register('error_renderer.renderer.json', JsonErrorRenderer::class)
- ->addTag('error_renderer.renderer')
- ;
-
- (new ErrorRendererPass())->process($container);
-
- $serviceLocatorDefinition = $container->getDefinition((string) $definition->getArgument(0));
- $this->assertSame(ServiceLocator::class, $serviceLocatorDefinition->getClass());
-
- $expected = [
- 'html' => new ServiceClosureArgument(new Reference('error_renderer.renderer.html')),
- 'json' => new ServiceClosureArgument(new Reference('error_renderer.renderer.json')),
- ];
- $this->assertEquals($expected, $serviceLocatorDefinition->getArgument(0));
- }
-
- public function testServicesAreOrderedAccordingToPriority()
- {
- $container = new ContainerBuilder();
- $definition = $container->register('error_renderer')->setArguments([null]);
- $container->register('r2')->addTag('error_renderer.renderer', ['format' => 'json', 'priority' => 100]);
- $container->register('r1')->addTag('error_renderer.renderer', ['format' => 'json', 'priority' => 200]);
- $container->register('r3')->addTag('error_renderer.renderer', ['format' => 'json']);
- (new ErrorRendererPass())->process($container);
-
- $expected = [
- 'json' => new ServiceClosureArgument(new Reference('r1')),
- ];
- $serviceLocatorDefinition = $container->getDefinition((string) $definition->getArgument(0));
- $this->assertEquals($expected, $serviceLocatorDefinition->getArgument(0));
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/Tests/DependencyInjection/LazyLoadingErrorRendererTest.php b/src/Symfony/Component/ErrorRenderer/Tests/DependencyInjection/LazyLoadingErrorRendererTest.php
deleted file mode 100644
index 5811a0c026..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Tests/DependencyInjection/LazyLoadingErrorRendererTest.php
+++ /dev/null
@@ -1,66 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\Tests\DependencyInjection;
-
-use PHPUnit\Framework\TestCase;
-use Psr\Container\ContainerInterface;
-use Symfony\Component\ErrorRenderer\DependencyInjection\LazyLoadingErrorRenderer;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-class LazyLoadingErrorRendererTest extends TestCase
-{
- public function testInvalidErrorRenderer()
- {
- $this->expectException('Symfony\Component\ErrorRenderer\Exception\ErrorRendererNotFoundException');
- $this->expectExceptionMessage('No error renderer found for format "foo".');
- $container = $this->getMockBuilder(ContainerInterface::class)->getMock();
- $container->expects($this->once())->method('has')->with('foo')->willReturn(false);
-
- $exception = FlattenException::createFromThrowable(new \Exception('Foo'));
- (new LazyLoadingErrorRenderer($container))->render($exception, 'foo');
- }
-
- public function testCustomErrorRenderer()
- {
- $container = $this->getMockBuilder(ContainerInterface::class)->getMock();
- $container
- ->expects($this->once())
- ->method('has')
- ->with('foo')
- ->willReturn(true)
- ;
- $container
- ->expects($this->once())
- ->method('get')
- ->willReturn(new FooErrorRenderer())
- ;
-
- $errorRenderer = new LazyLoadingErrorRenderer($container);
-
- $exception = FlattenException::createFromThrowable(new \RuntimeException('Foo'));
- $this->assertSame('Foo', $errorRenderer->render($exception, 'foo'));
- }
-}
-
-class FooErrorRenderer implements ErrorRendererInterface
-{
- public static function getFormat(): string
- {
- return 'foo';
- }
-
- public function render(FlattenException $exception): string
- {
- return $exception->getMessage();
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/JsonErrorRendererTest.php b/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/JsonErrorRendererTest.php
deleted file mode 100644
index 55e6d5cdf2..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/JsonErrorRendererTest.php
+++ /dev/null
@@ -1,76 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\Tests\ErrorRenderer;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\JsonErrorRenderer;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-class JsonErrorRendererTest extends TestCase
-{
- /**
- * @dataProvider getRenderData
- */
- public function testRender(FlattenException $exception, ErrorRendererInterface $errorRenderer, string $expected)
- {
- $this->assertStringMatchesFormat($expected, $errorRenderer->render($exception));
- }
-
- public function getRenderData(): iterable
- {
- $expectedDebug = <<render() returns the JSON content WITH stack traces in debug mode' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo')),
- new JsonErrorRenderer(true),
- $expectedDebug,
- ];
-
- yield '->render() returns the JSON content WITHOUT stack traces in non-debug mode' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo')),
- new JsonErrorRenderer(false),
- $expectedNonDebug,
- ];
-
- yield '->render() returns the JSON content WITHOUT stack traces in debug mode FORCING non-debug via X-Debug header' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo'), null, ['X-Debug' => false]),
- new JsonErrorRenderer(true),
- $expectedNonDebug,
- ];
-
- yield '->render() returns the JSON content WITHOUT stack traces in non-debug mode EVEN FORCING debug via X-Debug header' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo'), null, ['X-Debug' => true]),
- new JsonErrorRenderer(false),
- $expectedNonDebug,
- ];
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/TxtErrorRendererTest.php b/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/TxtErrorRendererTest.php
deleted file mode 100644
index b6c1570df8..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/TxtErrorRendererTest.php
+++ /dev/null
@@ -1,69 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\Tests\ErrorRenderer;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\TxtErrorRenderer;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-class TxtErrorRendererTest extends TestCase
-{
- /**
- * @dataProvider getRenderData
- */
- public function testRender(FlattenException $exception, ErrorRendererInterface $errorRenderer, string $expected)
- {
- $this->assertStringMatchesFormat($expected, $errorRenderer->render($exception));
- }
-
- public function getRenderData(): iterable
- {
- $expectedDebug = <<render() returns the TXT content WITH stack traces in debug mode' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo')),
- new TxtErrorRenderer(true),
- $expectedDebug,
- ];
-
- yield '->render() returns the TXT content WITHOUT stack traces in non-debug mode' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo')),
- new TxtErrorRenderer(false),
- $expectedNonDebug,
- ];
-
- yield '->render() returns the TXT content WITHOUT stack traces in debug mode FORCING non-debug via X-Debug header' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo'), null, ['X-Debug' => false]),
- new TxtErrorRenderer(true),
- $expectedNonDebug,
- ];
-
- yield '->render() returns the TXT content WITHOUT stack traces in non-debug mode EVEN FORCING debug via X-Debug header' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo'), null, ['X-Debug' => true]),
- new TxtErrorRenderer(false),
- $expectedNonDebug,
- ];
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/XmlErrorRendererTest.php b/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/XmlErrorRendererTest.php
deleted file mode 100644
index 3a756720ec..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRenderer/XmlErrorRendererTest.php
+++ /dev/null
@@ -1,75 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\Tests\ErrorRenderer;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\XmlErrorRenderer;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-class XmlErrorRendererTest extends TestCase
-{
- /**
- * @dataProvider getRenderData
- */
- public function testRender(FlattenException $exception, ErrorRendererInterface $errorRenderer, string $expected)
- {
- $this->assertStringMatchesFormat($expected, $errorRenderer->render($exception));
- }
-
- public function getRenderData(): iterable
- {
- $expectedDebug = <<
-
- Internal Server Error
- 500
- Foo
- %A
-
-XML;
-
- $expectedNonDebug = <<
-
- Internal Server Error
- 500
- Whoops, looks like something went wrong.
-
-
-XML;
-
- yield '->render() returns the XML content WITH stack traces in debug mode' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo')),
- new XmlErrorRenderer(true),
- $expectedDebug,
- ];
-
- yield '->render() returns the XML content WITHOUT stack traces in non-debug mode' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo')),
- new XmlErrorRenderer(false),
- $expectedNonDebug,
- ];
-
- yield '->render() returns the XML content WITHOUT stack traces in debug mode FORCING non-debug via X-Debug header' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo'), null, ['X-Debug' => false]),
- new XmlErrorRenderer(true),
- $expectedNonDebug,
- ];
-
- yield '->render() returns the XML content WITHOUT stack traces in non-debug mode EVEN FORCING debug via X-Debug header' => [
- FlattenException::createFromThrowable(new \RuntimeException('Foo'), null, ['X-Debug' => true]),
- new XmlErrorRenderer(false),
- $expectedNonDebug,
- ];
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRendererTest.php b/src/Symfony/Component/ErrorRenderer/Tests/ErrorRendererTest.php
deleted file mode 100644
index 11ef6a7d7e..0000000000
--- a/src/Symfony/Component/ErrorRenderer/Tests/ErrorRendererTest.php
+++ /dev/null
@@ -1,56 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\ErrorRenderer\Tests;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\ErrorRenderer\ErrorRenderer;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
-
-class ErrorRendererTest extends TestCase
-{
- public function testErrorRendererNotFound()
- {
- $this->expectException('Symfony\Component\ErrorRenderer\Exception\ErrorRendererNotFoundException');
- $this->expectExceptionMessage('No error renderer found for format "foo".');
- $exception = FlattenException::createFromThrowable(new \Exception('foo'));
- (new ErrorRenderer([]))->render($exception, 'foo');
- }
-
- public function testInvalidErrorRenderer()
- {
- $this->expectException('TypeError');
- new ErrorRenderer([new \stdClass()]);
- }
-
- public function testCustomErrorRenderer()
- {
- $renderers = [new FooErrorRenderer()];
- $errorRenderer = new ErrorRenderer($renderers);
-
- $exception = FlattenException::createFromThrowable(new \RuntimeException('Foo'));
- $this->assertSame('Foo', $errorRenderer->render($exception, 'foo'));
- }
-}
-
-class FooErrorRenderer implements ErrorRendererInterface
-{
- public static function getFormat(): string
- {
- return 'foo';
- }
-
- public function render(FlattenException $exception): string
- {
- return $exception->getMessage();
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/composer.json b/src/Symfony/Component/ErrorRenderer/composer.json
deleted file mode 100644
index 90351239fc..0000000000
--- a/src/Symfony/Component/ErrorRenderer/composer.json
+++ /dev/null
@@ -1,47 +0,0 @@
-{
- "name": "symfony/error-renderer",
- "type": "library",
- "description": "Symfony ErrorRenderer Component",
- "keywords": [],
- "homepage": "https://symfony.com",
- "license": "MIT",
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Yonel Ceruto",
- "email": "yonelceruto@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "require": {
- "php": "^7.1.3",
- "psr/log": "~1.0",
- "symfony/debug": "^4.4"
- },
- "require-dev": {
- "symfony/console": "^4.4",
- "symfony/dependency-injection": "^4.4",
- "symfony/http-kernel": "^4.4"
- },
- "conflict": {
- "symfony/http-kernel": "<4.4"
- },
- "autoload": {
- "psr-4": { "Symfony\\Component\\ErrorRenderer\\": "" },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "minimum-stability": "dev",
- "extra": {
- "branch-alias": {
- "dev-master": "4.4-dev"
- }
- }
-}
diff --git a/src/Symfony/Component/ErrorRenderer/phpunit.xml.dist b/src/Symfony/Component/ErrorRenderer/phpunit.xml.dist
deleted file mode 100644
index c4c29459f3..0000000000
--- a/src/Symfony/Component/ErrorRenderer/phpunit.xml.dist
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
- ./Tests/
-
-
-
-
-
- ./
-
- ./Tests
- ./vendor
-
-
-
-
diff --git a/src/Symfony/Component/HttpKernel/Controller/ErrorController.php b/src/Symfony/Component/HttpKernel/Controller/ErrorController.php
index a86fa5c5cf..3e5447928b 100644
--- a/src/Symfony/Component/HttpKernel/Controller/ErrorController.php
+++ b/src/Symfony/Component/HttpKernel/Controller/ErrorController.php
@@ -11,9 +11,8 @@
namespace Symfony\Component\HttpKernel\Controller;
-use Symfony\Component\ErrorRenderer\ErrorRenderer;
-use Symfony\Component\ErrorRenderer\Exception\ErrorRendererNotFoundException;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
@@ -30,26 +29,22 @@ class ErrorController
private $controller;
private $errorRenderer;
- public function __construct(HttpKernelInterface $kernel, $controller, ErrorRenderer $errorRenderer)
+ public function __construct(HttpKernelInterface $kernel, $controller, ErrorRendererInterface $errorRenderer)
{
$this->kernel = $kernel;
$this->controller = $controller;
$this->errorRenderer = $errorRenderer;
}
- public function __invoke(Request $request, FlattenException $exception): Response
+ public function __invoke(\Throwable $exception): Response
{
- try {
- return new Response($this->errorRenderer->render($exception, $request->getPreferredFormat()), $exception->getStatusCode(), $exception->getHeaders());
- } catch (ErrorRendererNotFoundException $_) {
- return new Response($this->errorRenderer->render($exception), $exception->getStatusCode(), $exception->getHeaders());
- }
+ $exception = $this->errorRenderer->render($exception);
+
+ return new Response($exception->getAsString(), $exception->getStatusCode(), $exception->getHeaders());
}
public function preview(Request $request, int $code): Response
{
- $exception = FlattenException::createFromThrowable(new \Exception('This is a sample exception.'), $code, ['X-Debug' => false]);
-
/*
* This Request mimics the parameters set by
* \Symfony\Component\HttpKernel\EventListener\ErrorListener::duplicateRequest, with
@@ -57,7 +52,7 @@ class ErrorController
*/
$subRequest = $request->duplicate(null, null, [
'_controller' => $this->controller,
- 'exception' => $exception,
+ 'exception' => new \Exception('This is a sample exception.'),
'logger' => null,
'showException' => false,
]);
diff --git a/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php
index 08e79c53e1..0a00a2e40e 100644
--- a/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php
+++ b/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php
@@ -11,7 +11,7 @@
namespace Symfony\Component\HttpKernel\DataCollector;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
diff --git a/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php b/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php
index 9a16cde741..fa3300b73e 100644
--- a/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php
+++ b/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php
@@ -123,7 +123,7 @@ class ErrorListener implements EventSubscriberInterface
{
$attributes = [
'_controller' => $this->controller,
- 'exception' => FlattenException::createFromThrowable($exception),
+ 'exception' => $exception,
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
];
$request = $request->duplicate(null, null, $attributes);
diff --git a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php
index dc2fd818ce..aa4349428a 100644
--- a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php
+++ b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php
@@ -12,7 +12,7 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Psr\Log\LoggerInterface;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ErrorControllerTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ErrorControllerTest.php
index 4a64af3ab1..7548dc19e4 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ErrorControllerTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ErrorControllerTest.php
@@ -12,10 +12,9 @@
namespace Symfony\Component\HttpKernel\Tests\Controller;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\ErrorRenderer\ErrorRenderer;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer;
-use Symfony\Component\ErrorRenderer\ErrorRenderer\JsonErrorRenderer;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRenderer;
+use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ErrorController;
@@ -31,7 +30,7 @@ class ErrorControllerTest extends TestCase
public function testInvokeController(Request $request, FlattenException $exception, int $statusCode, string $content)
{
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
- $errorRenderer = new ErrorRenderer([new HtmlErrorRenderer(), new JsonErrorRenderer()]);
+ $errorRenderer = new ErrorRenderer(new HtmlErrorRenderer());
$controller = new ErrorController($kernel, null, $errorRenderer);
$response = $controller($request, $exception);
@@ -55,33 +54,6 @@ class ErrorControllerTest extends TestCase
'The server returned a "404 Not Found".',
];
- $request = new Request();
- $request->attributes->set('_format', 'json');
- yield 'custom format via _format attribute' => [
- $request,
- FlattenException::createFromThrowable(new \Exception('foo')),
- 500,
- '{"title": "Internal Server Error","status": 500,"detail": "Whoops, looks like something went wrong."}',
- ];
-
- $request = new Request();
- $request->headers->set('Accept', 'application/json');
- yield 'custom format via Accept header' => [
- $request,
- FlattenException::createFromThrowable(new HttpException(405, 'Invalid request.')),
- 405,
- '{"title": "Method Not Allowed","status": 405,"detail": "Whoops, looks like something went wrong."}',
- ];
-
- $request = new Request();
- $request->headers->set('Content-Type', 'application/json');
- yield 'custom format via Content-Type header' => [
- $request,
- FlattenException::createFromThrowable(new HttpException(405, 'Invalid request.')),
- 405,
- '{"title": "Method Not Allowed","status": 405,"detail": "Whoops, looks like something went wrong."}',
- ];
-
$request = new Request();
$request->attributes->set('_format', 'unknown');
yield 'default HTML format for unknown formats' => [
@@ -116,7 +88,7 @@ class ErrorControllerTest extends TestCase
)
->willReturn($response = new Response());
- $controller = new ErrorController($kernel, $_controller, new ErrorRenderer([]));
+ $controller = new ErrorController($kernel, $_controller, new ErrorRenderer());
$this->assertSame($response, $controller->preview(new Request(), $code));
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php
index 8b1d1317d8..d1fc578b13 100644
--- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php
@@ -12,7 +12,7 @@
namespace Symfony\Component\HttpKernel\Tests\DataCollector;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector;
diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json
index 51f0d919a7..ba6ab33de8 100644
--- a/src/Symfony/Component/HttpKernel/composer.json
+++ b/src/Symfony/Component/HttpKernel/composer.json
@@ -18,7 +18,6 @@
"require": {
"php": "^7.1.3",
"symfony/error-handler": "^4.4|^5.0",
- "symfony/error-renderer": "^4.4|^5.0",
"symfony/event-dispatcher": "^4.4",
"symfony/http-foundation": "^4.4|^5.0",
"symfony/polyfill-ctype": "^1.8",
@@ -40,7 +39,6 @@
"symfony/templating": "^3.4|^4.0|^5.0",
"symfony/translation": "^4.2|^5.0",
"symfony/translation-contracts": "^1.1|^2",
- "symfony/var-dumper": "^4.1.1|^5.0",
"psr/cache": "~1.0",
"twig/twig": "^1.34|^2.4|^3.0"
},
@@ -53,15 +51,13 @@
"symfony/console": ">=5",
"symfony/dependency-injection": "<4.3",
"symfony/translation": "<4.2",
- "symfony/var-dumper": "<4.1.1",
"twig/twig": "<1.34|<2.4,>=2"
},
"suggest": {
"symfony/browser-kit": "",
"symfony/config": "",
"symfony/console": "",
- "symfony/dependency-injection": "",
- "symfony/var-dumper": ""
+ "symfony/dependency-injection": ""
},
"autoload": {
"psr-4": { "Symfony\\Component\\HttpKernel\\": "" },
diff --git a/src/Symfony/Component/Messenger/EventListener/SendFailedMessageToFailureTransportListener.php b/src/Symfony/Component/Messenger/EventListener/SendFailedMessageToFailureTransportListener.php
index 0aa8fd5ea7..8c84cf7992 100644
--- a/src/Symfony/Component/Messenger/EventListener/SendFailedMessageToFailureTransportListener.php
+++ b/src/Symfony/Component/Messenger/EventListener/SendFailedMessageToFailureTransportListener.php
@@ -11,7 +11,7 @@
namespace Symfony\Component\Messenger\EventListener;
use Psr\Log\LoggerInterface;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent;
use Symfony\Component\Messenger\Exception\HandlerFailedException;
diff --git a/src/Symfony/Component/Messenger/Stamp/RedeliveryStamp.php b/src/Symfony/Component/Messenger/Stamp/RedeliveryStamp.php
index 49bbf2f778..60c3898b08 100644
--- a/src/Symfony/Component/Messenger/Stamp/RedeliveryStamp.php
+++ b/src/Symfony/Component/Messenger/Stamp/RedeliveryStamp.php
@@ -11,7 +11,7 @@
namespace Symfony\Component\Messenger\Stamp;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\Messenger\Envelope;
/**
diff --git a/src/Symfony/Component/Messenger/Tests/Stamp/RedeliveryStampTest.php b/src/Symfony/Component/Messenger/Tests/Stamp/RedeliveryStampTest.php
index c55a670bf3..7fcabfc2d6 100644
--- a/src/Symfony/Component/Messenger/Tests/Stamp/RedeliveryStampTest.php
+++ b/src/Symfony/Component/Messenger/Tests/Stamp/RedeliveryStampTest.php
@@ -12,7 +12,7 @@
namespace Symfony\Component\Messenger\Tests\Stamp;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\ErrorRenderer\Exception\FlattenException;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\Messenger\Stamp\RedeliveryStamp;
class RedeliveryStampTest extends TestCase
diff --git a/src/Symfony/Component/Messenger/composer.json b/src/Symfony/Component/Messenger/composer.json
index 48f85f2b63..62b5240b82 100644
--- a/src/Symfony/Component/Messenger/composer.json
+++ b/src/Symfony/Component/Messenger/composer.json
@@ -25,7 +25,6 @@
"doctrine/persistence": "~1.0",
"symfony/console": "^3.4|^4.0|^5.0",
"symfony/dependency-injection": "^3.4.19|^4.1.8|^5.0",
- "symfony/error-renderer": "^4.4|^5.0",
"symfony/event-dispatcher": "^4.3|^5.0",
"symfony/http-kernel": "^4.4",
"symfony/process": "^3.4|^4.0|^5.0",
diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md
index 0958f50540..7f213186e3 100644
--- a/src/Symfony/Component/Serializer/CHANGELOG.md
+++ b/src/Symfony/Component/Serializer/CHANGELOG.md
@@ -6,6 +6,7 @@ CHANGELOG
* deprecated the `XmlEncoder::TYPE_CASE_ATTRIBUTES` constant, use `XmlEncoder::TYPE_CAST_ATTRIBUTES` instead
* added option to output a UTF-8 BOM in CSV encoder via `CsvEncoder::OUTPUT_UTF8_BOM_KEY` context option
+ * added `ProblemNormalizer` to normalize errors according to the API Problem spec (RFC 7807)
4.3.0
-----
diff --git a/src/Symfony/Component/Serializer/Normalizer/ProblemNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ProblemNormalizer.php
new file mode 100644
index 0000000000..0569c2923b
--- /dev/null
+++ b/src/Symfony/Component/Serializer/Normalizer/ProblemNormalizer.php
@@ -0,0 +1,74 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Serializer\Normalizer;
+
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
+
+/**
+ * Normalizes errors according to the API Problem spec (RFC 7807).
+ *
+ * @see https://tools.ietf.org/html/rfc7807
+ *
+ * @author Kévin Dunglas
+ * @author Yonel Ceruto
+ */
+class ProblemNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface
+{
+ private $debug;
+ private $defaultContext = [
+ 'type' => 'https://tools.ietf.org/html/rfc2616#section-10',
+ 'title' => 'An error occurred',
+ ];
+
+ public function __construct(bool $debug = false, array $defaultContext = [])
+ {
+ $this->debug = $debug;
+ $this->defaultContext = $defaultContext + $this->defaultContext;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function normalize($exception, $format = null, array $context = [])
+ {
+ $context += $this->defaultContext;
+
+ $data = [
+ 'type' => $context['type'],
+ 'title' => $context['title'],
+ 'status' => $context['status'] ?? $exception->getStatusCode(),
+ 'detail' => $this->debug ? $exception->getMessage() : $exception->getStatusText(),
+ ];
+ if ($this->debug) {
+ $data['class'] = $exception->getClass();
+ $data['trace'] = $exception->getTrace();
+ }
+
+ return $data;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function supportsNormalization($data, $format = null): bool
+ {
+ return $data instanceof FlattenException;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasCacheableSupportsMethod(): bool
+ {
+ return true;
+ }
+}
diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ProblemNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ProblemNormalizerTest.php
new file mode 100644
index 0000000000..4a754ac5b7
--- /dev/null
+++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ProblemNormalizerTest.php
@@ -0,0 +1,48 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Serializer\Tests\Normalizer;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\ErrorHandler\Exception\FlattenException;
+use Symfony\Component\Serializer\Normalizer\ProblemNormalizer;
+
+class ProblemNormalizerTest extends TestCase
+{
+ /**
+ * @var ProblemNormalizer
+ */
+ private $normalizer;
+
+ protected function setUp(): void
+ {
+ $this->normalizer = new ProblemNormalizer(false);
+ }
+
+ public function testSupportNormalization()
+ {
+ $this->assertTrue($this->normalizer->supportsNormalization(FlattenException::createFromThrowable(new \Exception())));
+ $this->assertFalse($this->normalizer->supportsNormalization(new \Exception()));
+ $this->assertFalse($this->normalizer->supportsNormalization(new \stdClass()));
+ }
+
+ public function testNormalize()
+ {
+ $expected = [
+ 'type' => 'https://tools.ietf.org/html/rfc2616#section-10',
+ 'title' => 'An error occurred',
+ 'status' => 500,
+ 'detail' => 'Internal Server Error',
+ ];
+
+ $this->assertSame($expected, $this->normalizer->normalize(FlattenException::createFromThrowable(new \RuntimeException('Error'))));
+ }
+}
diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json
index 45c185a364..dfee783304 100644
--- a/src/Symfony/Component/Serializer/composer.json
+++ b/src/Symfony/Component/Serializer/composer.json
@@ -20,17 +20,18 @@
"symfony/polyfill-ctype": "~1.8"
},
"require-dev": {
- "symfony/yaml": "^3.4|^4.0|^5.0",
- "symfony/config": "^3.4|^4.0|^5.0",
- "symfony/property-access": "^3.4|^4.0|^5.0",
- "symfony/http-foundation": "^3.4|^4.0|^5.0",
+ "doctrine/annotations": "~1.0",
+ "doctrine/cache": "~1.0",
+ "phpdocumentor/reflection-docblock": "^3.0|^4.0",
"symfony/cache": "^3.4|^4.0|^5.0",
+ "symfony/config": "^3.4|^4.0|^5.0",
+ "symfony/dependency-injection": "^3.4|^4.0|^5.0",
+ "symfony/error-handler": "^4.4|^5.0",
+ "symfony/http-foundation": "^3.4|^4.0|^5.0",
+ "symfony/property-access": "^3.4|^4.0|^5.0",
"symfony/property-info": "^3.4.13|~4.0|^5.0",
"symfony/validator": "^3.4|^4.0|^5.0",
- "doctrine/annotations": "~1.0",
- "symfony/dependency-injection": "^3.4|^4.0|^5.0",
- "doctrine/cache": "~1.0",
- "phpdocumentor/reflection-docblock": "^3.0|^4.0"
+ "symfony/yaml": "^3.4|^4.0|^5.0"
},
"conflict": {
"phpdocumentor/type-resolver": "<0.2.1",