added support for macros on "is defined" tests

This commit is contained in:
Fabien Potencier
2019-05-17 17:35:00 +02:00
parent f6855c6182
commit 9fe3213d1b
5 changed files with 63 additions and 1 deletions
+1
View File
@@ -1,5 +1,6 @@
* 2.11.0 (2019-XX-XX)
* added support for macros on "is defined" tests
* fixed macros "import" when using the same name in the parent and child templates
* fixed recursive macros
* macros imported "globally" in a template are now available in macros without re-importing them
+5
View File
@@ -679,6 +679,11 @@ class ExpressionParser
$arguments = $this->parseArguments(true);
}
if ('defined' === $name && $node instanceof NameExpression && null !== $alias = $this->parser->getImportedSymbol('function', $node->getAttribute('name'))) {
$node = new MethodCallExpression($alias['node'], $alias['name'], new ArrayExpression([], $node->getTemplateLine()), $node->getTemplateLine());
$node->setAttribute('safe', true);
}
return new $class($node, $name, $arguments, $this->parser->getCurrentToken()->getLine());
}
+13 -1
View File
@@ -17,7 +17,7 @@ class MethodCallExpression extends AbstractExpression
{
public function __construct(AbstractExpression $node, string $method, ArrayExpression $arguments, int $lineno)
{
parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false], $lineno);
parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false, 'is_defined_test' => false], $lineno);
if ($node instanceof NameExpression) {
$node->setAttribute('always_defined', true);
@@ -26,6 +26,18 @@ class MethodCallExpression extends AbstractExpression
public function compile(Compiler $compiler)
{
if ($this->getAttribute('is_defined_test')) {
$compiler
->raw('method_exists($macros[')
->repr($this->getNode('node')->getAttribute('name'))
->raw('], ')
->repr($this->getAttribute('method'))
->raw(')')
;
return;
}
$compiler
->raw('$macros[')
->repr($this->getNode('node')->getAttribute('name'))
+3
View File
@@ -18,6 +18,7 @@ use Twig\Node\Expression\BlockReferenceExpression;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Expression\FunctionExpression;
use Twig\Node\Expression\GetAttrExpression;
use Twig\Node\Expression\MethodCallExpression;
use Twig\Node\Expression\NameExpression;
use Twig\Node\Expression\TestExpression;
use Twig\Node\Node;
@@ -47,6 +48,8 @@ class DefinedTest extends TestExpression
$node->setAttribute('is_defined_test', true);
} elseif ($node instanceof ConstantExpression || $node instanceof ArrayExpression) {
$node = new ConstantExpression(true, $node->getTemplateLine());
} elseif ($node instanceof MethodCallExpression) {
$node->setAttribute('is_defined_test', true);
} else {
throw new SyntaxError('The "defined" test only works with simple variables.', $lineno);
}
@@ -0,0 +1,41 @@
--TEST--
"defined" support for macros
--TEMPLATE--
{% import _self as macros %}
{% from _self import hello, bar %}
{% if macros.hello is defined -%}
OK
{% endif %}
{% if macros.foo is not defined -%}
OK
{% endif %}
{% if hello is defined -%}
OK
{% endif %}
{% if bar is not defined -%}
OK
{% endif %}
{% if foo is not defined -%}
OK
{% endif %}
{% macro hello(name) %}
Hello {{ name }}
{% endmacro %}
--DATA--
return []
--EXPECT--
OK
OK
OK
OK
OK