mirror of
https://github.com/twigphp/Twig.git
synced 2026-08-31 20:47:28 +00:00
Add support for first class callables
This commit is contained in:
+4
-2
@@ -25,6 +25,7 @@ use Twig\Node\NodeOutputInterface;
|
||||
use Twig\Node\PrintNode;
|
||||
use Twig\Node\TextNode;
|
||||
use Twig\TokenParser\TokenParserInterface;
|
||||
use Twig\Util\ReflectionCallable;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
@@ -156,8 +157,9 @@ class Parser
|
||||
if (null !== $test) {
|
||||
$e = new SyntaxError(\sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext());
|
||||
|
||||
if (\is_array($test) && isset($test[0]) && $test[0] instanceof TokenParserInterface) {
|
||||
$e->appendMessage(\sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno));
|
||||
$callable = (new ReflectionCallable($test))->getCallable();
|
||||
if (\is_array($callable) && $callable[0] instanceof TokenParserInterface) {
|
||||
$e->appendMessage(\sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $callable[0]->getTag(), $lineno));
|
||||
}
|
||||
} else {
|
||||
$e = new SyntaxError(\sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext());
|
||||
|
||||
@@ -55,8 +55,10 @@ final class ReflectionCallable
|
||||
$callable = [$object, $r->name];
|
||||
$this->name = get_debug_type($object).'::'.$r->name;
|
||||
} elseif (\PHP_VERSION_ID >= 80111 && $class = $r->getClosureCalledClass()) {
|
||||
$callable = [$class->name, $r->name];
|
||||
$this->name = $class->name.'::'.$r->name;
|
||||
} elseif (\PHP_VERSION_ID < 80111 && $class = $r->getClosureScopeClass()) {
|
||||
$callable = [\is_array($callable) ? $callable[0] : $class->name, $r->name];
|
||||
$this->name = (\is_array($callable) ? $callable[0] : $class->name).'::'.$r->name;
|
||||
} else {
|
||||
$callable = $this->name = $r->name;
|
||||
|
||||
@@ -43,6 +43,9 @@ class FilterTest extends NodeTestCase
|
||||
$environment->addFilter(new TwigFilter('bar_closure', \Closure::fromCallable(twig_tests_filter_dummy::class), ['needs_environment' => true]));
|
||||
$environment->addFilter(new TwigFilter('barbar', 'Twig\Tests\Node\Expression\twig_tests_filter_barbar', ['needs_context' => true, 'is_variadic' => true]));
|
||||
$environment->addFilter(new TwigFilter('magic_static', __NAMESPACE__.'\ChildMagicCallStub::magicStaticCall'));
|
||||
if (\PHP_VERSION_ID >= 80111) {
|
||||
$environment->addExtension(new FilterTestExtension());
|
||||
}
|
||||
|
||||
$extension = new class() extends AbstractExtension {
|
||||
public function getFilters(): array
|
||||
@@ -121,6 +124,14 @@ class FilterTest extends NodeTestCase
|
||||
$node = $this->createFilter($string, 'barbar', ['arg2' => new ConstantExpression('bar', 1)]);
|
||||
$tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_filter_barbar($context, "abc", null, "bar")', $environment];
|
||||
|
||||
if (\PHP_VERSION_ID >= 80111) {
|
||||
$node = $this->createFilter($string, 'first_class_callable_static');
|
||||
$tests[] = [$node, 'Twig\Tests\Node\Expression\FilterTestExtension::staticMethod("abc")', $environment];
|
||||
|
||||
$node = $this->createFilter($string, 'first_class_callable_object');
|
||||
$tests[] = [$node, '$this->extensions[\'Twig\Tests\Node\Expression\FilterTestExtension\']->objectMethod("abc")', $environment];
|
||||
}
|
||||
|
||||
$node = $this->createFilter($string, 'barbar', [
|
||||
new ConstantExpression('1', 1),
|
||||
new ConstantExpression('2', 1),
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Twig\Tests\Node\Expression;
|
||||
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class FilterTestExtension extends AbstractExtension
|
||||
{
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new TwigFilter('first_class_callable_static', self::staticMethod(...)),
|
||||
new TwigFilter('first_class_callable_object', $this->objectMethod(...)),
|
||||
];
|
||||
}
|
||||
|
||||
public static function staticMethod()
|
||||
{
|
||||
}
|
||||
|
||||
public function objectMethod()
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user