276 Commits

Author SHA1 Message Date
Fabien Potencier f640320202 Merge branch '3.x' into 4.x
* 3.x: (26 commits)
  Remove the documentation comments compilation overhead
  Clarify source function trust requirements
  Throw on PCRE errors in the matches operator
  Document that reusing a non-rewindable iterator after destructuring is unsupported
  Release destructuring temporaries after assignment
  Deprecate prefixed macro definedness checks
  Fix duplicate macro deprecation wording
  Throw when list formatting fails
  Document that sequence destructuring consumes one value per pattern slot
  Fix the html_attr documentation about iterables in data attributes
  Warn about untrusted input with the default Tempest markdown converter
  Document that overriding MacroNode::compile() is not supported anymore
  Merge overlapping CHANGELOG entries for the destructuring fatal error fix
  Document that include_only keeps global variables available
  Remove lazy macro import resolution
  Honor date formatter prototype calendars
  Fix Stringable keys for ArrayAccess implementations
  Fix repeated object destructuring evaluation
  Restore void return type compatibility for extension points
  Reject destructuring patterns containing no variables
  ...

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	doc/filters/format_datetime.rst
#	extra/twig-extra-bundle/DependencyInjection/Compiler/MissingExtensionSuggestorPass.php
#	extra/twig-extra-bundle/DependencyInjection/TwigExtraExtension.php
#	extra/twig-extra-bundle/TwigExtraBundle.php
#	src/MacroNamespace.php
#	src/Node/MacrosNode.php
#	src/Parser.php
#	src/Test/IntegrationTestCase.php
#	src/Test/NodeTestCase.php
#	tests/CallMacroTest.php
#	tests/ExpressionParserTest.php
#	tests/Fixtures/macros/duplicate_definition.legacy.test
#	tests/Node/MacrosTest.php
#	tests/ParserTest.php
2026-08-29 00:25:20 +02:00
Fabien Potencier c459ef0bdd Release destructuring temporaries after assignment 2026-08-27 13:32:19 +02:00
Fabien Potencier cf971e1a59 Remove lazy macro import resolution 2026-08-27 12:17:08 +02:00
Fabien Potencier d7fc3d6dc9 Merge branch '3.x' into 4.x
* 3.x:
  Attach documentation comments to nodes

# Conflicts:
#	CHANGELOG
#	src/Lexer.php
#	src/Node/Node.php
#	src/Parser.php
#	src/Token.php
2026-08-19 16:44:35 +02:00
Fabien Potencier 6806e30474 Attach documentation comments to nodes 2026-08-19 16:41:17 +02:00
Fabien Potencier 93b00ee3c9 Merge branch '3.x' into 4.x
* 3.x:
  Nested macro imports

# Conflicts:
#	CHANGELOG
#	src/MacroNamespace.php
#	src/Node/MacrosNode.php
#	src/Parser.php
#	tests/Extension/SandboxStateChangeTest.php
#	tests/Node/MacrosTest.php
2026-08-03 10:34:02 +02:00
Fabien Potencier b53e100444 Nested macro imports 2026-08-03 10:30:32 +02:00
Fabien Potencier ce013c063e Remove deprecated code 2026-07-30 14:14:10 +02:00
Fabien Potencier 986a765019 Merge branch '3.x' into 4.x
* 3.x:
  Redesign macro calls and argument handling

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	src/ExpressionParser/Infix/ArgumentsTrait.php
#	src/ExpressionParser/Infix/DotExpressionParser.php
#	src/ExpressionParser/Infix/FunctionExpressionParser.php
#	src/Extension/CoreExtension.php
#	src/Node/Expression/MacroReferenceExpression.php
#	src/Node/Expression/MethodCallExpression.php
#	src/Node/Expression/TempNameExpression.php
#	src/Node/MacroNode.php
#	src/Node/ModuleNode.php
#	src/Template.php
#	tests/Fixtures/macros/call_without_parentheses.legacy.test
#	tests/Node/Expression/MacroReferenceTest.php
#	tests/Node/MacroTest.php
2026-07-30 14:02:30 +02:00
Fabien Potencier d7f8b4eb1c Redesign macro calls and argument handling 2026-07-30 13:53:24 +02:00
Fabien Potencier b34f022583 Remove deprecated code 2026-07-30 13:52:37 +02:00
Fabien Potencier 3197df7b5e Merge branch '3.x' into 4.x
* 3.x:
  Make the sandbox a first-class citizen with a dedicated Sandbox class

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	doc/tags/sandbox.rst
#	phpstan-baseline.neon
#	src/Extension/CoreExtension.php
#	src/Extension/SandboxExtension.php
#	src/Sandbox/SecurityPolicy.php
2026-07-30 13:04:50 +02:00
Fabien Potencier b762bc94b9 Make the sandbox a first-class citizen with a dedicated Sandbox class 2026-07-30 12:05:47 +02:00
Fabien Potencier 8bfb29b953 Remove deprecated code 2026-07-28 14:52:35 +02:00
Fabien Potencier 80df3b5f63 Merge branch '3.x' into 4.x
* 3.x:
  Rename macro variable AST nodes

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	src/ExpressionParser/Infix/DotExpressionParser.php
#	src/Node/Expression/Variable/TemplateVariable.php
#	src/Node/ImportNode.php
#	src/Parser.php
2026-07-28 14:47:56 +02:00
Fabien Potencier be36fee09e Rename macro variable AST nodes 2026-07-28 11:53:50 +02:00
Fabien Potencier ef9c43187a Fix incompatible identifier() signature in test stubs 2026-07-12 15:15:28 +02:00
Fabien Potencier 5ca7debf6e Fix merge conflict resolution 2026-07-12 15:08:38 +02:00
Fabien Potencier 0b6e824ea8 Merge branch '3.x' into 4.x
* 3.x:
  Add void return type hint even in tests
  Run php-cs-fixer sequentially so the void_return src-only customiser is applied
  Fix CHANGELOG
  [Intl] Add format_list filter using PHP 8.5's IntlListFormatter

