Commit Graph

1523 Commits

Author SHA1 Message Date
Fabien Potencier be36fee09e Rename macro variable AST nodes 2026-07-28 11:53:50 +02:00
Fabien Potencier 6ce5beb7c2 Normalize destructuring assignment targets 2026-07-27 18:51:15 +02:00
Fabien Potencier 44f6f7e6c8 feature #4873 Deprecate duplicate macro definitions (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Deprecate duplicate macro definitions

Commits
-------

258089b8a6 Deprecate duplicate macro definitions
2026-07-27 12:45:09 +02:00
Fabien Potencier 258089b8a6 Deprecate duplicate macro definitions 2026-07-27 12:24:45 +02:00
Fabien Potencier 9408f2a3f1 Reuse assignment targets parsed for the for tag 2026-07-25 17:48:54 +02:00
Christian Flothmann 57905dab67 bump Twig version metadata 2026-07-13 10:56:44 +02:00
Fabien Potencier 0b8e267bce Fix CS 2026-07-12 15:21:32 +02:00
Fabien Potencier 9c6d76b61c Add void return type hint even in tests 2026-07-12 13:43:08 +02:00
Fabien Potencier 8ada671fc3 bug #4856 Fix array access with a Stringable key on ArrayAccess objects using object keys (fabpot)
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
2026-07-08 21:15:02 +02:00
Matthieu Lempereur fc4dee393c fix version in deprecation message for tag usage outside of root template 2026-07-08 19:01:20 +02:00
Fabien Potencier 679b8fd610 Fix array access with a Stringable key on ArrayAccess objects using object keys 2026-07-06 22:42:11 +02:00
Fabien Potencier 0d283d304a Throw a SyntaxError instead of a PHP fatal error when a macro argument is defined twice 2026-07-04 11:17:28 +02:00
Fabien Potencier 54e5bc1453 Bump version 2026-07-03 22:44:56 +02:00
Fabien Potencier 597c12ed28 Prepare the 3.28.0 release 2026-07-03 22:44:34 +02:00
Fabien Potencier 2f202b006b bug #4841 Fix Markup truthiness in boolean expressions (xtrime-ru)
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
2026-06-13 12:28:15 +02:00
Derrick Austin 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).
2026-06-13 07:22:26 +02:00
Alexander Pankratov f5afaabf54 Fix Markup truthiness in boolean expressions 2026-06-11 15:33:21 +02:00
Fabien Potencier c0504b90c5 Handle single-node child template bodies in cleanup 2026-06-11 07:44:00 +02:00
Fabien Potencier a69d3dc71e Keep captured block definitions supported 2026-06-11 07:43:59 +02:00
Fabien Potencier 8a0ae2204c Simplify correctness visitor checks 2026-06-11 07:43:47 +02:00
Fabien Potencier ffcae61b15 Move extends validation into correctness visitor 2026-06-11 07:43:47 +02:00
Fabien Potencier d96eac3895 Fix correctness visitor regressions 2026-06-11 07:43:46 +02:00
Fabien Potencier 89e8699a73 Fix test assertions that did not verify the intended behavior 2026-06-11 07:43:36 +02:00
Fabien Potencier 4b2e651dd5 Address review: fix block-nesting checks in CorrectnessNodeVisitor 2026-06-11 07:43:36 +02:00
Fabien Potencier de7bbc7be9 Move the extends-in-block and extends-in-macro errors into the CorrectnessNodeVisitor 2026-06-11 07:43:36 +02:00
Fabien Potencier c12100525e Introduce a CorrectnessNodeVisitor to validate that templates are semantically correct 2026-06-11 07:43:33 +02:00
Fabien Potencier f938f6d153 Mark Markup as final 2026-06-07 10:29:17 +02:00
Fabien Potencier 612dc96c18 feature #4838 Allow calling a macro with a dynamic name via the dot operator (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Allow calling a macro with a dynamic name via the dot operator

Closes #4715

Commits
-------

