diff --git a/src/Node/Expression/CallExpression.php b/src/Node/Expression/CallExpression.php index 6d105313c41..a3b7c7e0d93 100644 --- a/src/Node/Expression/CallExpression.php +++ b/src/Node/Expression/CallExpression.php @@ -289,6 +289,7 @@ private function reflectCallable($callable) return $this->reflector = [$r, $callable, $r->class.'::'.$r->name]; } + $checkVisibility = $callable instanceof \Closure; $r = new \ReflectionFunction(\Closure::fromCallable($callable)); if (false !== strpos($r->name, '{closure}')) { @@ -305,6 +306,10 @@ private function reflectCallable($callable) $callable = $callableName = $r->name; } + if ($checkVisibility && \is_array($callable) && method_exists(...$callable) && !(new \ReflectionMethod(...$callable))->isPublic()) { + $callable = $r->getClosure(); + } + return $this->reflector = [$r, $callable, $callableName]; } } diff --git a/tests/Node/Expression/FilterTest.php b/tests/Node/Expression/FilterTest.php index 21efa3c1bd9..ef7c82cba41 100644 --- a/tests/Node/Expression/FilterTest.php +++ b/tests/Node/Expression/FilterTest.php @@ -48,12 +48,17 @@ public function getFilters(): array { return [ new TwigFilter('foo', \Closure::fromCallable([$this, 'foo'])), + new TwigFilter('foobar', \Closure::fromCallable([$this, 'foobar'])), ]; } public function foo() { } + + protected function foobar() + { + } }; $environment->addExtension($extension); @@ -127,6 +132,9 @@ public function foo() $node = $this->createFilter($string, 'foo'); $tests[] = [$node, sprintf('$this->extensions[\'%s\']->foo("abc")', \get_class($extension)), $environment]; + $node = $this->createFilter($string, 'foobar'); + $tests[] = [$node, '$this->env->getFilter(\'foobar\')->getCallable()("abc")', $environment]; + return $tests; }