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 merged into the 3.x branch.
Discussion
----------
Add throw tag to parse methods
Hi `@fabpot`, with PHPStan improving every day his exception checking, it's useful to have well documented method.
I didn't update all of them (there are too many), and focus on the one I have issue with:
- Almost all the InfixExpressionParserInterface/PrefixExpressionParserInterface implements throws a SyntaxError in parse method
- Parser::parse method is catching SyntaxError and rethrowing them so it should be added to the phpdoc
- Since Parser::parse catch Parser::subparse, it would be useful to add the phpdoc to subparse
Commits
-------
790eee7ae0 Add throw tag to parse methods
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
Support two words test guard
Extracted from https://github.com/twigphp/Twig/pull/4687
Commits
-------
30977bdea9 Support two words test guard
This PR was squashed before being merged into the 3.x branch.
Discussion
----------
Create attributes `AsTwigFilter`, `AsTwigFunction` and `AsTwigTest` to ease extension development
One drawback to writing extensions at present is that the declaration of functions/filters/tests is not directly adjacent to the methods. It's worse for runtime extensions because they need to be in 2 different classes. See [`SerializerExtension`](https://github.com/symfony/symfony/blob/7.0/src/Symfony/Bridge/Twig/Extension/SerializerExtension.php) and [`SerializerRuntime`](https://github.com/symfony/symfony/blob/7.0/src/Symfony/Bridge/Twig/Extension/SerializerRuntime.php) as an example.
By using attributes for filters, functions and tests definition, we can make writing extensions more expressive, and use reflection to detect particular options (`needs_environment`, `needs_context`, `is_variadic`).
Example if we implemented the `formatDate` filter: https://github.com/twigphp/Twig/blob/aeeec9a5e907a79e50a6bb78979154599401726e/extra/intl-extra/IntlExtension.php#L392-L395
By using the `AsTwigFilter` attribute, it is not necessary to create the `getFilters()` method. The `needs_environment` option is detected from method signature. The name is still required as the method naming convention (camelCase) doesn't match with Twig naming convention (snake_case).
```php
use Twig\Extension\Attribute\AsTwigFilter;
class IntlExtension
{
#[AsTwigFilter(name: 'format_date')]
public function formatDate(Environment $env, $date, ?string $dateFormat = 'medium', string $pattern = '', $timezone = null, string $calendar = 'gregorian', string $locale = null): string
{
return $this->formatDateTime($env, $date, $dateFormat, 'none', $pattern, $timezone, $calendar, $locale);
}
}
```
This approach does not totally replace the current definition of extensions, which is still necessary for advanced needs. It does, however, make for more pleasant reading and writing.
This makes writing lazy-loaded runtime extension the easiest way to create Twig extension in Symfony: https://github.com/symfony/symfony/pull/52748
Related to https://github.com/symfony/symfony/issues/50016
Is there any need to cache the parsing of method attributes? They are only read at compile time, but that can have a performance impact during development or when using dynamic templates.
Commits
-------
5886907b28 Create attributes `AsTwigFilter`, `AsTwigFunction` and `AsTwigTest` to ease extension development
This PR was merged into the 3.x branch.
Discussion
----------
Avoid polluting ModuleNode::toString() with embedded templates
Commits
-------
3d760aec1c Avoid polluting ModuleNode::toString() with embedded templates