Deprecating error templates for non-html formats and using ErrorRenderer
This commit is contained in:
parent
a7852c0da8
commit
bf0c24a634
@ -151,6 +151,74 @@ TwigBridge
|
||||
|
||||
* Deprecated to pass `$rootDir` and `$fileLinkFormatter` as 5th and 6th argument respectively to the
|
||||
`DebugCommand::__construct()` method, swap the variables position.
|
||||
|
||||
TwigBundle
|
||||
----------
|
||||
|
||||
* Deprecated default value `twig.controller.exception::showAction` of the `twig.exception_controller` configuration option,
|
||||
set it to `null` instead. This will also change the default error response format according to https://tools.ietf.org/html/rfc7807
|
||||
for `json`, `xml`, `atom` and `txt` formats:
|
||||
|
||||
Before:
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": 404,
|
||||
"message": "Sorry, the page you are looking for could not be found"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
```json
|
||||
{
|
||||
"title": "Not Found",
|
||||
"status": 404,
|
||||
"detail": "Sorry, the page you are looking for could not be found"
|
||||
}
|
||||
```
|
||||
|
||||
* Deprecated the `ExceptionController` and all built-in error templates, use the error renderer mechanism of the `ErrorRenderer` component
|
||||
* Deprecated loading custom error templates in non-html formats. Custom HTML error pages based on Twig keep working as before:
|
||||
|
||||
Before (`templates/bundles/TwigBundle/Exception/error.jsonld.twig`):
|
||||
```twig
|
||||
{
|
||||
"@id": "https://example.com",
|
||||
"@type": "error",
|
||||
"@context": {
|
||||
"title": "{{ status_text }}",
|
||||
"code": {{ status_code }},
|
||||
"message": "{{ exception.message }}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After (`App\ErrorRenderer\JsonLdErrorRenderer`):
|
||||
```php
|
||||
class JsonLdErrorRenderer implements ErrorRendererInterface
|
||||
{
|
||||
public static function getFormat(): string
|
||||
{
|
||||
return 'jsonld';
|
||||
}
|
||||
|
||||
public function render(FlattenException $exception): string
|
||||
{
|
||||
return json_encode([
|
||||
'@id' => 'https://example.com',
|
||||
'@type' => 'error',
|
||||
'@context' => [
|
||||
'title' => $exception->getTitle(),
|
||||
'code' => $exception->getStatusCode(),
|
||||
'message' => $exception->getMessage(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Configure your rendering service tagging it with `error_renderer.renderer`.
|
||||
|
||||
Validator
|
||||
---------
|
||||
|
@ -467,6 +467,8 @@ TwigBundle
|
||||
* The default value (`false`) of the `twig.strict_variables` configuration option has been changed to `%kernel.debug%`.
|
||||
* The `transchoice` tag and filter have been removed, use the `trans` ones instead with a `%count%` parameter.
|
||||
* Removed support for legacy templates directories `src/Resources/views/` and `src/Resources/<BundleName>/views/`, use `templates/` and `templates/bundles/<BundleName>/` instead.
|
||||
* The default value (`twig.controller.exception::showAction`) of the `twig.exception_controller` configuration option has been changed to `null`.
|
||||
* Removed `ExceptionController` class and all built-in error templates
|
||||
|
||||
TwigBridge
|
||||
----------
|
||||
|
@ -7,3 +7,4 @@ framework:
|
||||
|
||||
twig:
|
||||
strict_variables: '%kernel.debug%'
|
||||
exception_controller: ~
|
||||
|
@ -52,7 +52,7 @@
|
||||
"symfony/stopwatch": "^3.4|^4.0|^5.0",
|
||||
"symfony/translation": "^4.3|^5.0",
|
||||
"symfony/templating": "^3.4|^4.0|^5.0",
|
||||
"symfony/twig-bundle": "^3.4|^4.0|^5.0",
|
||||
"symfony/twig-bundle": "^4.4|^5.0",
|
||||
"symfony/validator": "^4.1|^5.0",
|
||||
"symfony/var-dumper": "^4.3|^5.0",
|
||||
"symfony/workflow": "^4.3|^5.0",
|
||||
@ -80,6 +80,7 @@
|
||||
"symfony/stopwatch": "<3.4",
|
||||
"symfony/translation": "<4.3",
|
||||
"symfony/twig-bridge": "<4.1.1",
|
||||
"symfony/twig-bundle": "<4.4",
|
||||
"symfony/validator": "<4.1",
|
||||
"symfony/workflow": "<4.3"
|
||||
},
|
||||
|
@ -70,6 +70,6 @@ class JsonLoginTest extends AbstractWebTestCase
|
||||
|
||||
$this->assertSame(400, $response->getStatusCode());
|
||||
$this->assertSame('application/json', $response->headers->get('Content-Type'));
|
||||
$this->assertArraySubset(['error' => ['code' => 400, 'message' => 'Bad Request']], json_decode($response->getContent(), true));
|
||||
$this->assertArraySubset(['title' => 'Bad Request', 'status' => 400, 'detail' => 'Invalid JSON.'], json_decode($response->getContent(), true));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\SecurityBundle\Tests\Functional\app;
|
||||
|
||||
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\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ExceptionController
|
||||
{
|
||||
private $errorRenderer;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->errorRenderer = new ErrorRenderer([
|
||||
new HtmlErrorRenderer(),
|
||||
new JsonErrorRenderer(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function __invoke(Request $request, FlattenException $exception)
|
||||
{
|
||||
return new Response($this->errorRenderer->render($exception, $request->getPreferredFormat()), $exception->getStatusCode());
|
||||
}
|
||||
}
|
@ -12,5 +12,4 @@
|
||||
return [
|
||||
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
|
||||
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
|
||||
new Symfony\Bundle\TwigBundle\TwigBundle(),
|
||||
];
|
||||
|
@ -1,5 +1,5 @@
|
||||
imports:
|
||||
- { resource: ./../config/default.yml }
|
||||
- { resource: ./../config/framework.yml }
|
||||
services:
|
||||
Symfony\Component\Ldap\Ldap:
|
||||
arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
|
||||
|
@ -11,10 +11,8 @@
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
|
||||
use Symfony\Bundle\SecurityBundle\SecurityBundle;
|
||||
use Symfony\Bundle\TwigBundle\TwigBundle;
|
||||
|
||||
return [
|
||||
new FrameworkBundle(),
|
||||
new SecurityBundle(),
|
||||
new TwigBundle(),
|
||||
];
|
||||
|
@ -1,5 +1,5 @@
|
||||
imports:
|
||||
- { resource: ./../config/default.yml }
|
||||
- { resource: ./../config/framework.yml }
|
||||
|
||||
services:
|
||||
# alias the service so we can access it in the tests
|
||||
|
@ -2,3 +2,4 @@
|
||||
twig:
|
||||
debug: '%kernel.debug%'
|
||||
strict_variables: '%kernel.debug%'
|
||||
exception_controller: Symfony\Bundle\SecurityBundle\Tests\Functional\app\ExceptionController
|
||||
|
@ -20,7 +20,7 @@
|
||||
"ext-xml": "*",
|
||||
"symfony/config": "^4.2|^5.0",
|
||||
"symfony/dependency-injection": "^4.2|^5.0",
|
||||
"symfony/http-kernel": "^4.3",
|
||||
"symfony/http-kernel": "^4.4",
|
||||
"symfony/security-core": "^4.3",
|
||||
"symfony/security-csrf": "^4.2|^5.0",
|
||||
"symfony/security-guard": "^4.2|^5.0",
|
||||
@ -33,10 +33,10 @@
|
||||
"symfony/css-selector": "^3.4|^4.0|^5.0",
|
||||
"symfony/dom-crawler": "^3.4|^4.0|^5.0",
|
||||
"symfony/form": "^3.4|^4.0|^5.0",
|
||||
"symfony/framework-bundle": "^4.2|^5.0",
|
||||
"symfony/framework-bundle": "^4.4|^5.0",
|
||||
"symfony/http-foundation": "^3.4|^4.0|^5.0",
|
||||
"symfony/translation": "^3.4|^4.0|^5.0",
|
||||
"symfony/twig-bundle": "^4.2|^5.0",
|
||||
"symfony/twig-bundle": "^4.4|^5.0",
|
||||
"symfony/twig-bridge": "^3.4|^4.0|^5.0",
|
||||
"symfony/process": "^3.4|^4.0|^5.0",
|
||||
"symfony/validator": "^3.4|^4.0|^5.0",
|
||||
@ -48,9 +48,9 @@
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/browser-kit": "<4.2",
|
||||
"symfony/twig-bundle": "<4.2",
|
||||
"symfony/twig-bundle": "<4.4",
|
||||
"symfony/var-dumper": "<3.4",
|
||||
"symfony/framework-bundle": "<4.2",
|
||||
"symfony/framework-bundle": "<4.4",
|
||||
"symfony/console": "<3.4"
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -6,6 +6,9 @@ CHANGELOG
|
||||
|
||||
* marked the `TemplateIterator` as `internal`
|
||||
* added HTML comment to beginning and end of `exception_full.html.twig`
|
||||
* added a new `TwigHtmlErrorRenderer` for `html` format, integrated with the `ErrorRenderer` component
|
||||
* deprecated `ExceptionController` class and all built-in error templates in favor of the new error renderer mechanism
|
||||
* deprecated default value `twig.controller.exception::showAction` of `twig.exception_controller` configuration option, set it to `null` instead
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
@ -19,12 +19,16 @@ use Twig\Environment;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Loader\ExistsLoaderInterface;
|
||||
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use the ErrorRenderer component instead.', ExceptionController::class), E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* ExceptionController renders error or exception pages for a given
|
||||
* FlattenException.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Matthias Pigulla <mp@webfactory.de>
|
||||
*
|
||||
* @deprecated since Symfony 4.4, use the ErrorRenderer component instead.
|
||||
*/
|
||||
class ExceptionController
|
||||
{
|
||||
|
@ -11,8 +11,10 @@
|
||||
|
||||
namespace Symfony\Bundle\TwigBundle\Controller;
|
||||
|
||||
use Symfony\Component\ErrorRenderer\ErrorRenderer;
|
||||
use Symfony\Component\ErrorRenderer\Exception\FlattenException;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
@ -26,16 +28,22 @@ class PreviewErrorController
|
||||
{
|
||||
protected $kernel;
|
||||
protected $controller;
|
||||
private $errorRenderer;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, $controller)
|
||||
public function __construct(HttpKernelInterface $kernel, $controller, ErrorRenderer $errorRenderer = null)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
$this->controller = $controller;
|
||||
$this->errorRenderer = $errorRenderer;
|
||||
}
|
||||
|
||||
public function previewErrorPageAction(Request $request, $code)
|
||||
{
|
||||
$exception = FlattenException::createFromThrowable(new \Exception('Something has intentionally gone wrong.'), $code);
|
||||
$exception = FlattenException::createFromThrowable(new \Exception('Something has intentionally gone wrong.'), $code, ['X-Debug' => false]);
|
||||
|
||||
if (null === $this->controller && null !== $this->errorRenderer) {
|
||||
return new Response($this->errorRenderer->render($exception, $request->getPreferredFormat()), $code);
|
||||
}
|
||||
|
||||
/*
|
||||
* This Request mimics the parameters set by
|
||||
|
@ -34,7 +34,13 @@ class Configuration implements ConfigurationInterface
|
||||
|
||||
$rootNode
|
||||
->children()
|
||||
->scalarNode('exception_controller')->defaultValue('twig.controller.exception::showAction')->end()
|
||||
->scalarNode('exception_controller')
|
||||
->defaultValue(static function () {
|
||||
@trigger_error('Relying on the default value ("twig.controller.exception::showAction") of the "twig.exception_controller" configuration option is deprecated since Symfony 4.4, set it to "null" explicitly instead, which will be the new default in 5.0.', E_USER_DEPRECATED);
|
||||
|
||||
return 'twig.controller.exception::showAction';
|
||||
})
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
|
||||
|
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\TwigBundle\ErrorRenderer;
|
||||
|
||||
use Symfony\Component\ErrorRenderer\ErrorRenderer\ErrorRendererInterface;
|
||||
use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer;
|
||||
use Symfony\Component\ErrorRenderer\Exception\FlattenException;
|
||||
use Twig\Environment;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Loader\ExistsLoaderInterface;
|
||||
|
||||
/**
|
||||
* Provides the ability to render custom Twig-based HTML error pages
|
||||
* in non-debug mode, otherwise falls back to HtmlErrorRenderer.
|
||||
*
|
||||
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||
*/
|
||||
class TwigHtmlErrorRenderer implements ErrorRendererInterface
|
||||
{
|
||||
private $twig;
|
||||
private $htmlErrorRenderer;
|
||||
private $debug;
|
||||
|
||||
public function __construct(Environment $twig, HtmlErrorRenderer $htmlErrorRenderer, bool $debug = false)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
$this->htmlErrorRenderer = $htmlErrorRenderer;
|
||||
$this->debug = $debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getFormat(): string
|
||||
{
|
||||
return 'html';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render(FlattenException $exception): string
|
||||
{
|
||||
$debug = $this->debug && ($exception->getHeaders()['X-Debug'] ?? true);
|
||||
|
||||
if ($debug) {
|
||||
return $this->htmlErrorRenderer->render($exception);
|
||||
}
|
||||
|
||||
$template = $this->findTemplate($exception->getStatusCode());
|
||||
|
||||
if (null === $template) {
|
||||
return $this->htmlErrorRenderer->render($exception);
|
||||
}
|
||||
|
||||
return $this->twig->render($template, [
|
||||
'legacy' => false, // to be removed in 5.0
|
||||
'exception' => $exception,
|
||||
'status_code' => $exception->getStatusCode(),
|
||||
'status_text' => $exception->getTitle(),
|
||||
]);
|
||||
}
|
||||
|
||||
private function findTemplate(int $statusCode): ?string
|
||||
{
|
||||
$template = sprintf('@Twig/Exception/error%s.html.twig', $statusCode);
|
||||
if ($this->templateExists($template)) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
$template = '@Twig/Exception/error.html.twig';
|
||||
if ($this->templateExists($template)) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* To be removed in 5.0.
|
||||
*
|
||||
* Use instead:
|
||||
*
|
||||
* $this->twig->getLoader()->exists($template)
|
||||
*/
|
||||
private function templateExists(string $template): bool
|
||||
{
|
||||
$loader = $this->twig->getLoader();
|
||||
if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) {
|
||||
return $loader->exists($template);
|
||||
}
|
||||
|
||||
try {
|
||||
$loader->getSourceContext($template);
|
||||
|
||||
return true;
|
||||
} catch (LoaderError $e) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -139,11 +139,13 @@
|
||||
<service id="twig.controller.exception" class="Symfony\Bundle\TwigBundle\Controller\ExceptionController" public="true">
|
||||
<argument type="service" id="twig" />
|
||||
<argument>%kernel.debug%</argument>
|
||||
<deprecated>The "%service_id%" service is deprecated since Symfony 4.4.</deprecated>
|
||||
</service>
|
||||
|
||||
<service id="twig.controller.preview_error" class="Symfony\Bundle\TwigBundle\Controller\PreviewErrorController" public="true">
|
||||
<argument type="service" id="http_kernel" />
|
||||
<argument>%twig.exception_listener.controller%</argument>
|
||||
<argument type="service" id="error_renderer" on-invalid="null" />
|
||||
</service>
|
||||
|
||||
<service id="twig.configurator.environment" class="Symfony\Bundle\TwigBundle\DependencyInjection\Configurator\EnvironmentConfigurator">
|
||||
@ -158,5 +160,12 @@
|
||||
<service id="twig.runtime_loader" class="Twig\RuntimeLoader\ContainerRuntimeLoader">
|
||||
<argument /> <!-- runtime locator -->
|
||||
</service>
|
||||
|
||||
<service id="twig.error_renderer.html" class="Symfony\Bundle\TwigBundle\ErrorRenderer\TwigHtmlErrorRenderer">
|
||||
<tag name="error_renderer.renderer" priority="1" />
|
||||
<argument type="service" id="twig" />
|
||||
<argument type="service" id="error_renderer.renderer.html" />
|
||||
<argument>%kernel.debug%</argument>
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
@ -1 +1,2 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{{ include('@Twig/Exception/error.xml.twig') }}
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
/*
|
||||
{{ status_code }} {{ status_text }}
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
{% if legacy is not defined or legacy %}
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{% endif %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
/*
|
||||
{{ status_code }} {{ status_text }}
|
||||
|
||||
|
@ -1 +1,2 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{{ { 'error': { 'code': status_code, 'message': status_text } }|json_encode|raw }}
|
||||
|
@ -1 +1,2 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{{ include('@Twig/Exception/error.xml.twig') }}
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
Oops! An Error Occurred
|
||||
=======================
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
<?xml version="1.0" encoding="{{ _charset }}" ?>
|
||||
|
||||
<error code="{{ status_code }}" message="{{ status_text }}" />
|
||||
|
@ -1 +1,2 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{{ include('@Twig/Exception/exception.xml.twig', { exception: exception }) }}
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
/*
|
||||
{{ include('@Twig/Exception/exception.txt.twig', { exception: exception }) }}
|
||||
*/
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
/*
|
||||
{{ include('@Twig/Exception/exception.txt.twig', { exception: exception }) }}
|
||||
*/
|
||||
|
@ -1 +1,2 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{{ { 'error': { 'code': status_code, 'message': status_text, 'exception': exception.toarray } }|json_encode|raw }}
|
||||
|
@ -1 +1,2 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{{ include('@Twig/Exception/exception.xml.twig', { exception: exception }) }}
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
[exception] {{ status_code ~ ' | ' ~ status_text ~ ' | ' ~ exception.class }}
|
||||
[message] {{ exception.message }}
|
||||
{% for i, e in exception.toarray %}
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
<?xml version="1.0" encoding="{{ _charset }}" ?>
|
||||
|
||||
<error code="{{ status_code }}" message="{{ status_text }}">
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
<traces>
|
||||
{% for trace in exception.trace %}
|
||||
<trace>
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{# This file is based on WebProfilerBundle/Resources/views/Profiler/base_js.html.twig.
|
||||
If you make any change in this file, verify the same change is needed in the other file. #}
|
||||
<script{% if csp_script_nonce is defined and csp_script_nonce %} nonce="{{ csp_script_nonce }}"{% endif %}>/*<![CDATA[*/
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{# This file is based on WebProfilerBundle/Resources/views/Profiler/profiler.css.twig.
|
||||
If you make any change in this file, verify the same change is needed in the other file. #}
|
||||
:root {
|
||||
|
@ -1,3 +1,4 @@
|
||||
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
|
||||
{% block before_html %}{% endblock %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
@ -18,6 +18,9 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
class ExceptionControllerTest extends TestCase
|
||||
{
|
||||
public function testShowActionCanBeForcedToShowErrorPage()
|
||||
|
@ -21,6 +21,7 @@ class ConfigurationTest extends TestCase
|
||||
{
|
||||
$input = [
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
'form_themes' => ['form_div_layout.html.twig'],
|
||||
];
|
||||
|
||||
@ -42,10 +43,23 @@ class ConfigurationTest extends TestCase
|
||||
$this->assertFalse($config['strict_variables']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @expectedDeprecation Relying on the default value ("twig.controller.exception::showAction") of the "twig.exception_controller" configuration option is deprecated since Symfony 4.4, set it to "null" explicitly instead, which will be the new default in 5.0.
|
||||
*/
|
||||
public function testGetExceptionControllerDefault()
|
||||
{
|
||||
$processor = new Processor();
|
||||
$config = $processor->processConfiguration(new Configuration(), [[]]);
|
||||
|
||||
$this->assertSame('twig.controller.exception::showAction', $config['exception_controller']);
|
||||
}
|
||||
|
||||
public function testGlobalsAreNotNormalized()
|
||||
{
|
||||
$input = [
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
'globals' => ['some-global' => true],
|
||||
];
|
||||
|
||||
@ -59,6 +73,7 @@ class ConfigurationTest extends TestCase
|
||||
{
|
||||
$input = [
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
'globals' => ['global' => ['some-key' => 'some-value']],
|
||||
];
|
||||
|
||||
|
@ -4,4 +4,5 @@ $container->loadFromExtension('twig', [
|
||||
'autoescape_service' => 'my_project.some_bundle.template_escaping_guesser',
|
||||
'autoescape_service_method' => 'guess',
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
]);
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
$container->loadFromExtension('twig', [
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
]);
|
||||
|
@ -12,4 +12,5 @@ $container->loadFromExtension('twig', [
|
||||
'thousands_separator' => '.',
|
||||
],
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
]);
|
||||
|
@ -17,6 +17,7 @@ $container->loadFromExtension('twig', [
|
||||
'charset' => 'ISO-8859-1',
|
||||
'debug' => true,
|
||||
'strict_variables' => true,
|
||||
'exception_controller' => null,
|
||||
'default_path' => '%kernel.project_dir%/Fixtures/templates',
|
||||
'paths' => [
|
||||
'path1',
|
||||
|
@ -6,5 +6,5 @@
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/twig https://symfony.com/schema/dic/twig/twig-1.0.xsd">
|
||||
|
||||
<twig:config autoescape-service="my_project.some_bundle.template_escaping_guesser" autoescape-service-method="guess" strict-variables="false" />
|
||||
<twig:config autoescape-service="my_project.some_bundle.template_escaping_guesser" autoescape-service-method="guess" strict-variables="false" exception-controller="null" />
|
||||
</container>
|
||||
|
@ -6,5 +6,5 @@
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/twig https://symfony.com/schema/dic/twig/twig-1.0.xsd">
|
||||
|
||||
<twig:config strict-variables="false" />
|
||||
<twig:config strict-variables="false" exception-controller="null" />
|
||||
</container>
|
||||
|
@ -6,7 +6,7 @@
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/twig https://symfony.com/schema/dic/twig/twig-1.0.xsd">
|
||||
|
||||
<twig:config auto-reload="true" autoescape="true" base-template-class="stdClass" cache="/tmp" charset="ISO-8859-1" debug="true" strict-variables="true">
|
||||
<twig:config auto-reload="true" autoescape="true" base-template-class="stdClass" cache="/tmp" charset="ISO-8859-1" debug="true" strict-variables="true" exception-controller="null">
|
||||
<twig:path namespace="namespace3">namespaced_path3</twig:path>
|
||||
</twig:config>
|
||||
</container>
|
||||
|
@ -5,7 +5,7 @@
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/twig https://symfony.com/schema/dic/twig/twig-1.0.xsd">
|
||||
|
||||
<twig:config strict-variables="false">
|
||||
<twig:config strict-variables="false" exception-controller="null">
|
||||
<twig:date format="Y-m-d" interval-format="%d" timezone="Europe/Berlin" />
|
||||
<twig:number-format decimals="2" decimal-point="," thousands-separator="." />
|
||||
</twig:config>
|
||||
|
@ -6,7 +6,7 @@
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/twig https://symfony.com/schema/dic/twig/twig-1.0.xsd">
|
||||
|
||||
<twig:config auto-reload="true" autoescape="true" base-template-class="stdClass" cache="/tmp" charset="ISO-8859-1" debug="true" strict-variables="true" default-path="%kernel.project_dir%/Fixtures/templates">
|
||||
<twig:config auto-reload="true" autoescape="true" base-template-class="stdClass" cache="/tmp" charset="ISO-8859-1" debug="true" strict-variables="true" default-path="%kernel.project_dir%/Fixtures/templates" exception-controller="null">
|
||||
<twig:form-theme>MyBundle::form.html.twig</twig:form-theme>
|
||||
<twig:global key="foo" id="bar" type="service" />
|
||||
<twig:global key="baz">@@qux</twig:global>
|
||||
|
@ -2,3 +2,4 @@ twig:
|
||||
autoescape_service: my_project.some_bundle.template_escaping_guesser
|
||||
autoescape_service_method: guess
|
||||
strict_variables: false # to be removed in 5.0 relying on default
|
||||
exception_controller: ~ # to be removed in 5.0 relying on default
|
||||
|
@ -1,2 +1,3 @@
|
||||
twig:
|
||||
strict_variables: false # to be removed in 5.0 relying on default
|
||||
exception_controller: ~ # to be removed in 5.0 relying on default
|
||||
|
@ -1,4 +1,5 @@
|
||||
twig:
|
||||
strict_variables: false # to be removed in 5.0 relying on default
|
||||
exception_controller: ~ # to be removed in 5.0 relying on default
|
||||
paths:
|
||||
namespaced_path3: namespace3
|
||||
|
@ -1,5 +1,6 @@
|
||||
twig:
|
||||
strict_variables: false # to be removed in 5.0 relying on default
|
||||
exception_controller: ~ # to be removed in 5.0 relying on default
|
||||
date:
|
||||
format: Y-m-d
|
||||
interval_format: '%d'
|
||||
|
@ -14,6 +14,7 @@ twig:
|
||||
debug: true
|
||||
strict_variables: true
|
||||
default_path: '%kernel.project_dir%/Fixtures/templates'
|
||||
exception_controller: ~ # to be removed in 5.0 relying on default
|
||||
paths:
|
||||
path1: ''
|
||||
path2: ''
|
||||
|
@ -31,6 +31,7 @@ class TwigExtensionTest extends TestCase
|
||||
$container->registerExtension(new TwigExtension());
|
||||
$container->loadFromExtension('twig', [
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
]);
|
||||
$this->compileContainer($container);
|
||||
|
||||
@ -156,6 +157,7 @@ class TwigExtensionTest extends TestCase
|
||||
$container->loadFromExtension('twig', [
|
||||
'globals' => $globals,
|
||||
'strict_variables' => false, // // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
]);
|
||||
$this->compileContainer($container);
|
||||
|
||||
@ -259,6 +261,7 @@ class TwigExtensionTest extends TestCase
|
||||
$container->registerExtension(new TwigExtension());
|
||||
$container->loadFromExtension('twig', [
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
]);
|
||||
$container->setAlias('test.twig.extension.debug.stopwatch', 'twig.extension.debug.stopwatch')->setPublic(true);
|
||||
$this->compileContainer($container);
|
||||
@ -289,6 +292,7 @@ class TwigExtensionTest extends TestCase
|
||||
$container->registerExtension(new TwigExtension());
|
||||
$container->loadFromExtension('twig', [
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
]);
|
||||
$container->setParameter('kernel.environment', 'test');
|
||||
$container->setParameter('debug.file_link_format', 'test');
|
||||
|
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\TwigBundle\Tests\ErrorRenderer;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bundle\TwigBundle\ErrorRenderer\TwigHtmlErrorRenderer;
|
||||
use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer;
|
||||
use Symfony\Component\ErrorRenderer\Exception\FlattenException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
|
||||
class TwigHtmlErrorRendererTest extends TestCase
|
||||
{
|
||||
public function testFallbackToNativeRendererIfDebugOn()
|
||||
{
|
||||
$exception = FlattenException::createFromThrowable(new \Exception());
|
||||
|
||||
$twig = $this->createMock(Environment::class);
|
||||
$nativeRenderer = $this->createMock(HtmlErrorRenderer::class);
|
||||
$nativeRenderer
|
||||
->expects($this->once())
|
||||
->method('render')
|
||||
->with($exception)
|
||||
;
|
||||
|
||||
(new TwigHtmlErrorRenderer($twig, $nativeRenderer, true))->render($exception);
|
||||
}
|
||||
|
||||
public function testFallbackToNativeRendererIfCustomTemplateNotFound()
|
||||
{
|
||||
$exception = FlattenException::createFromThrowable(new NotFoundHttpException());
|
||||
|
||||
$twig = new Environment(new ArrayLoader([]));
|
||||
|
||||
$nativeRenderer = $this->createMock(HtmlErrorRenderer::class);
|
||||
$nativeRenderer
|
||||
->expects($this->once())
|
||||
->method('render')
|
||||
->with($exception)
|
||||
;
|
||||
|
||||
(new TwigHtmlErrorRenderer($twig, $nativeRenderer, false))->render($exception);
|
||||
}
|
||||
|
||||
public function testRenderCustomErrorTemplate()
|
||||
{
|
||||
$exception = FlattenException::createFromThrowable(new NotFoundHttpException());
|
||||
|
||||
$twig = new Environment(new ArrayLoader([
|
||||
'@Twig/Exception/error404.html.twig' => '<h1>Page Not Found</h1>',
|
||||
]));
|
||||
|
||||
$nativeRenderer = $this->createMock(HtmlErrorRenderer::class);
|
||||
$nativeRenderer
|
||||
->expects($this->never())
|
||||
->method('render')
|
||||
;
|
||||
|
||||
$content = (new TwigHtmlErrorRenderer($twig, $nativeRenderer, false))->render($exception);
|
||||
|
||||
$this->assertSame('<h1>Page Not Found</h1>', $content);
|
||||
}
|
||||
}
|
@ -99,6 +99,7 @@ class CacheWarmingKernel extends Kernel
|
||||
])
|
||||
->loadFromExtension('twig', [ // to be removed in 5.0 relying on default
|
||||
'strict_variables' => false,
|
||||
'exception_controller' => null,
|
||||
])
|
||||
;
|
||||
});
|
||||
|
@ -14,6 +14,8 @@ namespace Symfony\Bundle\TwigBundle\Tests\Functional;
|
||||
use Symfony\Bundle\TwigBundle\Tests\TestCase;
|
||||
use Symfony\Bundle\TwigBundle\TwigBundle;
|
||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\ErrorRenderer\ErrorRenderer;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
|
||||
class EmptyAppTest extends TestCase
|
||||
@ -37,12 +39,13 @@ class EmptyAppKernel extends Kernel
|
||||
|
||||
public function registerContainerConfiguration(LoaderInterface $loader)
|
||||
{
|
||||
$loader->load(function ($container) {
|
||||
$container
|
||||
->loadFromExtension('twig', [ // to be removed in 5.0 relying on default
|
||||
'strict_variables' => false,
|
||||
])
|
||||
;
|
||||
$loader->load(static function (ContainerBuilder $container) {
|
||||
$container->loadFromExtension('twig', [ // to be removed in 5.0 relying on default
|
||||
'strict_variables' => false,
|
||||
'exception_controller' => null,
|
||||
]);
|
||||
$container->register('error_renderer', ErrorRenderer::class);
|
||||
$container->setParameter('debug.file_link_format', null);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,7 @@ class NoTemplatingEntryKernel extends Kernel
|
||||
])
|
||||
->loadFromExtension('twig', [
|
||||
'strict_variables' => false, // to be removed in 5.0 relying on default
|
||||
'exception_controller' => null, // to be removed in 5.0 relying on default
|
||||
'default_path' => __DIR__.'/templates',
|
||||
])
|
||||
;
|
||||
|
Reference in New Issue
Block a user