mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-02 05:26:43 +00:00
Add support for named arguments on special functions
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# 3.12.0 (2024-XX-XX)
|
||||
|
||||
* Add support for named arguments to the `block`, and `attribute` functions
|
||||
* Throw a SyntaxError exception at compile time when a Twig callable has not the minimum number of required arguments
|
||||
* Add a `CallableArgumentsExtractor` class
|
||||
* Deprecate passing a name to `FunctionExpression`, `FilterExpression`, and `TestExpression`;
|
||||
|
||||
@@ -21,3 +21,10 @@ attribute:
|
||||
|
||||
The resolution algorithm is the same as the one used for the ``.``
|
||||
notation, except that the item can be any valid expression.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``variable``: The variable
|
||||
* ``attribute``: The attribute name
|
||||
* ``arguments``: An array of arguments to pass to the call
|
||||
|
||||
@@ -32,6 +32,12 @@ current template:
|
||||
...
|
||||
{% endif %}
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
* ``name``: The block name
|
||||
* ``template``: The template where to look for the block
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`extends<../tags/extends>`, :doc:`parent<../functions/parent>`
|
||||
|
||||
+13
-11
@@ -33,6 +33,7 @@ use Twig\Node\Expression\Unary\NegUnary;
|
||||
use Twig\Node\Expression\Unary\NotUnary;
|
||||
use Twig\Node\Expression\Unary\PosUnary;
|
||||
use Twig\Node\Node;
|
||||
use Twig\Util\CallableArgumentsExtractor;
|
||||
|
||||
/**
|
||||
* Parses expressions.
|
||||
@@ -458,7 +459,6 @@ class ExpressionParser
|
||||
{
|
||||
switch ($name) {
|
||||
case 'parent':
|
||||
$this->parseArguments();
|
||||
if (!\count($this->parser->getBlockStack())) {
|
||||
throw new SyntaxError('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
@@ -467,21 +467,23 @@ class ExpressionParser
|
||||
throw new SyntaxError('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
|
||||
$this->parseArguments(true);
|
||||
|
||||
return new ParentExpression($this->parser->peekBlockStack(), $line);
|
||||
case 'block':
|
||||
$args = $this->parseArguments();
|
||||
if (\count($args) < 1) {
|
||||
throw new SyntaxError('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
$fakeNode = new Node(lineno: $line);
|
||||
$fakeNode->setSourceContext($this->parser->getStream()->getSourceContext());
|
||||
$fakeFunction = new TwigFunction('block', fn ($name, $template = null) => null);
|
||||
$args = (new CallableArgumentsExtractor($fakeNode, $fakeFunction))->extractArguments($this->parseArguments(true));
|
||||
|
||||
return new BlockReferenceExpression($args->getNode('0'), \count($args) > 1 ? $args->getNode('1') : null, $line);
|
||||
return new BlockReferenceExpression($args[0], $args[1] ?? null, $line);
|
||||
case 'attribute':
|
||||
$args = $this->parseArguments();
|
||||
if (\count($args) < 2) {
|
||||
throw new SyntaxError('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext());
|
||||
}
|
||||
$fakeNode = new Node(lineno: $line);
|
||||
$fakeNode->setSourceContext($this->parser->getStream()->getSourceContext());
|
||||
$fakeFunction = new TwigFunction('attribute', fn ($variable, $attribute, $arguments = []) => null);
|
||||
$args = (new CallableArgumentsExtractor($fakeNode, $fakeFunction))->extractArguments($this->parseArguments(true));
|
||||
|
||||
return new GetAttrExpression($args->getNode('0'), $args->getNode('1'), \count($args) > 2 ? $args->getNode('2') : null, Template::ANY_CALL, $line);
|
||||
return new GetAttrExpression($args[0], $args[1], $args[2] ?? null, Template::ANY_CALL, $line);
|
||||
default:
|
||||
if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
|
||||
$arguments = new ArrayExpression([], $line);
|
||||
|
||||
@@ -2,17 +2,21 @@
|
||||
"attribute" function
|
||||
--TEMPLATE--
|
||||
{{ attribute(obj, method) }}
|
||||
{{ attribute(variable=obj, attribute=method) }}
|
||||
{{ attribute(array, item) }}
|
||||
{{ attribute(obj, "bar", ["a", "b"]) }}
|
||||
{{ attribute(obj, "bar", arguments) }}
|
||||
{{ attribute(variable=obj, attribute="bar", arguments=arguments) }}
|
||||
{{ attribute(obj, method) is defined ? 'ok' : 'ko' }}
|
||||
{{ attribute(obj, nonmethod) is defined ? 'ok' : 'ko' }}
|
||||
--DATA--
|
||||
return ['obj' => new Twig\Tests\TwigTestFoo(), 'method' => 'foo', 'array' => ['foo' => 'bar'], 'item' => 'foo', 'nonmethod' => 'xxx', 'arguments' => ['a', 'b']]
|
||||
--EXPECT--
|
||||
foo
|
||||
foo
|
||||
bar
|
||||
bar_a-b
|
||||
bar_a-b
|
||||
bar_a-b
|
||||
ok
|
||||
ko
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
--TEST--
|
||||
"attribute" function
|
||||
--TEMPLATE--
|
||||
{{ attribute(var=var, template="tpl") }}
|
||||
--DATA--
|
||||
return ['var' => null]
|
||||
--EXCEPTION--
|
||||
Twig\Error\SyntaxError: Value for argument "variable" is required for function "attribute" in "index.twig" at line 2.
|
||||
@@ -5,8 +5,9 @@
|
||||
{% block bar %}BAR{% endblock %}
|
||||
--TEMPLATE(base.twig)--
|
||||
{% block foo %}{{ block('bar') }}{% endblock %}
|
||||
{% block baz %}{{ block(name='bar') }}{% endblock %}
|
||||
{% block bar %}BAR_BASE{% endblock %}
|
||||
--DATA--
|
||||
return []
|
||||
--EXPECT--
|
||||
BARBAR
|
||||
BARBARBAR
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
{{ block('foo', included_loaded_internal) }}
|
||||
{% set output = block('foo', 'included.twig') %}
|
||||
{{ output }}
|
||||
{% set output = block(name='foo', template='included.twig') %}
|
||||
{{ output }}
|
||||
{% set output = block(template='included.twig', name='foo') %}
|
||||
{{ output }}
|
||||
{% block foo %}NOT FOO{% endblock %}
|
||||
--TEMPLATE(included.twig)--
|
||||
{% block foo %}FOO{% endblock %}
|
||||
@@ -19,4 +23,6 @@ FOO
|
||||
FOO
|
||||
FOO
|
||||
FOO
|
||||
FOO
|
||||
FOO
|
||||
NOT FOO
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
--DATA--
|
||||
return []
|
||||
--EXCEPTION--
|
||||
Twig\Error\SyntaxError: The "block" function takes one argument (the block name) in "base.twig" at line 2.
|
||||
Twig\Error\SyntaxError: Value for argument "name" is required for function "block" in "base.twig" at line 2.
|
||||
|
||||
Reference in New Issue
Block a user