diff --git a/extra/html-extra/HtmlExtension.php b/extra/html-extra/HtmlExtension.php
index dcee84f52a..7776f615ff 100644
--- a/extra/html-extra/HtmlExtension.php
+++ b/extra/html-extra/HtmlExtension.php
@@ -108,6 +108,6 @@ public static function htmlClasses(...$args): string
}
}
- return implode(' ', array_unique($classes));
+ return implode(' ', array_unique(array_filter($classes, static function($v) { return '' !== $v; })));
}
}
diff --git a/extra/html-extra/Tests/Fixtures/html_classes.test b/extra/html-extra/Tests/Fixtures/html_classes.test
index 8a5304cf63..65ecaba6ad 100644
--- a/extra/html-extra/Tests/Fixtures/html_classes.test
+++ b/extra/html-extra/Tests/Fixtures/html_classes.test
@@ -1,12 +1,12 @@
--TEST--
"html_classes" function
--TEMPLATE--
-{{ html_classes('a', {'b': true, 'c': false}, 'd') }}
+{{ html_classes('a', {'b': true, 'c': false}, 'd', false ? 'e', true ? 'f', '0') }}
{% set class_a = 'a' %}
{% set class_b = 'b' %}
{{ html_classes(class_a, {(class_b): true})}}
--DATA--
return []
--EXPECT--
-a b d
+a b d f 0
a b
diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php
index 8c384e197f..b3429dd624 100644
--- a/src/Extension/CoreExtension.php
+++ b/src/Extension/CoreExtension.php
@@ -329,7 +329,7 @@ public static function cycle($values, $position)
}
if (!\count($values)) {
- throw new RuntimeError('The "cycle" function does not work on empty arrays');
+ throw new RuntimeError('The "cycle" function does not work on empty arrays.');
}
return $values[$position % \count($values)];
@@ -476,7 +476,7 @@ public static function sprintf($format, ...$values)
*
* @internal
*/
- public static function dateConverter(Environment $env, $date = null, $timezone = null): \DateTimeImmutable
+ public static function dateConverter(Environment $env, $date = null, $timezone = null): \DateTime|\DateTimeImmutable
{
// determine the timezone
if (false !== $timezone) {
@@ -492,7 +492,7 @@ public static function dateConverter(Environment $env, $date = null, $timezone =
return false !== $timezone ? $date->setTimezone($timezone) : $date;
}
- if ($date instanceof \DateTimeInterface) {
+ if ($date instanceof \DateTime) {
$date = \DateTimeImmutable::createFromInterface($date);
if (false !== $timezone) {
return $date->setTimezone($timezone);
diff --git a/src/Node/CheckSecurityNode.php b/src/Node/CheckSecurityNode.php
index 9df4ca913d..2b131ce6b1 100644
--- a/src/Node/CheckSecurityNode.php
+++ b/src/Node/CheckSecurityNode.php
@@ -24,6 +24,11 @@ class CheckSecurityNode extends Node
private array $usedTags;
private array $usedFunctions;
+ /**
+ * @param array $usedFilters
+ * @param array $usedTags
+ * @param array $usedFunctions
+ */
public function __construct(array $usedFilters, array $usedTags, array $usedFunctions)
{
$this->usedFilters = $usedFilters;
@@ -35,32 +40,21 @@ public function __construct(array $usedFilters, array $usedTags, array $usedFunc
public function compile(Compiler $compiler): void
{
- $tags = $filters = $functions = [];
- foreach (['tags', 'filters', 'functions'] as $type) {
- foreach ($this->{'used'.ucfirst($type)} as $name => $node) {
- if ($node instanceof Node) {
- ${$type}[$name] = $node->getTemplateLine();
- } else {
- ${$type}[$node] = null;
- }
- }
- }
-
$compiler
->write("\n")
->write("public function checkSecurity()\n")
->write("{\n")
->indent()
- ->write('static $tags = ')->repr(array_filter($tags))->raw(";\n")
- ->write('static $filters = ')->repr(array_filter($filters))->raw(";\n")
- ->write('static $functions = ')->repr(array_filter($functions))->raw(";\n\n")
+ ->write('static $tags = ')->repr(array_filter($this->usedTags))->raw(";\n")
+ ->write('static $filters = ')->repr(array_filter($this->usedFilters))->raw(";\n")
+ ->write('static $functions = ')->repr(array_filter($this->usedFunctions))->raw(";\n\n")
->write("try {\n")
->indent()
->write("\$this->sandbox->checkSecurity(\n")
->indent()
- ->write(!$tags ? "[],\n" : "['".implode("', '", array_keys($tags))."'],\n")
- ->write(!$filters ? "[],\n" : "['".implode("', '", array_keys($filters))."'],\n")
- ->write(!$functions ? "[],\n" : "['".implode("', '", array_keys($functions))."'],\n")
+ ->write(!$this->usedTags ? "[],\n" : "['".implode("', '", array_keys($this->usedTags))."'],\n")
+ ->write(!$this->usedFilters ? "[],\n" : "['".implode("', '", array_keys($this->usedFilters))."'],\n")
+ ->write(!$this->usedFunctions ? "[],\n" : "['".implode("', '", array_keys($this->usedFunctions))."'],\n")
->write("\$this->source\n")
->outdent()
->write(");\n")
diff --git a/src/NodeVisitor/SandboxNodeVisitor.php b/src/NodeVisitor/SandboxNodeVisitor.php
index 04431168c2..1933fa42be 100644
--- a/src/NodeVisitor/SandboxNodeVisitor.php
+++ b/src/NodeVisitor/SandboxNodeVisitor.php
@@ -34,8 +34,11 @@
final class SandboxNodeVisitor implements NodeVisitorInterface
{
private bool $inAModule = false;
+ /** @var array */
private array $tags;
+ /** @var array */
private array $filters;
+ /** @var array */
private array $functions;
private bool $needsToStringWrap = false;
@@ -51,22 +54,22 @@ public function enterNode(Node $node, Environment $env): Node
} elseif ($this->inAModule) {
// look for tags
if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) {
- $this->tags[$node->getNodeTag()] = $node;
+ $this->tags[$node->getNodeTag()] = $node->getTemplateLine();
}
// look for filters
if ($node instanceof FilterExpression && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) {
- $this->filters[$node->getNode('filter')->getAttribute('value')] = $node;
+ $this->filters[$node->getNode('filter')->getAttribute('value')] = $node->getTemplateLine();
}
// look for functions
if ($node instanceof FunctionExpression && !isset($this->functions[$node->getAttribute('name')])) {
- $this->functions[$node->getAttribute('name')] = $node;
+ $this->functions[$node->getAttribute('name')] = $node->getTemplateLine();
}
// the .. operator is equivalent to the range() function
if ($node instanceof RangeBinary && !isset($this->functions['range'])) {
- $this->functions['range'] = $node;
+ $this->functions['range'] = $node->getTemplateLine();
}
if ($node instanceof PrintNode) {
diff --git a/src/Test/IntegrationTestCase.php b/src/Test/IntegrationTestCase.php
index 0323e5a828..f3ee733866 100644
--- a/src/Test/IntegrationTestCase.php
+++ b/src/Test/IntegrationTestCase.php
@@ -189,7 +189,7 @@ protected function doIntegrationTest($file, $message, $condition, $templates, $e
// avoid using the same PHP class name for different cases
$p = new \ReflectionProperty($twig, 'templateClassPrefix');
$p->setAccessible(true);
- $p->setValue($twig, '__TwigTemplate_'.hash('xxh128', uniqid(mt_rand(), true), false).'_');
+ $p->setValue($twig, '__TwigTemplate_'.hash('xxh128', uniqid((string) mt_rand(), true), false).'_');
$deprecations = [];
try {
diff --git a/tests/Extension/EscaperTest.php b/tests/Extension/EscaperTest.php
index c465789153..d8fedc64e2 100644
--- a/tests/Extension/EscaperTest.php
+++ b/tests/Extension/EscaperTest.php
@@ -17,7 +17,7 @@
use Twig\Extension\EscaperExtension;
use Twig\Loader\LoaderInterface;
-class Twig_Tests_Extension_EscaperTest extends TestCase
+class EscaperTest extends TestCase
{
/**
* All character encodings supported by htmlspecialchars().
diff --git a/tests/Fixtures/functions/cycle_empty.test b/tests/Fixtures/functions/cycle_empty.test
index 1eaffc8e5f..bb338452a6 100644
--- a/tests/Fixtures/functions/cycle_empty.test
+++ b/tests/Fixtures/functions/cycle_empty.test
@@ -5,4 +5,4 @@
--DATA--
return []
--EXCEPTION--
-Twig\Error\RuntimeError: The "cycle" function does not work on empty arrays in "index.twig" at line 2
+Twig\Error\RuntimeError: The "cycle" function does not work on empty arrays in "index.twig" at line 2.
diff --git a/tests/Fixtures/functions/include/template_instance.test b/tests/Fixtures/functions/include/template_instance.test
index 4c8b450835..be18d244ac 100644
--- a/tests/Fixtures/functions/include/template_instance.test
+++ b/tests/Fixtures/functions/include/template_instance.test
@@ -1,5 +1,5 @@
--TEST--
-"include" function accepts Twig_Template instance
+"include" function accepts Twig\Template instance
--TEMPLATE--
{{ include(foo) }} FOO
--TEMPLATE(foo.twig)--
diff --git a/tests/Fixtures/tags/inheritance/parent_as_template_wrapper.test b/tests/Fixtures/tags/inheritance/parent_as_template_wrapper.test
index 1aaed556c5..cf257f25dc 100644
--- a/tests/Fixtures/tags/inheritance/parent_as_template_wrapper.test
+++ b/tests/Fixtures/tags/inheritance/parent_as_template_wrapper.test
@@ -1,5 +1,5 @@
--TEST--
-"extends" tag with a parent as a Twig_TemplateWrapper instance
+"extends" tag with a parent as a Twig\TemplateWrapper instance
--TEMPLATE--
{% extends foo %}
diff --git a/tests/Fixtures/tags/inheritance/template_instance.test b/tests/Fixtures/tags/inheritance/template_instance.test
index a5a223886d..b9009e5df5 100644
--- a/tests/Fixtures/tags/inheritance/template_instance.test
+++ b/tests/Fixtures/tags/inheritance/template_instance.test
@@ -1,5 +1,5 @@
--TEST--
-"extends" tag accepts Twig_Template instance
+"extends" tag accepts Twig\Template instance
--TEMPLATE--
{% extends foo %}
diff --git a/tests/Node/Expression/CallTest.php b/tests/Node/Expression/CallTest.php
index 992eacfcef..72681a4a1f 100644
--- a/tests/Node/Expression/CallTest.php
+++ b/tests/Node/Expression/CallTest.php
@@ -112,10 +112,10 @@ public function customFunctionWithArbitraryArguments()
public function testResolveArgumentsWithMissingParameterForArbitraryArgumentsOnFunction()
{
$this->expectException(\LogicException::class);
- $this->expectExceptionMessageMatches('#^The last parameter of "Twig\\\\Tests\\\\Node\\\\Expression\\\\custom_Twig_Tests_Node_Expression_CallTest_function" for function "foo" must be an array with default value, eg\\. "array \\$arg \\= \\[\\]"\\.$#');
+ $this->expectExceptionMessageMatches('#^The last parameter of "Twig\\\\Tests\\\\Node\\\\Expression\\\\custom_call_test_function" for function "foo" must be an array with default value, eg\\. "array \\$arg \\= \\[\\]"\\.$#');
$node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'foo', 'is_variadic' => true]);
- $node->getArguments('Twig\Tests\Node\Expression\custom_Twig_Tests_Node_Expression_CallTest_function', []);
+ $node->getArguments('Twig\Tests\Node\Expression\custom_call_test_function', []);
}
public function testResolveArgumentsWithMissingParameterForArbitraryArgumentsOnObject()
@@ -143,6 +143,6 @@ public function __invoke($required)
}
}
-function custom_Twig_Tests_Node_Expression_CallTest_function($required)
+function custom_call_test_function($required)
{
}
diff --git a/tests/Util/DeprecationCollectorTest.php b/tests/Util/DeprecationCollectorTest.php
index 7b5794d83c..18f889f6a4 100644
--- a/tests/Util/DeprecationCollectorTest.php
+++ b/tests/Util/DeprecationCollectorTest.php
@@ -28,7 +28,7 @@ public function testCollect()
$twig->addFunction(new TwigFunction('deprec', [$this, 'deprec'], ['deprecated' => '1.1']));
$collector = new DeprecationCollector($twig);
- $deprecations = $collector->collect(new Twig_Tests_Util_Iterator());
+ $deprecations = $collector->collect(new Iterator());
$this->assertEquals(['Twig Function "deprec" is deprecated since version 1.1 in deprec.twig at line 1.'], $deprecations);
}
@@ -38,7 +38,7 @@ public function deprec()
}
}
-class Twig_Tests_Util_Iterator implements \IteratorAggregate
+class Iterator implements \IteratorAggregate
{
public function getIterator(): \Traversable
{