This PR was submitted for the 2.x branch but it was merged into the 1.x branch instead (closes#2764).
Discussion
----------
Document combining JSON constants
Working out how to do this took a Slack conversation and a StackOverflow answer. I'm adding ti to the documentation so others can get the answer immediately.
Apologies for any reST errors, it's been 10+ years since I wrote any.
Commits
-------
7f4ecd66 Document combining JSON constants
This PR was merged into the 1.x branch.
Discussion
----------
Improved the code of an example
The original code contains an unneeded *"pop culture"* reference. For those unaware of it, it contains two strong words ("kill" and "bastard").
The concern about this example was firstly raised in the `#diversity` channel of [Symfony Slack](https://symfony.com/support).
Commits
-------
f07a876d Improved the code of an example
This PR was merged into the 1.x branch.
Discussion
----------
Fix multi-byte UFT-8 in escape('html_attr')
same as #2750 but on 1.x
Commits
-------
8863b68c Fix multi-byte UFT-8 in escape('html_attr')
This PR was merged into the 1.x branch.
Discussion
----------
[RFC] Added new "deprecated" tag
```twig
{% deprecated 'The message...' %}
```
This new tag would allow us to define a deprecation warning anywhere within a template, useful for Frameworks, bundles, etc. where breaking the BC is frequently when templates are involved.
It will be easy to guarantee a smooth migration path when we want e.g. rename/remove a template or block, as well as displaying an accurate depreciation message.
**Deprecating a whole template `{# base.twig #}`**
```twig
{% deprecated 'The "' ~ _self ~ '" template is deprecated, use "layout.twig" instead' %}
{% extends 'layout.twig' %}
```
If we're extending from this template `{% extends 'base.twig' %}` then:
```
The "base.twig" template is deprecated, use "layout.twig" instead ("base.twig" at line 1).
```
**Deprecating a block {# greeting/blocks.twig #}**
```twig
{% block hey %}
{% deprecated 'The "hey" block is deprecated, use "greet" block instead' %}
{{ block('greet') }}
{% endblock %}
{% block greet %}
Hey you!
{% endblock %}
```
If we're using this block `{{ block('hey') }}` then:
```
The "hey" block is deprecated, use "greet" block instead ("greeting/blocks.twig" at line 2).
```
also other examples come from my mind like deprecating macros, and any other extension point.
Commits
-------
2ab43383 Added "deprecated" tag
This PR was squashed before being merged into the 1.x branch (closes#2730).
Discussion
----------
Add support for dynamic tests
fixes#2589
Commits
-------
4beb7bfb Add support for dynamic tests
This PR was merged into the 1.x branch.
Discussion
----------
Fix GlobalsInterface extends for IDE
Commits
-------
0b819abb Fix GlobalsInterface extends for IDE
This PR was merged into the 1.x branch.
Discussion
----------
Use isset before array_key_exists
Small performance improvment when using
```
{% set foo = foo|default("bar") %}
```
Will render the following code
```
$context["foo"] = (((isset($context["foo"]) || array_key_exists("foo", $context))) ? (_twig_default_filter((isset($context["foo"]) || array_key_exists("foo", $context) ? $context["foo"] : (function () { throw new Twig_Error_Runtime('Variable "foo" does not exist.', 1, $this->source); })()), "bar")) : ("bar"));
```
instead of
```
$context["foo"] = ((array_key_exists("foo", $context)) ? (_twig_default_filter((isset($context["foo"]) || array_key_exists("foo", $context) ? $context["foo"] : (function () { throw new Twig_Error_Runtime('Variable "foo" does not exist.', 1, $this->source); })()), "bar")) : ("bar"));
```
Commits
-------
230d3412 Use isset before array_key_exists
This PR was merged into the 1.x branch.
Discussion
----------
Ensure that syntax errors are triggered with the right line
When throwing the syntax error without any line and source in these places, the guessing logic enters into action. For the main template, it won't find anything. But for included templates (or any other template loaded during the rendering of another one, even as main one), the guessing will find a template (the caller one) and set the source and line based on it. The source will then be replaced by the proper template by `\Twig_Environment::compileSource`, but the guessed line number will make no sense then.
I searched for all places triggering a syntax error in Twig, to ensure that they always set the actual line number or set the source directly (so that the guessing logic knows that the template it found is the wrong one and so does not try to use it for guessing). There were only a few missing ones.
Commits
-------
6fab6b0b Ensure that syntax errors are triggered with the right line
This PR was merged into the 1.x branch.
Discussion
----------
Fixed PHPDoc of Twig_Token::test
For exemple `Twig_TokenParser_Set` use `->test('endset')`
Commits
-------
35a1070a Fixed PHPDoc of Twig_Token::test
This PR was merged into the 1.x branch.
Discussion
----------
Add the Symfony ctype polyfill as a dependency
Commits
-------
5b9a70b3 added the Symfony ctype polyfill as a dependency
This PR was submitted for the 2.x branch but it was merged into the 1.x branch instead (closes#2670).
Discussion
----------
Fix partial template caching after update when auto_reload is on
**Description of the bug:**
This bug manifests itself on production servers.
And with a high load the probability of getting on this bug tends to 100%
The bug results in the caching of a partial template and the failure of a part of the site working with this template. Can only be corrected by deleting the cache.
**What's happening:**
If in the process of uploading the template file, a render() is called, the partially uploaded file gets into the cache and after the template file is fully uploaded, the cache is not updated anymore.
**How to demonstrate:**
To demonstrate the bug, you can create 2 files:
File simulating the download of a file to the server (twig_test_write.php):
```
$classTwig = new Twig_Environment( new Twig_Loader_Filesystem(__DIR__."/../../site_templates/"), array(
'cache' => __DIR__.'/../../site_templates_cache',
'auto_reload'=>true
));
file_put_contents(__DIR__."/../../site_templates/"."test.twig","\n<br>Template start write to filesystem");
echo $classTwig->render("test.twig", array());
file_put_contents(__DIR__."/../../site_templates/"."test.twig"," - Template end write to filesystem",FILE_APPEND);
```
File for template rendering (twig_test_read.php):
```
$classTwig = new Twig_Environment( new Twig_Loader_Filesystem(__DIR__."/../../site_templates/"), array(
'cache' => __DIR__.'/../../site_templates_cache',
'auto_reload'=>true
));
echo $classTwig->render("test.twig", array());
```
Result executeing file twig_test_write.php:
```
Template start write to filesystem
```
Result executeing file twig_test_read.php:
```
Template start write to filesystem
```
**After this fix:**
Result executeing file twig_test_read.php:
```
Template start write to filesystem - Template end write to filesystem
```
Commits
-------
50d990e2 Fix cache update after uploading the template file (when auto-update is enabled).
If in the process of uploading the template file, a render() is called, the partially uploaded file gets into the cache and after the template file is fully uploaded, the cache is not updated anymore.
This PR was merged into the 1.x branch.
Discussion
----------
Small optimization for Twig_NodeTraverser::traverseForVisitor
During traversing a node tree `Twig_NodeTraverser::traverseForVisitor` (`Twig_NodeVisitorInterface::leaveNode`) often returns a same child node (a same object). So, there is no need to set it back to its parent.
This PR adds a check if a child node was changed. With this check a lot of calls to `Twig_Node::setNode` will be skipped.
Closes#2665
Commits
-------
555d01f3 Small optimization for Twig_NodeTraverser::traverseForVisitor
This PR was squashed before being merged into the 1.x branch (closes#2581).
Discussion
----------
Add JSON escape strategy
The `js` escape strategy used `\xNN`-style escape sequences. This is not allowed in JSON, only `\uNNNN` is allowed.
This PR adds a new escape strategy, `json` that is similar to `js` except that it does not use `\xNN` but uses `\uNNNN` instead.
I know that I can use `json_decode()`, but it came as a surprise to me that `escape('js')` did not work. You probably shouldn't be generating JSON structures in your templates, but sometimes it comes in handy. My use-case was generating a piece of [JSON-LD](https://json-ld.org).
A different approach that would perhaps be less confusing to users would be to change `js` to not use `\xNN`. This output is still valid JavaScript, it just uses two more bytes per occurrence. Let me know what you think.
Commits
-------
5c7b080b Add JSON escape strategy
This PR was merged into the 1.x branch.
Discussion
----------
Remove dev deps in composer.json
Commits
-------
64349bcf removed dev deps in composer.json