Commit Graph

7574 Commits

Author SHA1 Message Date
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 57e2f5c367 feature #4840 Mark Markup as final (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Mark Markup as final

Commits
-------

f938f6d153 Mark Markup as final
2026-06-09 21:43:35 +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 3f54383f1b bug #4835 Fix markdown_to_html mangling content that starts with a blank line (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Fix markdown_to_html mangling content that starts with a blank line

Closes #3685

Commits
-------

113aec62e7 Fix markdown_to_html mangling content that starts with a blank line
2026-06-07 09:35:24 +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 fa33c2278e minor #4837 Reduce memory usage of the context restoration compiled at the end of for loops (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Reduce memory usage of the context restoration compiled at the end of for loops

Refs #4021

I benchmarked the new version and it's 10–15% faster CPU and half the allocations.

Commits
-------

0197736dfc Reduce memory usage of the context restoration compiled at the end of for loops
2026-06-06 10:56:19 +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 9a1d3d241f feature #4816 Add an always_allowed_in_sandbox flag for filters, functions, and tags (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

Add an always_allowed_in_sandbox flag for filters, functions, and tags

Some filters, functions, and tags are pure and inherently safe to use in sandboxed templates. Forcing every sandbox policy to explicitly allow-list them is noisy.

Introduce an opt-in flag that lets callable and token-parser authors mark their item as always allowed in the sandbox. When set, the sandbox node visitor skips recording the name, so it never reaches the policy's `checkSecurity()` call: zero runtime cost, no allow-list entry required.

Commits
-------

cf4b50d181 Clarify sandbox always-allowed trust boundary
29c4325afd Bump version to 3.28.0 for the always_allowed_in_sandbox feature
1c53b790fb Add regression tests that always-allowed callables still enforce the sandbox __toString policy on arguments
7fd87a381f Document the criteria for always-allowed sandbox items and list 4.0 built-ins
2d75c87d05 Add an always_allowed_in_sandbox flag for filters, functions, and tags
2026-06-06 09:22:57 +02:00
Fabien Potencier cf4b50d181 Clarify sandbox always-allowed trust boundary 2026-06-06 09:19:48 +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 1c53b790fb Add regression tests that always-allowed callables still enforce the sandbox __toString policy on arguments 2026-06-06 08:56:58 +02:00
Fabien Potencier 7fd87a381f Document the criteria for always-allowed sandbox items and list 4.0 built-ins 2026-06-06 08:56:58 +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 e3c0c3fe5a feature #4834 Track the source offset of each token and expose it in syntax errors (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

Track the source offset of each token and expose it in syntax errors

Commits
-------

3868bac531 Avoid allocating a normalized copy when counting newlines without carriage returns
a82782ac30 Report columns in syntax errors
4943bb405c Track the source offset of each token
2026-06-06 08:56:09 +02:00
Fabien Potencier d0cc1fcd40 Remove issue references in tests 2026-06-06 08:55:16 +02:00
Fabien Potencier 611a5d911a minor #4836 Document how to customize the markdown_to_html converter (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Document how to customize the markdown_to_html converter

Closes #3842
Closes #3211

Commits
-------

36cd35dff4 Document how to customize the markdown_to_html converter
2026-06-06 08:46:50 +02:00
Fabien Potencier 36cd35dff4 Document how to customize the markdown_to_html converter 2026-06-05 21:52:27 +02:00
Fabien Potencier 113aec62e7 Fix markdown_to_html mangling content that starts with a blank line 2026-06-05 21:47:22 +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 379df77252 bug #4825 Make the include() function return a Markup object (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Make the include() function return a Markup object

Closes #4754

Commits
-------

a3eda4b1fd Make the include() function return a Markup object
2026-06-04 21:32:19 +02:00
Fabien Potencier a3eda4b1fd Make the include() function return a Markup object 2026-06-04 21:32:12 +02:00
Fabien Potencier ecf0ebf78b bug #4830 Fix nested block() resolution when a directly rendered block calls parent() (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Fix nested block() resolution when a directly rendered block calls parent()

Closes #3321

Commits
-------

279fe13b22 Fix nested block() resolution when a directly rendered block calls parent()
2026-06-04 21:30:37 +02:00
Fabien Potencier 279fe13b22 Fix nested block() resolution when a directly rendered block calls parent() 2026-06-03 22:13:40 +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 a0093cd699 minor #4827 Document {#--#} as the replacement for the deprecated spaceless filter (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Document {#--#} as the replacement for the deprecated spaceless filter

