This PR was merged into the 3.x branch.
Discussion
----------
Tweak null-safe operator implementation
Follow-up for #4717
Commits
-------
6904954165 Tweak null-safe operator implementation
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
Add null-safe operator
Adds native support for Twig’s null-safe `?.` operator so templates can traverse objects and arrays without defensive plumbing: `{{ user?.address?.city }}` now renders the value when present and stays silent when any hop is `null`.
`?.` reuses the existing `GetAttrExpression` operator, so it should have otherwise the same precedence and behavior as `.`.
Usage cases can be found in the tests:
https://github.com/twigphp/Twig/blob/7d98d45f58df040f41a81f7f8d4cce6c42be781e/tests/ExpressionParserTest.php#L304-L343
Tests cover both the rendered output and the generated PHP.
Let me know if any tests are missing or if the implementation should be done any other way.
Commits
-------
263c04fd1f Add null-safe operator
This PR was merged into the 3.x branch.
Discussion
----------
Update u.rst to clarify truncate method's third argument behavior
Current wording "to preserve whole words" suggests setting the argument to ``true`` preserves words. However, the parameter is ``$cut`` (defaults to ``true`` for cutting at exact length), and ``false`` is required to preserve whole words.
Commits
-------
28c2606be7 Update u.rst to clarify truncate method's third argument behavior
This PR was merged into the 3.x branch.
Discussion
----------
Fix documentation for getOperators()
Closes#4710
Commits
-------
ae51f93f70 Fix documentation for getOperators()
This PR was merged into the 3.x branch.
Discussion
----------
bump version
#4736 added new operators thus require the minor version to be increased
Commits
-------
55cb67f87d bump version
Current wording "to preserve whole words" suggests setting the argument to ``true`` preserves words. However, the parameter is ``$cut`` (defaults to ``true`` for cutting at exact length), and ``false`` is required to preserve whole words.
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
Enhance enum.rst with dynamic case example
Added example for dynamic enum case display.
Commits
-------
bcc5ffc301 Enhance enum.rst with dynamic case example
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
Update extends.rst
Semantically correct HTML elements instead of `<div>`itis
Commits
-------
5b63d90bfb Update extends.rst
This PR was merged into the 3.x branch.
Discussion
----------
Fix intl-extra tests
Fix CI since `Scripts::getNames()` returns 4 new values. It just tests if the value is an array to limit maintenance on future updates.
Commits
-------
683adc550f Fix intl-extra tests
This PR was merged into the 3.x branch.
Discussion
----------
Fix tiny typo in CI step name
Just a nano-typo there in a step name
`symfony/translation-contract`+`s`
Commits
-------
949f351458 Fix tiny typo in CI workflow label
This PR was merged into the 3.x branch.
Discussion
----------
Fix opcache preload warning for unlinked anonymous class
This fixes PHP opcache preload warning, caused by https://github.com/php/php-src/issues/10131 . The warning is now produced when the preload is initiated.
> Can't preload unlinked class Twig\ExpressionParser\Infix\BinaryOperatorExpressionParser@anonymous: Unknown parent Twig\ExpressionParser\Infix\BinaryOperatorExpressionParser
This started with Twig 3.21, when the anonymous class started to be used in ExtensionSet.
This is a similar woraround as is already used in a TwigBridge, as suggested by `@nicolas`-grekas here https://github.com/symfony/symfony/pull/38533
Also similar fix is in API platform: https://github.com/api-platform/core/pull/3827
Commits
-------
86997d1bef Fix opcache preload warning for unlinked anonymous class
This PR was merged into the 3.x branch.
Discussion
----------
Add .gitignore & .gitattributes to all .gitattributes
Commits
-------
ff327e4163 Add .gitignore & .gitattributes to all .gitattributes
This PR was merged into the 3.x branch.
Discussion
----------
Avoid ord deprecation notice in PHP 8.5
Change the one usage of `ord()` in Twig where a multibyte character can trigger the new deprecation in PHP 8.5, which is in the `html_attr` escape functionality in EscaperRuntime, currently leading to:
```
ord(): Providing a string that is not one byte long is deprecated. Use ord($str[0]) instead"
```
This small change fixes it. There are no other usages of `ord()` in Twig which lead to this deprecation notice.
Commits
-------
4d98cce4e4 Avoid ord deprecation in PHP 8.5
Change the one usage of ord() in Twig where a multibyte character can trigger the new deprecation in PHP 8.5, which is in the `html_attr` escape functionality, previously leading to:
ord(): Providing a string that is not one byte long is deprecated. Use ord($str[0]) instead"
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
use getShareDir as an indicator of Symfony version
Proposal to fix#4719 , replaces #4721
Commits
-------
c4dcd0bb8c use getShareDir as an indicator of Symfony version
This PR was merged into the 3.x branch.
Discussion
----------
Add 'invoke' to filters index
Missing from https://github.com/twigphp/Twig/pull/4518 I think.
Commits
-------
f7daf71acc Add 'invoke' to filters index
This PR was merged into the 3.x branch.
Discussion
----------
Fix cycle() with non-countable ArrayAccess+Traversable objects
When using `cycle()` with an object that implements `\ArrayAccess` and `\Traversable` but is not `\Countable`, the function currently returns the object instance immediately after triggering the deprecation notice.
This prevents the value from being converted to an array, causing the cycle logic to fail or return the object itself.
This PR removes the early return to ensure `self::toArray()` is called, allowing these objects to be cycled correctly as expected.
**How to test**
```php
$seq = new class implements \ArrayAccess, \IteratorAggregate {
public function offsetExists($offset): bool { return true; }
public function offsetGet($offset): mixed { return 'val'; }
public function offsetSet($offset, $value): void {}
public function offsetUnset($offset): void {}
public function getIterator(): \Traversable { yield 'odd'; yield 'even'; }
};
// Should return 'odd', currently returns the $seq object
$result = CoreExtension::cycle($seq, 0);
```
Related to #4241
Commits
-------
473653d19b [Core] Fix cycle() with non-countable ArrayAccess+Traversable objects
This PR was merged into the 3.x branch.
Discussion
----------
Update .gitattributes to exclude phpstan configs
They where added in https://github.com/twigphp/Twig/pull/4458
Versions >= 3.16.0 have the not needed files
Commits
-------
2e0c874776 Update .gitattributes to exclude phpstan configs