# Conflicts:
#	.github/workflows/ci.yml
#	CHANGELOG
#	extra/cssinliner-extra/Tests/LegacyFunctionsTest.php
#	extra/html-extra/Tests/CvaTest.php
#	extra/html-extra/Tests/HtmlAttrMergeTest.php
#	extra/html-extra/Tests/HtmlAttrTest.php
#	extra/html-extra/Tests/LegacyFunctionsTest.php
#	extra/inky-extra/Tests/LegacyFunctionsTest.php
#	extra/markdown-extra/Tests/FunctionalTest.php
#	extra/markdown-extra/Tests/LegacyFunctionsTest.php
#	extra/twig-extra-bundle/DependencyInjection/Compiler/MissingExtensionSuggestorPass.php
#	extra/twig-extra-bundle/DependencyInjection/TwigExtraExtension.php
#	extra/twig-extra-bundle/TwigExtraBundle.php
#	src/Extension/CoreExtension.php
#	src/Extension/EscaperExtension.php
#	src/Node/CheckSecurityCallNode.php
#	src/Node/Expression/FunctionExpression.php
#	src/Node/ModuleNode.php
#	src/Node/Node.php
#	src/Node/TypesNode.php
#	src/Resources/core.php
#	src/Resources/debug.php
#	src/Test/IntegrationTestCase.php
#	tests/CustomExtensionTest.php
#	tests/EnvironmentTest.php
#	tests/ExpressionParserTest.php
#	tests/Extension/CoreTest.php
#	tests/Extension/EscaperTest.php
#	tests/Extension/LegacyDebugFunctionsTest.php
#	tests/Extension/LegacyStringLoaderFunctionsTest.php
#	tests/Extension/SandboxStateChangeTest.php
#	tests/Extension/SandboxTest.php
#	tests/LexerTest.php
#	tests/Node/Expression/CallTest.php
#	tests/Node/Expression/ConditionalTest.php
#	tests/Node/NodeTest.php
#	tests/Resources/LegacyCoreTest.php
#	tests/TemplateTest.php
#	tests/Util/CallableArgumentsExtractorTest.php
2026-07-12 13:55:37 +02:00
Fabien Potencier 9c6d76b61c Add void return type hint even in tests 2026-07-12 13:43:08 +02:00
Fabien Potencier 04ace9dba0 Merge branch '3.x' into 4.x
* 3.x:
  Handle single-node child template bodies in cleanup
  Keep captured block definitions supported
  Clarify captured block deprecation wording
  Simplify correctness visitor checks
  Move extends validation into correctness visitor
  Fix correctness visitor regressions
  Fix test assertions that did not verify the intended behavior
  Address review: fix block-nesting checks in CorrectnessNodeVisitor
  Move the extends-in-block and extends-in-macro errors into the CorrectnessNodeVisitor
  Introduce a CorrectnessNodeVisitor to validate that templates are semantically correct
  Mark Markup as final
  Allow calling a macro with a dynamic name via the dot operator
  Add an allow-list for tests to the sandbox security policy
  Fix markdown_to_html mangling content that starts with a blank line

