Merge branch '2.x' into 3.x

* 2.x:
  macros imported "globally" in a template are now available in macros without re-importing them
  added more tests
  added some tests
This commit is contained in:
Fabien Potencier
2019-05-17 14:16:15 +02:00
24 changed files with 205 additions and 41 deletions
+3 -1
View File
@@ -19,7 +19,9 @@
* 2.11.0 (2019-XX-XX)
* n/a
* 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
* 2.10.0 (2019-05-14)
+1
View File
@@ -32,6 +32,7 @@ class BlockNode extends Node
->addDebugInfo($this)
->write(sprintf("public function block_%s(\$context, array \$blocks = [])\n", $this->getAttribute('name')), "{\n")
->indent()
->write("\$macros = \$this->macros;\n")
;
$compiler
+3 -2
View File
@@ -27,8 +27,9 @@ class MethodCallExpression extends AbstractExpression
public function compile(Compiler $compiler): void
{
$compiler
->subcompile($this->getNode('node'))
->raw('->')
->raw('$macros[')
->repr($this->getNode('node')->getAttribute('name'))
->raw(']->')
->raw($this->getAttribute('method'))
->raw('(')
;
+13 -5
View File
@@ -22,19 +22,27 @@ use Twig\Node\Expression\NameExpression;
*/
class ImportNode extends Node
{
public function __construct(AbstractExpression $expr, AbstractExpression $var, int $lineno, string $tag = null)
public function __construct(AbstractExpression $expr, AbstractExpression $var, int $lineno, string $tag = null, bool $global = true)
{
parent::__construct(['expr' => $expr, 'var' => $var], [], $lineno, $tag);
parent::__construct(['expr' => $expr, 'var' => $var], ['global' => $global], $lineno, $tag);
}
public function compile(Compiler $compiler): void
{
$compiler
->addDebugInfo($this)
->write('')
->subcompile($this->getNode('var'))
->raw(' = ')
->write('$macros[')
->repr($this->getNode('var')->getAttribute('name'))
->raw('] = ')
;
if ($this->getAttribute('global')) {
$compiler
->raw('$this->macros[')
->repr($this->getNode('var')->getAttribute('name'))
->raw('] = ')
;
}
if ($this->getNode('expr') instanceof NameExpression && '_self' === $this->getNode('expr')->getAttribute('name')) {
$compiler->raw('$this');
+1 -3
View File
@@ -63,9 +63,7 @@ class MacroNode extends Node
->raw(")\n")
->write("{\n")
->indent()
;
$compiler
->write("\$macros = \$this->macros;\n")
->write("\$context = \$this->env->mergeGlobals([\n")
->indent()
;
+3 -1
View File
@@ -160,7 +160,8 @@ final class ModuleNode extends Node
->raw(" extends Template\n")
->write("{\n")
->indent()
->write("private \$source;\n\n")
->write("private \$source;\n")
->write("private \$macros = [];\n\n")
;
}
@@ -304,6 +305,7 @@ final class ModuleNode extends Node
$compiler
->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n")
->indent()
->write("\$macros = \$this->macros;\n")
->subcompile($this->getNode('display_start'))
->subcompile($this->getNode('body'))
;
+2 -13
View File
@@ -266,19 +266,8 @@ class Parser
public function getImportedSymbol(string $type, string $alias)
{
if (null !== $this->peekBlockStack()) {
foreach ($this->importedSymbols as $functions) {
if (isset($functions[$type][$alias])) {
if (count($this->blockStack) > 1) {
return null;
}
return $functions[$type][$alias];
}
}
} else {
return $this->importedSymbols[0][$type][$alias] ?? null;
}
// if the symbol does not exist in the current scope (0), try in the main/global scope (last index)
return $this->importedSymbols[0][$type][$alias] ?? ($this->importedSymbols[\count($this->importedSymbols) - 1][$type][$alias] ?? null);
}
public function isMainScope(): bool
+1 -1
View File
@@ -48,7 +48,7 @@ final class FromTokenParser extends AbstractTokenParser
$stream->expect(/* Token::BLOCK_END_TYPE */ 3);
$var = new AssignNameExpression($this->parser->getVarName(), $token->getLine());
$node = new ImportNode($macro, $var, $token->getLine(), $this->getTag());
$node = new ImportNode($macro, $var, $token->getLine(), $this->getTag(), $this->parser->isMainScope());
foreach ($targets as $name => $alias) {
$this->parser->addImportedSymbol('function', $alias, 'macro_'.$name, $var);
+1 -1
View File
@@ -32,7 +32,7 @@ final class ImportTokenParser extends AbstractTokenParser
$this->parser->addImportedSymbol('template', $var->getAttribute('name'));
return new ImportNode($macro, $var, $token->getLine(), $this->getTag());
return new ImportNode($macro, $var, $token->getLine(), $this->getTag(), $this->parser->isMainScope());
}
public function getTag(): string
@@ -0,0 +1,21 @@
--TEST--
"macro" tag
--TEMPLATE--
{% from _self import input %}
{% embed 'embed' %}
{% block foo %}
{{ input("username") }}
{% endblock %}
{% endembed %}
{% macro input(name) -%}
<input name="{{ name }}">
{% endmacro %}
--TEMPLATE(embed)--
{% block foo %}
{% endblock %}
--DATA--
return []
--EXCEPTION--
Twig\Error\SyntaxError: Unknown "input" function in "index.twig" at line 6.
@@ -0,0 +1,28 @@
--TEST--
"macro" tag
--TEMPLATE--
{%- from _self import input %}
{% block foo %}
{%- from "macros" import input %}
{{- input('username') }}
{% endblock %}
{% block bar %}
{{- input('username') }}
{% endblock %}
{% macro input(name) -%}
<input name="{{ name }}">
{% endmacro %}
--TEMPLATE(macros)--
{% macro input(name) %}
<input name="{{ name }}" value="local">
{% endmacro %}
--DATA--
return []
--EXPECT--
<input name="username" value="local">
<input name="username">
@@ -14,5 +14,5 @@
{% endmacro %}
--DATA--
return []
--EXCEPTION--
Twig\Error\SyntaxError: Unknown "another" function in "index.twig" at line 7.
--EXPECT--
OK
@@ -14,5 +14,5 @@
{% endmacro %}
--DATA--
return []
--EXCEPTION--
Twig\Error\SyntaxError: Unknown "input" function in "index.twig" at line 6.
--EXPECT--
<input name="username">
@@ -0,0 +1,27 @@
--TEST--
"import" tag
--TEMPLATE--
{% from _self import recursive_macro %}
{{ recursive_macro(10) }}
{% macro recursive_macro(n) %}
{% if n > 0 %}
{{- recursive_macro(n - 1) -}}
{% endif %}
{{- n }}
{% endmacro %}
--DATA--
return []
--EXPECT--
0
1
2
3
4
5
6
7
8
9
10
@@ -0,0 +1,21 @@
--TEST--
"macro" tag
--TEMPLATE--
{% import _self as macros %}
{% embed 'embed' %}
{% block foo %}
{{ macros.input("username") }}
{% endblock %}
{% endembed %}
{% macro input(name) -%}
<input name="{{ name }}">
{% endmacro %}
--TEMPLATE(embed)--
{% block foo %}
{% endblock %}
--DATA--
return []
--EXCEPTION--
Twig\Error\RuntimeError: Variable "macros" does not exist in "index.twig" at line 6.
@@ -0,0 +1,28 @@
--TEST--
"macro" tag
--TEMPLATE--
{%- import _self as macros %}
{% block foo %}
{%- import "macros" as macros %}
{{- macros.input('username') }}
{% endblock %}
{% block bar %}
{{- macros.input('username') }}
{% endblock %}
{% macro input(name) -%}
<input name="{{ name }}">
{% endmacro %}
--TEMPLATE(macros)--
{% macro input(name) %}
<input name="{{ name }}" value="local">
{% endmacro %}
--DATA--
return []
--EXPECT--
<input name="username" value="local">
<input name="username">
@@ -14,5 +14,5 @@
{% endmacro %}
--DATA--
return []
--EXCEPTION--
Twig\Error\RuntimeError: Variable "foo" does not exist in "index.twig" at line 7.
--EXPECT--
OK
@@ -15,4 +15,4 @@
--DATA--
return []
--EXCEPTION--
Twig\Error\RuntimeError: Accessing \Twig\Template attributes is forbidden in "index.twig" at line 6.
Twig\Error\RuntimeError: Variable "lmacros" does not exist in "index.twig" at line 6.
@@ -14,5 +14,5 @@
{% endmacro %}
--DATA--
return []
--EXCEPTION--
Twig\Error\RuntimeError: Accessing \Twig\Template attributes is forbidden in "index.twig" at line 6.
--EXPECT--
<input name="username">
@@ -0,0 +1,30 @@
--TEST--
"import" tag
--TEMPLATE--
{% extends "parent" %}
{% macro anotherThing() -%}
Do it too
{% endmacro %}
{% import _self as macros %}
{% block content %}
{{ parent() }}
{{ macros.anotherThing() }}
{% endblock %}
--TEMPLATE(parent)--
{% macro thing() %}
Do it
{% endmacro %}
{% import _self as macros %}
{% block content %}
{{ macros.thing() }}
{% endblock %}
--DATA--
return []
--EXPECT--
Do it
Do it too
+1
View File
@@ -34,6 +34,7 @@ class Twig_Tests_Node_BlockTest extends NodeTestCase
// line 1
public function block_foo(\$context, array \$blocks = [])
{
\$macros = \$this->macros;
echo "foo";
}
EOF
+1 -1
View File
@@ -36,7 +36,7 @@ class Twig_Tests_Node_ImportTest extends NodeTestCase
$tests[] = [$node, <<<EOF
// line 1
\$context["macro"] = \$this->loadTemplate("foo.twig", null, 1)->unwrap();
\$macros["macro"] = \$this->macros["macro"] = \$this->loadTemplate("foo.twig", null, 1)->unwrap();
EOF
];
+1
View File
@@ -43,6 +43,7 @@ class Twig_Tests_Node_MacroTest extends NodeTestCase
// line 1
public function macro_foo(\$__foo__ = null, \$__bar__ = "Foo", ...\$__varargs__)
{
\$macros = \$this->macros;
\$context = \$this->env->mergeGlobals([
"foo" => \$__foo__,
"bar" => \$__bar__,
+10 -4
View File
@@ -74,6 +74,7 @@ use Twig\Template;
class __TwigTemplate_%x extends Template
{
private \$source;
private \$macros = [];
public function __construct(Environment \$env)
{
@@ -89,6 +90,7 @@ class __TwigTemplate_%x extends Template
protected function doDisplay(array \$context, array \$blocks = [])
{
\$macros = \$this->macros;
// line 1
echo "foo";
}
@@ -100,7 +102,7 @@ class __TwigTemplate_%x extends Template
public function getDebugInfo()
{
return array ( 35 => 1,);
return array ( 37 => 1,);
}
public function getSourceContext()
@@ -136,6 +138,7 @@ use Twig\Template;
class __TwigTemplate_%x extends Template
{
private \$source;
private \$macros = [];
public function __construct(Environment \$env)
{
@@ -155,8 +158,9 @@ class __TwigTemplate_%x extends Template
protected function doDisplay(array \$context, array \$blocks = [])
{
\$macros = \$this->macros;
// line 2
\$context["macro"] = \$this->loadTemplate("foo.twig", "foo.twig", 2)->unwrap();
\$macros["macro"] = \$this->macros["macro"] = \$this->loadTemplate("foo.twig", "foo.twig", 2)->unwrap();
// line 1
\$this->parent = \$this->loadTemplate("layout.twig", "foo.twig", 1);
\$this->parent->display(\$context, array_merge(\$this->blocks, \$blocks));
@@ -174,7 +178,7 @@ class __TwigTemplate_%x extends Template
public function getDebugInfo()
{
return array ( 41 => 1, 39 => 2, 33 => 1,);
return array ( 43 => 1, 41 => 2, 34 => 1,);
}
public function getSourceContext()
@@ -215,6 +219,7 @@ use Twig\Template;
class __TwigTemplate_%x extends Template
{
private \$source;
private \$macros = [];
public function __construct(Environment \$env)
{
@@ -234,6 +239,7 @@ class __TwigTemplate_%x extends Template
protected function doDisplay(array \$context, array \$blocks = [])
{
\$macros = \$this->macros;
// line 4
\$context["foo"] = "foo";
// line 2
@@ -252,7 +258,7 @@ class __TwigTemplate_%x extends Template
public function getDebugInfo()
{
return array ( 41 => 2, 39 => 4, 33 => 2,);
return array ( 43 => 2, 41 => 4, 34 => 2,);
}
public function getSourceContext()