Aliased/extended classes may not be reflected correctly when creating filter expressions
The class reflection changes that were introduced in https://github.com/twigphp/Twig/commit/bb64a49441a00787ab2ea8f322b450af34f2778f may cause issues with classes that have __call or __callStatic magic method that belong to a parent class, like Laravel facades.
I've provided a test case as a patch below.
diff --git a/tests/Node/Expression/FilterTest.php b/tests/Node/Expression/FilterTest.php
index ef7c82cb..1a86e800 100644
--- a/tests/Node/Expression/FilterTest.php
+++ b/tests/Node/Expression/FilterTest.php
@@ -49,6 +49,7 @@ class FilterTest extends NodeTestCase
return [
new TwigFilter('foo', \Closure::fromCallable([$this, 'foo'])),
new TwigFilter('foobar', \Closure::fromCallable([$this, 'foobar'])),
+ new TwigFilter('alias_bar', ['Twig_Test_Alias_Class', 'test']),
];
}
@@ -135,6 +136,10 @@ class FilterTest extends NodeTestCase
$node = $this->createFilter($string, 'foobar');
$tests[] = [$node, '$this->env->getFilter(\'foobar\')->getCallable()("abc")', $environment];
+ // aliased class
+ $node = $this->createFilter($string, 'alias_bar');
+ $tests[] = [$node, '$this->env->getFilter(\'alias_bar\')->getCallable()("abc")', $environment];
+
return $tests;
}
@@ -190,3 +195,31 @@ function twig_tests_filter_dummy()
function twig_tests_filter_barbar($context, $string, $arg1 = null, $arg2 = null, array $args = [])
{
}
+
+// Sample class with a magic method
+class Twig_Test_Parent_Class
+{
+ public static function getAccessor()
+ {
+ throw new \Exception('Accessor not set');
+ }
+
+ public static function __callStatic($name, $arguments)
+ {
+ $accessor = static::getAccessor();
+
+ if ($name === 'test') {
+ return 'received ' . $arguments[0];
+ }
+ }
+}
+
+class Twig_Test_Child_Class extends Twig_Test_Parent_Class
+{
+ public static function getAccessor()
+ {
+ return 'child';
+ }
+}
+
+class_alias(Twig_Test_Child_Class::class, 'Twig_Test_Alias_Class');
It passes in the test case, in the sense that it creates the compiled getFilter call just fine - the issue would only manifest if one were to run the actual template, as it would throw the Accessor not set exception due to the $r->getClosureScopeClass() call here returning the class as Twig_Test_Parent_Class - ostensibly because this is the class that will actually fulfill the callable.
Refs:
- https://github.com/wintercms/winter/issues/557#issuecomment-1160480419
- https://github.com/twigphp/Twig/pull/3702#issuecomment-1160511737
@stof @nicolas-grekas is this enough information to go on?