Deprecating error templates for non-html formats and using ErrorRenderer

This commit is contained in:
Yonel Ceruto 2019-07-22 13:18:46 -04:00
parent a7852c0da8
commit bf0c24a634
58 changed files with 404 additions and 26 deletions

View File

@ -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
---------

View File

@ -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
----------

View File

@ -7,3 +7,4 @@ framework:
twig:
strict_variables: '%kernel.debug%'
exception_controller: ~

View File

@ -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"
},

View File

@ -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));
}
}

View File

@ -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());
}
}

View File

@ -12,5 +12,4 @@
return [
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
];

View File

@ -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']

View File

@ -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(),
];

View File

@ -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

View File

@ -2,3 +2,4 @@
twig:
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
exception_controller: Symfony\Bundle\SecurityBundle\Tests\Functional\app\ExceptionController

View File

@ -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": {

View File

@ -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
-----

View File

@ -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
{

View File

@ -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

View File

@ -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()
;

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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') }}

View File

@ -1,3 +1,4 @@
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
/*
{{ status_code }} {{ status_text }}

View File

@ -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>

View File

@ -1,3 +1,4 @@
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
/*
{{ status_code }} {{ status_text }}

View File

@ -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 }}

View File

@ -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') }}

View File

@ -1,3 +1,4 @@
{% deprecated 'The template "' ~ _self ~'" is deprecated since Symfony 4.4, will be removed in 5.0.' %}
Oops! An Error Occurred
=======================

View File

@ -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 }}" />

View File

@ -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 }) }}

View File

@ -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 }) }}
*/

View File

@ -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 }) }}
*/

View File

@ -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 }}

View File

@ -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 }) }}

View File

@ -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 %}

View File

@ -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 }}">

View File

@ -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>

View File

@ -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[*/

View File

@ -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 {

View File

@ -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>

View File

@ -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()

View File

@ -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']],
];

View File

@ -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
]);

View File

@ -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
]);

View File

@ -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
]);

View File

@ -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',

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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: ''

View File

@ -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');

View File

@ -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);
}
}

View File

@ -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,
])
;
});

View File

@ -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);
});
}

View File

@ -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',
])
;