Closes #4442

Commits
-------

c29877f54a Document {#--#} as the replacement for the deprecated spaceless filter
2026-06-03 22:03:07 +02:00
Fabien Potencier 1bdc760cff bug #4828 Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run

Closes #4635

Commits
-------

86076c87a6 Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run
2026-06-03 22:02:35 +02:00
Fabien Potencier b52f6d9927 minor #4829 Document storing an enum in a variable to avoid repeating its FQCN (fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Document storing an enum in a variable to avoid repeating its FQCN

Closes #4646

Commits
-------

e1178abfa1 Document storing an enum in a variable to avoid repeating its FQCN
2026-06-03 22:00:02 +02:00
Fabien Potencier e1178abfa1 Document storing an enum in a variable to avoid repeating its FQCN 2026-06-03 21:58:29 +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 c29877f54a Document {#--#} as the replacement for the deprecated spaceless filter 2026-06-03 20:00:30 +02:00
Fabien Potencier 1a2f2ea0a3 bug #4824 Cast printed expressions to string so values that cannot be converted to a string (arrays, non-Stringable objects, ...) report a usable stack trace at the print location (stof, fabpot)
This PR was merged into the 3.x branch.

Discussion
----------

Cast printed expressions to string so values that cannot be converted to a string (arrays, non-`Stringable` objects, ...) report a usable stack trace at the print location

Closes #4765
Closes #4780
Closes #4644

Is it what you had in mind `@stof`?

Commits
-------

89f886e324 Skip the string cast in PrintNode when the expression is already a string and add tests
86840f9351 Ensure PrintNode is yielding string content
2026-06-03 19:56:33 +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 4cc1afe067 feature #4826 Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11 (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11

Closes #4782

Commits
-------

8a4b77920a Add PHPUnit attributes alongside annotations to silence doc-comment metadata deprecations on PHPUnit 11
8b35934e68 Run the test suite against PHPUnit 11.3 in CI
ee8ab447d7 Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11
2026-06-03 19:45:14 +02:00
Fabien Potencier 8a4b77920a Add PHPUnit attributes alongside annotations to silence doc-comment metadata deprecations on PHPUnit 11 2026-06-03 18:26:39 +02:00
Fabien Potencier 8b35934e68 Run the test suite against PHPUnit 11.3 in CI 2026-06-03 18:21:23 +02:00
Fabien Potencier ee8ab447d7 Make IntegrationTestCase and NodeTestCase compatible with PHPUnit 11 2026-06-03 18:17:03 +02:00
Fabien Potencier 2a2f058f70 feature #4823 Skip the sandbox __toString check on arguments whose PHP parameter type cannot implicitly coerce to string (fabpot)
This PR was squashed before being merged into the 3.x branch.

Discussion
----------

Skip the sandbox `__toString` check on arguments whose PHP parameter type cannot implicitly coerce to string

The sandbox visitor currently wraps every argument of every Twig callable with `CheckToStringNode.

As an optimization, we are now only wrapping when needed (based on the callable type hints). This is a conservative approach (untyped, mixed, string, array, iterable, object, Stringable, Traversable, self/static/parent and unknown class names all keep wrapping).

Here is a concrete before/after for template `{{ demo(a, b) }}` under the sandbox, with the following signature on the PHP side `demo(int $a, string $b)`:

**Before**:

```php
    yield $this->sandbox->ensureToStringAllowed(
       $this->env->getFunction('demo')->getCallable()(
           $this->sandbox->ensureToStringAllowed(($context["a"] ?? null), 1, $this->source),
           $this->sandbox->ensureToStringAllowed(($context["b"] ?? null), 1, $this->source),
       ),
       1, $this->source,
   );
```

**After**

```php
   yield $this->sandbox->ensureToStringAllowed(
       $this->env->getFunction('demo')->getCallable()(
           ($context["a"] ?? null),                                                            // int: bare, skipped
           $this->sandbox->ensureToStringAllowed(($context["b"] ?? null), 1, $this->source),   // string: still wrapped
       ),
       1, $this->source,
   );
```

Commits
-------

6d5ef30436 Skip the sandbox `__toString` check on arguments whose PHP parameter type cannot implicitly coerce to string
2026-06-02 13:58:28 +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