mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-02 21:46:48 +00:00
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:
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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');
|
||||
|
||||
@@ -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()
|
||||
;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
|
||||
@@ -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__,
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user