Skip to content

Commit 56a7aa4

Browse files
committed
Merge branch '3.x' into 4.x
* 3.x: use getShareDir as an indicator of Symfony version Add 'invoke' to filters index [Core] Fix cycle() with non-countable ArrayAccess+Traversable objects Update .gitattributes to exclude phpstan configs Bump version Prepare the 3.22.1 release Update CHANGELOG `CoreExtension` : Make error message more readable Add caution note for random function usage Add throw tag to parse methods
2 parents 83f264b + 8308f7f commit 56a7aa4

File tree

9 files changed

+27
-5
lines changed

9 files changed

+27
-5
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@
88
/.gitignore export-ignore
99
/.php-cs-fixer.dist.php export-ignore
1010
/phpunit.xml.dist export-ignore
11+
/phpstan.neon.dist export-ignore
12+
/phpstan-baseline.neon export-ignore

doc/filters/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Filters
2929
html_to_markdown
3030
inline_css
3131
inky_to_html
32+
invoke
3233
join
3334
json_encode
3435
keys

doc/functions/random.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ parameter type:
1010
* a random integer between the integer parameter (when negative) and 0 (inclusive).
1111
* a random integer between the first integer and the second integer parameter (inclusive).
1212

13+
.. caution::
14+
15+
The ``random`` function does not produce cryptographically secure random numbers.
16+
Do not use them for purposes that require returned values to be unguessable.
17+
1318
.. code-block:: twig
1419
1520
{{ random(['apple', 'orange', 'citrus']) }} {# example output: orange #}

src/ExpressionParser/InfixExpressionParserInterface.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@
1111

1212
namespace Twig\ExpressionParser;
1313

14+
use Twig\Error\SyntaxError;
1415
use Twig\Node\Expression\AbstractExpression;
1516
use Twig\Parser;
1617
use Twig\Token;
1718

1819
interface InfixExpressionParserInterface extends ExpressionParserInterface
1920
{
21+
/**
22+
* @throws SyntaxError
23+
*/
2024
public function parse(Parser $parser, AbstractExpression $left, Token $token): AbstractExpression;
2125

2226
public function getAssociativity(): InfixAssociativity;

src/ExpressionParser/PrefixExpressionParserInterface.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@
1111

1212
namespace Twig\ExpressionParser;
1313

14+
use Twig\Error\SyntaxError;
1415
use Twig\Node\Expression\AbstractExpression;
1516
use Twig\Parser;
1617
use Twig\Token;
1718

1819
interface PrefixExpressionParserInterface extends ExpressionParserInterface
1920
{
21+
/**
22+
* @throws SyntaxError
23+
*/
2024
public function parse(Parser $parser, Token $token): AbstractExpression;
2125
}

src/Extension/CoreExtension.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,9 @@ public static function cycle($values, $position): mixed
415415

416416
if (!is_countable($values)) {
417417
throw new RuntimeError('The "cycle" function expects a countable sequence as first argument.');
418-
}
419418

420-
$values = self::toArray($values, false);
419+
$values = self::toArray($values, false);
420+
}
421421
}
422422

423423
if (!$count = \count($values)) {
@@ -1817,7 +1817,7 @@ public static function getAttribute(Environment $env, Source $source, $object, $
18171817
return;
18181818
}
18191819

1820-
throw new RuntimeError(\sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()"/"has%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), $lineno, $source);
1820+
throw new RuntimeError(\sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()", "is%1$s()", "has%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), $lineno, $source);
18211821
}
18221822

18231823
if ($sandboxed) {

src/Parser.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ public function getEnvironment(): Environment
8686
return $this->env;
8787
}
8888

89+
/**
90+
* @throws SyntaxError
91+
*/
8992
public function parse(TokenStream $stream, $test = null, bool $dropNeedle = false): ModuleNode
9093
{
9194
$vars = get_object_vars($this);
@@ -170,6 +173,8 @@ public function subparseIgnoreUnknownTwigCallables($test, bool $dropNeedle = fal
170173

171174
/**
172175
* @phpstan-impure
176+
*
177+
* @throws SyntaxError
173178
*/
174179
public function subparse($test, bool $dropNeedle = false): Node
175180
{

tests/Extension/CoreTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
use PHPUnit\Framework\Attributes\DataProvider;
2424
use PHPUnit\Framework\TestCase;
25+
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
2526
use Twig\Environment;
2627
use Twig\Error\RuntimeError;
2728
use Twig\Extension\CoreExtension;

tests/TemplateTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ public static function getAttributeExceptions()
8585
['{{ empty_array.a }}', 'Key "a" does not exist as the sequence/mapping is empty in "%s" at line 1.'],
8686
['{{ array.a }}', 'Key "a" for sequence/mapping with keys "foo" does not exist in "%s" at line 1.'],
8787
['{{ array.(-10) }}', 'Key "-10" for sequence/mapping with keys "foo" does not exist in "%s" at line 1.'],
88-
['{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()"/"isa()"/"hasa()" or "__call()" exist and have public access in class "Twig\Tests\TemplateArrayAccessObject" in "%s" at line 1.'],
89-
['{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()"/"ismissing_method()"/"hasmissing_method()" or "__call()" exist and have public access in class "Twig\Tests\TemplateArrayAccessObject" in "%s" at line 1.'],
88+
['{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()", "isa()", "hasa()" or "__call()" exist and have public access in class "Twig\Tests\TemplateArrayAccessObject" in "%s" at line 1.'],
89+
['{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()", "ismissing_method()", "hasmissing_method()" or "__call()" exist and have public access in class "Twig\Tests\TemplateArrayAccessObject" in "%s" at line 1.'],
9090
['{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.'],
9191
['{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1.'],
9292
];

0 commit comments

Comments
 (0)