87093aab9e Allow calling a macro with a dynamic name via the dot operator
2026-06-07 09:36:06 +02:00
Fabien Potencier 87093aab9e Allow calling a macro with a dynamic name via the dot operator 2026-06-06 17:10:52 +02:00
Fabien Potencier aef7587fc8 feature #4819 Add an allow-list for tests to the sandbox security policy (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Add an allow-list for tests to the sandbox security policy

Commits
-------

416d07da1d Add an allow-list for tests to the sandbox security policy
2026-06-06 17:04:39 +02:00
Fabien Potencier 416d07da1d Add an allow-list for tests to the sandbox security policy 2026-06-06 11:08:56 +02:00
Fabien Potencier 0197736dfc Reduce memory usage of the context restoration compiled at the end of for loops 2026-06-06 09:31:56 +02:00
Fabien Potencier 29c4325afd Bump version to 3.28.0 for the always_allowed_in_sandbox feature 2026-06-06 08:56:59 +02:00
Fabien Potencier 2d75c87d05 Add an always_allowed_in_sandbox flag for filters, functions, and tags 2026-06-06 08:56:58 +02:00
Fabien Potencier 3868bac531 Avoid allocating a normalized copy when counting newlines without carriage returns 2026-06-05 20:33:28 +02:00
Fabien Potencier a82782ac30 Report columns in syntax errors 2026-06-05 20:28:45 +02:00
Fabien Potencier 4943bb405c Track the source offset of each token 2026-06-05 20:28:45 +02:00
Fabien Potencier afad02326d minor #4662 CoreExtension::getAttribute: small improvement regarding getter/isser/hasser (gharlan)
This PR was merged into the 3.x branch.

Discussion
----------

CoreExtension::getAttribute: small improvement regarding getter/isser/hasser

For a getter method like `getFirstName` it is common to call it in twig via `person.firstName`.
But at the moment twig is adding these variants to the class method cache: `getFirstName`, `getfirstname`, `FirstName` and `firstname`.
So when resolving the name, it uses the first `elseif` here with additional `strtolower` call, because `firstName` is missing:

https://github.com/twigphp/Twig/blob/403bd9d73c2a010e5b26689f2f2eb9d7ddf391af/src/Extension/CoreExtension.php#L1863-L1867

This PR replaces `FirstName` with `firstName` in the method cache.
So `person.firstName` is resolved via first `if` branch (but `person.FirstName` would use the `elseif` with `strtolower` now).

Commits
-------

45cd6ffe80 CoreExtension::getAttribute: small improvement regarding getter/isser/hasser
2026-06-04 22:28:58 +02:00
Fabien Potencier a3eda4b1fd Make the include() function return a Markup object 2026-06-04 21:32:12 +02:00
Fabien Potencier 2171127676 Fix nested block() resolution when a directly rendered block calls parent() 2026-06-03 22:09:09 +02:00
Fabien Potencier 86076c87a6 Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run 2026-06-03 20:07:23 +02:00
Fabien Potencier 89f886e324 Skip the string cast in PrintNode when the expression is already a string and add tests 2026-06-03 19:56:27 +02:00
Christophe Coevoet 86840f9351 Ensure PrintNode is yielding string content 2026-06-03 19:56:11 +02:00
Fabien Potencier ee8ab447d7 Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11 2026-06-03 18:17:03 +02:00
Fabien Potencier 6d5ef30436 Skip the sandbox __toString check on arguments whose PHP parameter type cannot implicitly coerce to string 2026-06-02 13:58:24 +02:00
Fabien Potencier dc1db9ef63 Bump version 2026-05-30 19:09:51 +02:00
Fabien Potencier ae2071bffb Prepare the 3.27.1 release 2026-05-30 19:09:26 +02:00
Fabien Potencier 8ec9530732 Fix inconsistent array access with a Stringable key 2026-05-29 10:06:57 +02:00
Fabien Potencier d25f98f45b Preserve IteratorAggregate identity in sandbox __toString walker 2026-05-29 09:31:03 +02:00
Fabien Potencier 86f3b3a1f2 Bump version 2026-05-27 15:06:12 +02:00