This PR was merged into the 3.x branch.
Discussion
----------
Reuse assignment targets parsed for the for tag
`ForTokenParser` rebuilds the loop targets returned by `parseAssignmentExpression()` into new `AssignContextVariable` instances, copying only the name and line number. But the parsed targets are already `AssignContextVariable` nodes with exactly those values, so the rebuild is a no-op left over from older Twig versions where for-targets were parsed as general expressions and needed normalizing.
Reusing the parsed nodes directly removes dead code, and makes the parser more robust: any metadata attached to the targets during parsing (now or in the future) is preserved instead of being silently dropped.
Commits
-------
9408f2a3f1 Reuse assignment targets parsed for the for tag
This PR was merged into the 3.x branch.
Discussion
----------
Update for.rst
Add context and explanation about loop.parent.
Commits
-------
02382585e9 add shadowing example
7234d51ec8 Update for.rst
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
Fix IntlExtension ignoring explicit formats when a date formatter prototype is set
Closes#3845
Commits
-------
083b6dcabe Fix IntlExtension ignoring explicit formats when a date formatter prototype is set
This PR was merged into the 3.x branch.
Discussion
----------
bump Twig version metadata
following #4852
Commits
-------
57905dab67 bump Twig version metadata
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
Document and test sandbox __call support
Related to #1950
Commits
-------
29b66fd916 Document sandbox handling of magic __call() methods
72da20aeb7 Add sandbox tests for methods routed through __call()
This PR was merged into the 3.x branch.
Discussion
----------
Disable the fabbot test-case return type check
See https://github.com/symfony-tools/fabbot/pull/18
Commits
-------
27a2dba4a7 Disable the fabbot test-case return type check
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
[Intl] Add format_list filter using PHP 8.5's IntlListFormatter
Adds a new `format_list` Twig filter to IntlExtension that formats arrays using using PHP 8.5's IntlListFormatter
On PHP < 8.5, using the filter throws a RuntimeError explaining the dependency on IntlListFormatter (Checks if `class_exists` to allow polyfills).
CI workflow only covered up to PHP 8.4, so I extended it to also run PHPUnit against 8.5.
phpstan's PHP version also bumped to 8.5.
Commits
-------
163f1b6341 [Intl] Add format_list filter using PHP 8.5's IntlListFormatter
This PR was merged into the 3.x branch.
Discussion
----------
Fix array access with a Stringable key on ArrayAccess objects using object keys
Closes#4855
Commits
-------
679b8fd610 Fix array access with a Stringable key on ArrayAccess objects using object keys
This PR was merged into the 3.x branch.
Discussion
----------
Fix version in deprecation message for tag usage outside of root template
#4292 has been introduced in 3.28 and related deprecations are shown for this version in changelog file
But in some part of code including deprecation message, it's about 3.27, this is confusing when upgrading Twig
Commits
-------
fc4dee393c fix version in deprecation message for tag usage outside of root template
This PR was merged into the 3.x branch.
Discussion
----------
Throw a SyntaxError instead of a PHP fatal error when a macro argument is defined twice
Commits
-------
0d283d304a Throw a SyntaxError instead of a PHP fatal error when a macro argument is defined twice
This PR was merged into the 3.x branch.
Discussion
----------
Render backed enums using their backing value in the html_attr function
Closes#4848
Commits
-------
9323a82eb9 Render backed enums using their backing value in the html_attr function
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
Add documention note about variable scope of override blocks in {% embed ... only %}
Closes#4844
Commits
-------
068a2e6cb4 Add documention note about variable scope of override blocks in {% embed ... only %}
This PR was merged into the 3.x branch.
Discussion
----------
Define macros at the template root in the cache macro fixture
Commits
-------
424d2f1195 Define the macro at the template root in the cache macro fixture
This PR was merged into the 3.x branch.
Discussion
----------
Fix Markup truthiness in boolean expressions
## Summary
Fixes Markup truthiness handling in boolean expressions.
`trim` can return a `Twig\Markup` instance for safe strings. Empty `Markup` objects must behave like empty strings in Twig truth tests, but PHP treats all objects as truthy. This caused expressions like this to incorrectly evaluate as true:
```twig
{% set x %} {% endset %}
{% if x|trim and x|trim %}fail{% else %}ok{% endif %}
```
This case was working properly in https://github.com/twigphp/Twig/releases/tag/v3.14.2 and earlier.
## Related commits
- Bug was introduced in [v3.15.0](https://github.com/twigphp/Twig/releases/tag/v3.15.0) in this commit https://github.com/twigphp/Twig/commit/10c3142d3b036910f63080070c101bfff61e0743
- Partially fixed here: https://github.com/twigphp/Twig/commit/10c3142d3b036910f63080070c101bfff61e0743
## Changes
- Added `TrueTest::wrap()` to centralize wrapping non-primitive expressions with Twig’s Markup-aware true test.
- Reused `TrueTest::wrap()` in:
- `IfNode`
- conditional ternary expressions
- `and`, `or`, and `xor` binary expressions
- Elvis expressions
- unary `not`
- Added regression coverage for boolean operators (`and`, `or`, `xor`, `not`) and ternary/Elvis expressions whose operands evaluate to empty `Markup`.
## Tests
```bash
./vendor/bin/simple-phpunit tests/IntegrationTest.php --filter markup_test
```
Commits
-------
f5afaabf54 Fix Markup truthiness in boolean expressions
This PR was merged into the 3.x branch.
Discussion
----------
Fix a PHP 8.5 chr() deprecation when decoding octal string escapes
PHP 8.5 deprecates passing a value outside the `[0, 255]` range to `chr()`.
The string-escape decoder in `Lexer::stringEscape()` accepts up to three octal digits, so a template containing an escape such as `"\777"` (= 511) reaches `chr()` out of range and emits:
> `chr(): Providing a value not in-between 0 and 255 is deprecated, this is because a byte value must be in the [0, 255] interval. The value used will be constrained using % 256`
`chr()` already constrains the value with `% 256`, so applying `% 256` explicitly preserves the exact byte that was produced before while silencing the deprecation. The hex-escape branch is unaffected because it is capped at two digits (`\xff` = 255).
Reproducer (PHP 8.5):
```twig
{{ "\777" }}
```
Tests added to `getStringWithEscapedDelimiter()` cover `"\777"` (constrained to `0xff`) and `"\400"` (wraps to a NUL byte). The full suite passes on PHP 8.5; without this change the bridge reports the `chr()` notice as a self-deprecation.
Commits
-------
153094b601 Fix a PHP 8.5 chr() deprecation when decoding octal string escapes
PHP 8.5 deprecates passing a value outside the [0, 255] range to chr().
The string-escape decoder in the lexer accepts up to three octal digits,
so an escape such as "\777" (= 511) reaches chr() out of range and emits:
chr(): Providing a value not in-between 0 and 255 is deprecated ...
chr() already constrains the value with "% 256", so applying "% 256"
explicitly preserves the exact byte while silencing the deprecation. The
hex escape branch is unaffected because it is capped at two digits (0xff).
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
Introduce a CorrectnessNodeVisitor to validate that templates are semantically correct
This PR addresses several issues around the correctness of templates.
Being able to parse and compile a template does not mean that it is semantically correct. To enforce correctness, we currently have several places where we deal with it:
* `Parser::filterBodyNodes()`: This method is a mix of ensuring the correctness of a template, but it also changes the body node of a child template (something that is always needed and not part of the correctness checks)
* `ExtendsTokenParser`: It checks that an `extend` tag is not embedded into a block or a macro. The `extend` tag is not the only one that must be at the root of a template
This PR introduces a new `CorrectnessNodeVisitor` that has the responsibility to check that a template is semantically correct. It's the continuation of work that started a long time ago in #2687 (where I mentioned the weirdness of some supported templates like those mentioned in #3926 and deprecated by this PR).
Closes#3698: Having a `use` tag embedded in another tag (like `if` in the mentioned PR) is deprecated and will not be possible in 4.0.
Commits
-------
c0504b90c5 Handle single-node child template bodies in cleanup
a69d3dc71e Keep captured block definitions supported
16e5a937ed Clarify captured block deprecation wording
8a0ae2204c Simplify correctness visitor checks
ffcae61b15 Move extends validation into correctness visitor
d96eac3895 Fix correctness visitor regressions
89e8699a73 Fix test assertions that did not verify the intended behavior
4b2e651dd5 Address review: fix block-nesting checks in CorrectnessNodeVisitor
de7bbc7be9 Move the extends-in-block and extends-in-macro errors into the CorrectnessNodeVisitor
c12100525e Introduce a CorrectnessNodeVisitor to validate that templates are semantically correct