# Conflicts:
#	CHANGELOG
#	doc/deprecated.rst
#	doc/sandbox.rst
#	src/ExpressionParser/Infix/DotExpressionParser.php
#	src/Extension/CoreExtension.php
#	src/Markup.php
#	src/Node/CheckSecurityNode.php
#	src/Node/Expression/Filter/DefaultFilter.php
#	src/Node/Expression/NullCoalesceExpression.php
#	src/Node/IfNode.php
#	src/NodeVisitor/SandboxNodeVisitor.php
#	src/Parser.php
#	src/Sandbox/SecurityPolicy.php
#	tests/Extension/SandboxTest.php
#	tests/ParserTest.php
2026-06-11 07:57:54 +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 c12100525e Introduce a CorrectnessNodeVisitor to validate that templates are semantically correct 2026-06-11 07:43:33 +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 16a7e4ec0d Merge branch '3.x' into 4.x
* 3.x:
  Document how to customize the markdown_to_html converter
  Make the include() function return a Markup object
  Fix nested block() resolution when a directly rendered block calls parent()
  Fix nested block() resolution when a directly rendered block calls parent()
  Document storing an enum in a variable to avoid repeating its FQCN
  Stop reporting a skipped test in IntegrationTestCase when there is no legacy test to run
  Document {#--#} as the replacement for the deprecated spaceless filter
  Skip the string cast in PrintNode when the expression is already a string and add tests
  Ensure PrintNode is yielding string content
  CoreExtension::getAttribute: small improvement regarding getter/isser/hasser

# Conflicts:
#	CHANGELOG
#	tests/Node/ForTest.php
2026-06-06 08:48:52 +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
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 b91dbaa1ba Fix merge conflict resolution 2026-05-21 14:11:53 +02:00
Fabien Potencier 8dd0383353 Merge branch '3.x' into 4.x
* 3.x: (23 commits)
  Bump version
  Prepare the 3.26.0 release
  Update CHANGELOG
  Document that the sandbox doesn't protect against resource exhaustion
  Document template_from_string caveats when used in a sandboxed env
  Pre-escape HTML input on the `spaceless` filter
  Add docs on Markup about the goal of this class in the context of a sandbox
  Fix sandbox bypass in the "column" filter
  Fix sandbox `__toString` bypasses
  Validate macro name in MacroReferenceExpression constructor
  Fix sandbox bypass: PHP code injection via _self / import macro reference
  Fix deprecations in tests
  Fix sandbox bypass in the `{% sandbox %}` tag when including a preloaded template
  Encode single quotes as \x27 in Compiler::string()
  Fix sandbox bypass: PHP code injection via {% use %} template name
  Fix unbounded memoisation of `IntlDateFormatter` / `NumberFormatter`
  Fix deprecation
  [Profiler] Escape template and profile names in HtmlDumper
  Bump version
  Fix sandbox bypass: propagate sandbox state to checkArrow for source-policy sandboxing
  ...

# Conflicts:
#	CHANGELOG
#	doc/filters/spaceless.rst
#	extra/cssinliner-extra/CssInlinerExtension.php
#	extra/inky-extra/InkyExtension.php
#	extra/markdown-extra/MarkdownExtension.php
#	src/Environment.php
#	src/ExpressionParser/Infix/DotExpressionParser.php
#	src/Extension/CoreExtension.php
#	src/Node/Expression/FilterExpression.php
#	src/Node/Expression/FunctionExpression.php
#	src/Node/Expression/TestExpression.php
#	src/Node/ModuleNode.php
#	src/NodeVisitor/SandboxNodeVisitor.php
#	src/Resources/core.php
#	src/TokenParser/SandboxTokenParser.php
#	tests/Extension/SandboxTest.php
2026-05-21 13:58:45 +02:00
Fabien Potencier ea3f7a2844 Validate macro name in MacroReferenceExpression constructor
The name passed to MacroReferenceExpression is emitted as raw PHP in
compile() via "->{$name}(...)". Callers were expected to validate
the name, but a missing check led to CVE-2026-XXXXX (PHP code injection
via _self / import macro reference): defense-in-depth, validate the
name in the constructor so the class is safe by construction.
2026-05-19 23:42:31 +02:00
Alexandre Daubois e9ff55f691 Fix sandbox bypass: PHP code injection via {% use %} template name 2026-05-19 22:50:45 +02:00
Fabien Potencier 0c515667d2 Merge remote-tracking branch 'origin/3.x' into 4.x
* origin/3.x:
  Add a `needs_is_sandboxed` option for filters, functions, and tests
  Bump version
  Make embeds deterministic
  [Doc] Document loose comparison in the `in` operator
  [Doc] Reword whitespace control note about first-newline removal
  Stop publishing extra package minor versions with no changes
  Lazy load EscaperRuntime in EscaperExtension
  Fix typo
  Replace parent-child analogy in `doc/tags/extends.rst`
  doc: Add missing toctree entries and fix ordering
  Fix CHANGELOG
  Bump version
  Prepare the 3.24.0 release
2026-05-17 08:18:04 +01:00
Fabien Potencier 5462817da0 Add a needs_is_sandboxed option for filters, functions, and tests 2026-05-16 18:52:17 +01:00
Fabien Potencier 9a198ce169 Fix tests 2026-02-09 12:32:40 +01:00
Fabien Potencier 463ef4018d Merge branch '3.x' into 4.x
* 3.x:
  Update CHANGELOG
  Add `html_attr_relaxed` escaping strategy
  re-add mixed return type
  Support short-circuiting in null-safe operator chains
  Add support for renaming variables in object destructuring
  Update .gitattributes to remove splitsh.json
  Fix intro for operator precedence table ?
2026-02-09 12:29:34 +01:00
Fabien Potencier 751a187f07 feature #4748 Support short-circuiting in null-safe operator chains (HypeMC)
This PR was merged into the 3.x branch.

Discussion
----------

Support short-circuiting in null-safe operator chains

This PR adds short-circuiting for null-safe operator chains, using the same rules as PHP, `PropertyAccess`, and the `ExpressionLanguage`.

Previously, only the immediate null-safe access was guarded. With this change, as soon as a `null` is encountered at a null-safe access, the rest of the chain is skipped.

My approach was to move the null check outside of the `getAttribute()` calls so the expression can immediately return `null`, eg:

```twig
foo?.bar.baz
```

Before:

```php
yield $this->env
    ->getRuntime('Twig\Runtime\EscaperRuntime')
    ->escape(
        CoreExtension::getAttribute(
            $this->env,
            $this->source,
            (
                null === (
                    $_v0 = (
                        isset($context['foo']) || array_key_exists('foo', $context)
                            ? $context['foo']
                            : throw new RuntimeError('Variable "foo" does not exist.', 3, $this->source)
                    )
                )
                    ? null
                    : CoreExtension::getAttribute(
                        $this->env,
                        $this->source,
                        $_v0,
                        'bar',
                        [],
                        'any',
                        false,
                        false,
                        false,
                        3
                    )
            ),
            'baz',
            [],
            'any',
            false,
            false,
            false,
            3
        ),
        'html',
        null,
        true
    );
```

Now:

```php
yield $this->env
    ->getRuntime('Twig\Runtime\EscaperRuntime')
    ->escape(
        (
            null === (
                $_v0 = (
                    isset($context['foo']) || array_key_exists('foo', $context)
                        ? $context['foo']
                        : throw new RuntimeError('Variable "foo" does not exist.', 3, $this->source)
                )
            )
                ? null
                : CoreExtension::getAttribute(
                    $this->env,
                    $this->source,
                    CoreExtension::getAttribute(
                        $this->env,
                        $this->source,
                        $_v0,
                        'bar',
                        [],
                        'any',
                        false,
                        false,
                        false,
                        3
                    ),
                    'baz',
                    [],
                    'any',
                    false,
                    false,
                    false,
                    3
                )
        ),
        'html',
        null,
        true
    );
```

Commits
-------

d56e8e2dba Support short-circuiting in null-safe operator chains
2026-02-08 19:02:03 +01:00
Fabien Potencier 2fba06cba9 Fix tests 2026-02-07 09:18:21 +01:00
Fabien Potencier cdce18d02a Fix CS 2026-02-07 09:16:06 +01:00
Fabien Potencier 0facb551b0 Merge branch '3.x' into 4.x
* 3.x:
  Fix CS
2026-02-07 09:12:05 +01:00
Fabien Potencier 861215c507 Fix CS 2026-02-07 09:07:38 +01:00
HypeMC d56e8e2dba Support short-circuiting in null-safe operator chains 2026-02-06 22:36:57 +01:00
Fabien Potencier e968cf6591 Merge branch '3.x' into 4.x
* 3.x:
  Tweak null-safe operator implementation
  Add null-safe operator
  Update u.rst to clarify truncate method's third argument behavior
2026-01-17 15:17:13 +01:00
Felds Liscia 263c04fd1f Add null-safe operator 2026-01-17 14:57:47 +01:00
Fabien Potencier 8391928896 Fix deprecations 2026-01-12 09:52:14 +01:00
Fabien Potencier b03de9de05 Merge branch '3.x' into 4.x
* 3.x:
  Update CHANGELOG
  Fix accessing arrays with stringable objects as key
  Update inky_to_html.rst: Updating link
  Update replace.rst
  [Doc] Tweaks in the escaping article
  Compile 'index' with repr (not string) in EmbedNode
  Introduce registerUndefinedTestCallback
  Fix intl test
  Bump minimum Commonmark requirement
  Support two words test guard
  Bump version
  Improve documentation examples for `enum` and `enum_cases`
  Avoid errors when failing to guess the template info for an error
  Add note to format_datetime explaining how to install required extensions
  Fix compatibility layer
2025-10-29 11:55:46 -04:00