mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-10 01:16:52 +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\PrintNode;
|
||||||
use Twig\Node\TextNode;
|
use Twig\Node\TextNode;
|
||||||
use Twig\TokenParser\TokenParserInterface;
|
use Twig\TokenParser\TokenParserInterface;
|
||||||
|
use Twig\Util\ReflectionCallable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
@@ -156,8 +157,9 @@ class Parser
|
|||||||
if (null !== $test) {
|
if (null !== $test) {
|
||||||
$e = new SyntaxError(\sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext());
|
$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) {
|
$callable = (new ReflectionCallable($test))->getCallable();
|
||||||
$e->appendMessage(\sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno));
|
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 {
|
} else {
|
||||||
$e = new SyntaxError(\sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext());
|
$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];
|
$callable = [$object, $r->name];
|
||||||
$this->name = get_debug_type($object).'::'.$r->name;
|
$this->name = get_debug_type($object).'::'.$r->name;
|
||||||
} elseif (\PHP_VERSION_ID >= 80111 && $class = $r->getClosureCalledClass()) {
|
} elseif (\PHP_VERSION_ID >= 80111 && $class = $r->getClosureCalledClass()) {
|
||||||
|
$callable = [$class->name, $r->name];
|
||||||
$this->name = $class->name.'::'.$r->name;
|
$this->name = $class->name.'::'.$r->name;
|
||||||
} elseif (\PHP_VERSION_ID < 80111 && $class = $r->getClosureScopeClass()) {
|
} 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;
|
$this->name = (\is_array($callable) ? $callable[0] : $class->name).'::'.$r->name;
|
||||||
} else {
|
} else {
|
||||||
$callable = $this->name = $r->name;
|
$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('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('barbar', 'Twig\Tests\Node\Expression\twig_tests_filter_barbar', ['needs_context' => true, 'is_variadic' => true]));
|
||||||
$environment->addFilter(new TwigFilter('magic_static', __NAMESPACE__.'\ChildMagicCallStub::magicStaticCall'));
|
$environment->addFilter(new TwigFilter('magic_static', __NAMESPACE__.'\ChildMagicCallStub::magicStaticCall'));
|
||||||
|
if (\PHP_VERSION_ID >= 80111) {
|
||||||
|
$environment->addExtension(new FilterTestExtension());
|
||||||
|
}
|
||||||
|
|
||||||
$extension = new class() extends AbstractExtension {
|
$extension = new class() extends AbstractExtension {
|
||||||
public function getFilters(): array
|
public function getFilters(): array
|
||||||
@@ -121,6 +124,14 @@ class FilterTest extends NodeTestCase
|
|||||||
$node = $this->createFilter($string, 'barbar', ['arg2' => new ConstantExpression('bar', 1)]);
|
$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];
|
$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', [
|
$node = $this->createFilter($string, 'barbar', [
|
||||||
new ConstantExpression('1', 1),
|
new ConstantExpression('1', 1),
|
||||||
new ConstantExpression('2', 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