mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-19 13:57:00 +00:00
Added support for unconsumed macro arguments
This commit is contained in:
@@ -20,6 +20,10 @@ Macros differs from native PHP functions in a few ways:
|
|||||||
|
|
||||||
* Arguments of a macro are always optional.
|
* Arguments of a macro are always optional.
|
||||||
|
|
||||||
|
* If more positional arguments are passed to the macro than accepted by the macro,
|
||||||
|
they end up in the special ``varargs`` variable as a list of values. This variable
|
||||||
|
is always available in the macro body.
|
||||||
|
|
||||||
But as with PHP functions, macros don't have access to the current template
|
But as with PHP functions, macros don't have access to the current template
|
||||||
variables.
|
variables.
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -93,7 +93,7 @@ access the variable attribute:
|
|||||||
don't put the braces around them.
|
don't put the braces around them.
|
||||||
|
|
||||||
If a variable or attribute does not exist, you will receive a ``null`` value
|
If a variable or attribute does not exist, you will receive a ``null`` value
|
||||||
when the ``strict_variables`` option is set to ``false``; alternatively, if ``strict_variables``
|
when the ``strict_variables`` option is set to ``false``; alternatively, if ``strict_variables``
|
||||||
is set, Twig will throw an error (see :ref:`environment options<environment_options>`).
|
is set, Twig will throw an error (see :ref:`environment options<environment_options>`).
|
||||||
|
|
||||||
.. sidebar:: Implementation
|
.. sidebar:: Implementation
|
||||||
@@ -541,6 +541,10 @@ macro call:
|
|||||||
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
|
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
Inside macros, you have access to special variable ``varargs``. If more positional arguments
|
||||||
|
are passed to the macro than accepted by the macro, they end up in the special ``varargs`` variable
|
||||||
|
as a list of values.
|
||||||
|
|
||||||
.. _twig-expressions:
|
.. _twig-expressions:
|
||||||
|
|
||||||
Expressions
|
Expressions
|
||||||
|
|||||||
+49
-19
@@ -16,8 +16,19 @@
|
|||||||
*/
|
*/
|
||||||
class Twig_Node_Macro extends Twig_Node
|
class Twig_Node_Macro extends Twig_Node
|
||||||
{
|
{
|
||||||
|
const VARARGS_NAME = 'varargs';
|
||||||
|
|
||||||
public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
||||||
{
|
{
|
||||||
|
foreach ($arguments as $argumentName => $argument) {
|
||||||
|
if (self::VARARGS_NAME === $argumentName) {
|
||||||
|
throw new Twig_Error_Syntax(sprintf(
|
||||||
|
'The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments',
|
||||||
|
self::VARARGS_NAME, $name, self::VARARGS_NAME
|
||||||
|
), $argument->getLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
|
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +41,7 @@ class Twig_Node_Macro extends Twig_Node
|
|||||||
{
|
{
|
||||||
$compiler
|
$compiler
|
||||||
->addDebugInfo($this)
|
->addDebugInfo($this)
|
||||||
->write(sprintf("public function get%s(", $this->getAttribute('name')))
|
->write(sprintf('public function get%s(', $this->getAttribute('name')))
|
||||||
;
|
;
|
||||||
|
|
||||||
$count = count($this->getNode('arguments'));
|
$count = count($this->getNode('arguments'));
|
||||||
@@ -46,36 +57,55 @@ class Twig_Node_Macro extends Twig_Node
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID >= 50600) {
|
||||||
|
if ($count) {
|
||||||
|
$compiler->raw(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
$compiler->raw('...$__varargs__');
|
||||||
|
}
|
||||||
|
|
||||||
$compiler
|
$compiler
|
||||||
->raw(")\n")
|
->raw(")\n")
|
||||||
->write("{\n")
|
->write("{\n")
|
||||||
->indent()
|
->indent()
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!count($this->getNode('arguments'))) {
|
$compiler
|
||||||
$compiler->write("\$context = \$this->env->getGlobals();\n\n");
|
->write("\$context = \$this->env->mergeGlobals(array(\n")
|
||||||
} else {
|
->indent()
|
||||||
$compiler
|
;
|
||||||
->write("\$context = \$this->env->mergeGlobals(array(\n")
|
|
||||||
->indent()
|
|
||||||
;
|
|
||||||
|
|
||||||
foreach ($this->getNode('arguments') as $name => $default) {
|
|
||||||
$compiler
|
|
||||||
->write('')
|
|
||||||
->string($name)
|
|
||||||
->raw(' => $__'.$name.'__')
|
|
||||||
->raw(",\n")
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
foreach ($this->getNode('arguments') as $name => $default) {
|
||||||
$compiler
|
$compiler
|
||||||
->outdent()
|
->addIndentation()
|
||||||
->write("));\n\n")
|
->string($name)
|
||||||
|
->raw(' => $__'.$name.'__')
|
||||||
|
->raw(",\n")
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
$compiler
|
$compiler
|
||||||
|
->addIndentation()
|
||||||
|
->string(self::VARARGS_NAME)
|
||||||
|
->raw(' => ')
|
||||||
|
;
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID >= 50600) {
|
||||||
|
$compiler->raw("\$__varargs__,\n");
|
||||||
|
} else {
|
||||||
|
$compiler
|
||||||
|
->raw('func_num_args() > ')
|
||||||
|
->repr($count)
|
||||||
|
->raw(' ? array_slice(func_get_args(), ')
|
||||||
|
->repr($count)
|
||||||
|
->raw(") : array(),\n")
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
$compiler
|
||||||
|
->outdent()
|
||||||
|
->write("));\n\n")
|
||||||
->write("\$blocks = array();\n\n")
|
->write("\$blocks = array();\n\n")
|
||||||
->write("ob_start();\n")
|
->write("ob_start();\n")
|
||||||
->write("try {\n")
|
->write("try {\n")
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
--TEST--
|
||||||
|
macro with arbitrary arguments
|
||||||
|
--TEMPLATE--
|
||||||
|
{% from _self import test1, test2 %}
|
||||||
|
|
||||||
|
{% macro test1(var) %}
|
||||||
|
{{- var }}: {{ varargs|join(", ") }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro test2() %}
|
||||||
|
{{- varargs|join(", ") }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{{ test1("foo", "bar", "foobar") }}
|
||||||
|
{{ test2("foo", "bar", "foobar") }}
|
||||||
|
--DATA--
|
||||||
|
return array();
|
||||||
|
--EXPECT--
|
||||||
|
foo: bar, foobar
|
||||||
|
|
||||||
|
foo, bar, foobar
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
--TEST--
|
||||||
|
macro with varargs argument
|
||||||
|
--TEMPLATE--
|
||||||
|
{% macro test(varargs) %}
|
||||||
|
{% endmacro %}
|
||||||
|
--EXCEPTION--
|
||||||
|
Twig_Error_Syntax: The argument "varargs" in macro "test" cannot be defined because the variable "varargs" is reserved for arbitrary arguments in "index.twig" at line 2
|
||||||
|
|
||||||
@@ -31,14 +31,23 @@ class Twig_Tests_Node_MacroTest extends Twig_Test_NodeTestCase
|
|||||||
), array(), 1);
|
), array(), 1);
|
||||||
$node = new Twig_Node_Macro('foo', $body, $arguments, 1);
|
$node = new Twig_Node_Macro('foo', $body, $arguments, 1);
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID >= 50600) {
|
||||||
|
$declaration = ', ...$__varargs__';
|
||||||
|
$varargs = '$__varargs__';
|
||||||
|
} else {
|
||||||
|
$declaration = '';
|
||||||
|
$varargs = 'func_num_args() > 2 ? array_slice(func_get_args(), 2) : array()';
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
array($node, <<<EOF
|
array($node, <<<EOF
|
||||||
// line 1
|
// line 1
|
||||||
public function getfoo(\$__foo__ = null, \$__bar__ = "Foo")
|
public function getfoo(\$__foo__ = null, \$__bar__ = "Foo"$declaration)
|
||||||
{
|
{
|
||||||
\$context = \$this->env->mergeGlobals(array(
|
\$context = \$this->env->mergeGlobals(array(
|
||||||
"foo" => \$__foo__,
|
"foo" => \$__foo__,
|
||||||
"bar" => \$__bar__,
|
"bar" => \$__bar__,
|
||||||
|
"varargs" => $varargs,
|
||||||
));
|
));
|
||||||
|
|
||||||
\$blocks = array();
|
\$blocks = array();
|
||||||
|
|||||||
Reference in New Issue
Block a user