mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-16 20:36:33 +00:00
feature #1215 Macros changes removal (fabpot)
This PR was merged into the master branch. Discussion ---------- Macros changes removal This PR reverts the changes made to macros in 1.14. The initial PR looked massive and I was not comfortable with the changes, but I merged it anyways. But the latest PR about fixes some bugs in the implementation -- and adding some more changes (#1213) really scares me. So, instead of continuing doing big changes, I prefer to revert everything for now, release 1.14 and give more time for these changes to mature and eventually be merged again. Commits -------74586e9Revert "merged branch hason/macros (PR #1139)"bf40fa3Revert "updated CHANGELOG"c3e05f3Revert "added an exception when a macro re-uses the same argument name twice"524e406Revert "renamed an internal variable"60b575fRevert "fixed some unit tests"
This commit is contained in:
@@ -9,9 +9,6 @@
|
||||
* fixed the filesystem loader cache when a template name exists in several namespaces
|
||||
* fixed template_from_string when the template includes or extends other ones
|
||||
* fixed a crash of the C extension on an edge case
|
||||
* added support for calling macros defined in a template without importing them first
|
||||
* added support for named arguments for macros
|
||||
* replaced a PHP fatal error with an exception when a macro does not exist
|
||||
|
||||
* 1.13.2 (2013-08-03)
|
||||
|
||||
|
||||
+3
-17
@@ -1,9 +1,6 @@
|
||||
``macro``
|
||||
=========
|
||||
|
||||
.. versionadded:: 1.14
|
||||
Support for default argument values was added in Twig 1.14.
|
||||
|
||||
Macros are comparable with functions in regular programming languages. They
|
||||
are useful to put often used HTML idioms into reusable elements to not repeat
|
||||
yourself.
|
||||
@@ -18,20 +15,10 @@ Here is a small example of a macro that renders a form element:
|
||||
|
||||
Macros differs from native PHP functions in a few ways:
|
||||
|
||||
* Arguments of a macro are always optional;
|
||||
* Default argument values are defined by using the ``default`` filter in the
|
||||
macro body;
|
||||
|
||||
* Default argument values may be defined by using the ``default`` filter in the
|
||||
macro body.
|
||||
|
||||
.. tip::
|
||||
|
||||
A macro may define default values for scalar arguments as follows:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{% macro input(name, value = "", type = "text", size = 20) %}
|
||||
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
|
||||
{% endmacro %}
|
||||
* Arguments of a macro are always optional.
|
||||
|
||||
But as with PHP functions, macros don't have access to the current template
|
||||
variables.
|
||||
@@ -59,7 +46,6 @@ The macro can then be called at will:
|
||||
|
||||
<p>{{ forms.input('username') }}</p>
|
||||
<p>{{ forms.input('password', null, 'password') }}</p>
|
||||
<p>{{ forms.input(name='username', size=40) }}</p>
|
||||
|
||||
If macros are defined and used in the same template, you can use the
|
||||
special ``_self`` variable to import them:
|
||||
|
||||
@@ -191,19 +191,12 @@ progression of integers:
|
||||
Go to the :doc:`functions<functions/index>` page to learn more about the
|
||||
built-in functions.
|
||||
|
||||
.. _named_arguments:
|
||||
|
||||
Named Arguments
|
||||
---------------
|
||||
|
||||
.. versionadded:: 1.12
|
||||
Support for named arguments was added in Twig 1.12.
|
||||
|
||||
.. versionadded:: 1.14
|
||||
Support for named arguments for macros was added in Twig 1.14.
|
||||
|
||||
Arguments for filters, functions and macros can also be passed as *named arguments*:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{% for i in range(low=1, high=10, step=2) %}
|
||||
@@ -503,10 +496,6 @@ Macros
|
||||
.. versionadded:: 1.12
|
||||
Support for default argument values was added in Twig 1.12.
|
||||
|
||||
.. versionadded:: 1.14
|
||||
Support for macro call with named arguments was added in Twig 1.14.
|
||||
Support for directly call macros defined in the same template was added in Twig 1.14.
|
||||
|
||||
Macros are comparable with functions in regular programming languages. They
|
||||
are useful to reuse often used HTML fragments to not repeat yourself.
|
||||
|
||||
@@ -528,21 +517,6 @@ Macros can be defined in any template, and need to be "imported" via the
|
||||
|
||||
<p>{{ forms.input('username') }}</p>
|
||||
|
||||
Macros defined in the same template can be directly called:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{% macro submit(name) %}
|
||||
<input type="submit" value="{{ name }}" />
|
||||
{% endmacro %}
|
||||
|
||||
<p>{{ submit('Send') }}</p>
|
||||
|
||||
.. note::
|
||||
|
||||
If the macro name matches the name of a function, it need to be "imported"
|
||||
via the :doc:`import<tags/import>`.
|
||||
|
||||
Alternatively, you can import individual macro names from a template into the
|
||||
current namespace via the :doc:`from<tags/from>` tag and optionally alias them:
|
||||
|
||||
@@ -566,14 +540,6 @@ macro call:
|
||||
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
|
||||
{% endmacro %}
|
||||
|
||||
Arguments for macro can also be passed as :ref:`named arguments<named_arguments>`:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{% import "forms.html" as forms %}
|
||||
|
||||
<p>{{ forms.input(name='username', size=40) }}</p>
|
||||
|
||||
.. _twig-expressions:
|
||||
|
||||
Expressions
|
||||
|
||||
@@ -318,21 +318,21 @@ class Twig_ExpressionParser
|
||||
|
||||
return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_Template::ANY_CALL, $line);
|
||||
default:
|
||||
$args = $this->parseArguments(true);
|
||||
if (null !== $alias = $this->parser->getImportedSymbol('macro', $name)) {
|
||||
return new Twig_Node_Expression_MacroCall($alias['node'], $alias['name'], $this->createArrayFromArguments($args), $line);
|
||||
}
|
||||
|
||||
try {
|
||||
$class = $this->getFunctionNodeClass($name, $line);
|
||||
} catch (Twig_Error_Syntax $e) {
|
||||
if (!$this->parser->hasMacro($name)) {
|
||||
throw $e;
|
||||
if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
|
||||
$arguments = new Twig_Node_Expression_Array(array(), $line);
|
||||
foreach ($this->parseArguments() as $n) {
|
||||
$arguments->addElement($n);
|
||||
}
|
||||
|
||||
return new Twig_Node_Expression_MacroCall(new Twig_Node_Expression_Name('_self', $line), $name, $this->createArrayFromArguments($args), $line);
|
||||
$node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line);
|
||||
$node->setAttribute('safe', true);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
$args = $this->parseArguments(true);
|
||||
$class = $this->getFunctionNodeClass($name, $line);
|
||||
|
||||
return new $class($name, $args, $line);
|
||||
}
|
||||
}
|
||||
@@ -354,6 +354,13 @@ class Twig_ExpressionParser
|
||||
($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
|
||||
) {
|
||||
$arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
|
||||
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$type = Twig_TemplateInterface::METHOD_CALL;
|
||||
foreach ($this->parseArguments() as $n) {
|
||||
$arguments->addElement($n);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
|
||||
}
|
||||
@@ -363,14 +370,10 @@ class Twig_ExpressionParser
|
||||
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
|
||||
$arguments = $this->createArrayFromArguments($this->parseArguments(true));
|
||||
$node = new Twig_Node_Expression_MethodCall($node, 'get'.$arg->getAttribute('value'), $arguments, $lineno);
|
||||
$node->setAttribute('safe', true);
|
||||
|
||||
return new Twig_Node_Expression_MacroCall($node, $arg->getAttribute('value'), $arguments, $lineno);
|
||||
}
|
||||
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$type = Twig_Template::METHOD_CALL;
|
||||
$arguments = $this->createArrayFromArguments($this->parseArguments());
|
||||
return $node;
|
||||
}
|
||||
} else {
|
||||
$type = Twig_Template::ARRAY_CALL;
|
||||
@@ -449,8 +452,6 @@ class Twig_ExpressionParser
|
||||
*
|
||||
* @param Boolean $namedArguments Whether to allow named arguments or not
|
||||
* @param Boolean $definition Whether we are parsing arguments for a function definition
|
||||
*
|
||||
* @return Twig_Node
|
||||
*/
|
||||
public function parseArguments($namedArguments = false, $definition = false)
|
||||
{
|
||||
@@ -482,26 +483,25 @@ class Twig_ExpressionParser
|
||||
$value = $this->parsePrimaryExpression();
|
||||
|
||||
if (!$this->checkConstantExpression($value)) {
|
||||
throw new Twig_Error_Syntax('A default value for an argument must be a constant (a boolean, a string, a number, or an array).', $token->getLine(), $this->parser->getFilename());
|
||||
throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
} else {
|
||||
$value = $this->parseExpression();
|
||||
}
|
||||
}
|
||||
|
||||
if ($definition && null === $name) {
|
||||
$name = $value->getAttribute('name');
|
||||
$value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
|
||||
if (null === $name) {
|
||||
$args[] = $value;
|
||||
} else {
|
||||
if ($definition && isset($args[$name])) {
|
||||
throw new Twig_Error_Syntax(sprintf('Arguments cannot contain the same argument name more than once ("%s" is defined twice).', $name), $token->getLine(), $this->parser->getFilename());
|
||||
if ($definition) {
|
||||
if (null === $name) {
|
||||
$name = $value->getAttribute('name');
|
||||
$value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
|
||||
$args[$name] = $value;
|
||||
} else {
|
||||
if (null === $name) {
|
||||
$args[] = $value;
|
||||
} else {
|
||||
$args[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
|
||||
@@ -597,15 +597,4 @@ class Twig_ExpressionParser
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function createArrayFromArguments(Twig_Node $arguments, $line = null)
|
||||
{
|
||||
$line = null === $line ? $arguments->getLine() : $line;
|
||||
$array = new Twig_Node_Expression_Array(array(), $line);
|
||||
foreach ($arguments as $key => $value) {
|
||||
$array->addElement($value, new Twig_Node_Expression_Constant($key, $value->getLine()));
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a macro call node.
|
||||
*
|
||||
* @author Martin Hasoň <martin.hason@gmail.com>
|
||||
*/
|
||||
class Twig_Node_Expression_MacroCall extends Twig_Node_Expression
|
||||
{
|
||||
public function __construct(Twig_Node_Expression $template, $name, Twig_Node_Expression_Array $arguments, $lineno)
|
||||
{
|
||||
parent::__construct(array('template' => $template, 'arguments' => $arguments), array('name' => $name), $lineno);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$namedNames = array();
|
||||
$namedCount = 0;
|
||||
$positionalCount = 0;
|
||||
foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) {
|
||||
$name = $pair['key']->getAttribute('value');
|
||||
if (!is_int($name)) {
|
||||
$namedCount++;
|
||||
$namedNames[$name] = 1;
|
||||
} elseif ($namedCount > 0) {
|
||||
throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for macro "%s".', $this->getAttribute('name')), $this->lineno);
|
||||
} else {
|
||||
$positionalCount++;
|
||||
}
|
||||
}
|
||||
|
||||
$compiler
|
||||
->raw('$this->callMacro(')
|
||||
->subcompile($this->getNode('template'))
|
||||
->raw(', ')->repr($this->getAttribute('name'))
|
||||
->raw(', ')->subcompile($this->getNode('arguments'))
|
||||
;
|
||||
|
||||
if ($namedCount > 0) {
|
||||
$compiler
|
||||
->raw(', ')->repr($namedNames)
|
||||
->raw(', ')->repr($namedCount)
|
||||
->raw(', ')->repr($positionalCount)
|
||||
;
|
||||
}
|
||||
|
||||
$compiler
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class Twig_Node_Macro extends Twig_Node
|
||||
{
|
||||
public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
||||
{
|
||||
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name, 'method' => 'get'.ucfirst($name)), $lineno, $tag);
|
||||
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ class Twig_Node_Macro extends Twig_Node
|
||||
{
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write(sprintf("public function %s(", $this->getAttribute('method')))
|
||||
->write(sprintf("public function get%s(", $this->getAttribute('name')))
|
||||
;
|
||||
|
||||
$count = count($this->getNode('arguments'));
|
||||
|
||||
@@ -233,43 +233,11 @@ class Twig_Node_Module extends Twig_Node
|
||||
;
|
||||
}
|
||||
|
||||
$compiler
|
||||
->outdent()
|
||||
->write(");\n\n")
|
||||
;
|
||||
|
||||
// macro information
|
||||
$compiler
|
||||
->write("\$this->macros = array(\n")
|
||||
->indent()
|
||||
;
|
||||
|
||||
foreach ($this->getNode('macros') as $name => $node) {
|
||||
$compiler
|
||||
->addIndentation()->repr($name)->raw(" => array(\n")
|
||||
->indent()
|
||||
->write("'method' => ")->repr($node->getAttribute('method'))->raw(",\n")
|
||||
->write("'arguments' => array(\n")
|
||||
->indent()
|
||||
;
|
||||
foreach ($node->getNode('arguments') as $argument => $value) {
|
||||
$compiler->addIndentation()->repr($argument)->raw (' => ')->subcompile($value)->raw(",\n");
|
||||
}
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("),\n")
|
||||
->outdent()
|
||||
->write("),\n")
|
||||
;
|
||||
}
|
||||
$compiler
|
||||
->outdent()
|
||||
->write(");\n")
|
||||
;
|
||||
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
->write("}\n\n");
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,8 +97,6 @@ class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
|
||||
} else {
|
||||
$this->setSafe($node, array());
|
||||
}
|
||||
} elseif ($node instanceof Twig_Node_Expression_MacroCall) {
|
||||
$this->setSafe($node, array('all'));
|
||||
} elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) {
|
||||
$name = $node->getNode('node')->getAttribute('name');
|
||||
// attributes on template instances are safe
|
||||
|
||||
@@ -24,7 +24,6 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
||||
protected $env;
|
||||
protected $blocks;
|
||||
protected $traits;
|
||||
protected $macros;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -36,7 +35,6 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
||||
$this->env = $env;
|
||||
$this->blocks = array();
|
||||
$this->traits = array();
|
||||
$this->macros = array();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,66 +445,6 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls macro in a template.
|
||||
*
|
||||
* @param Twig_Template $template The template
|
||||
* @param string $macro The name of macro
|
||||
* @param array $arguments The arguments of macro
|
||||
* @param array $namedNames An array of names of arguments as keys
|
||||
* @param integer $namedCount The count of named arguments
|
||||
* @param integer $positionalCount The count of positional arguments
|
||||
*
|
||||
* @return string The content of a macro
|
||||
*
|
||||
* @throws Twig_Error_Runtime if the macro is not defined
|
||||
* @throws Twig_Error_Runtime if the argument is defined twice
|
||||
* @throws Twig_Error_Runtime if the argument is unknown
|
||||
*/
|
||||
protected function callMacro(Twig_Template $template, $macro, array $arguments, array $namedNames = array(), $namedCount = 0, $positionalCount = -1)
|
||||
{
|
||||
if (!isset($template->macros[$macro]['reflection'])) {
|
||||
if (!isset($template->macros[$macro])) {
|
||||
throw new Twig_Error_Runtime(sprintf('Macro "%s" is not defined in the template "%s".', $macro, $template->getTemplateName()));
|
||||
}
|
||||
|
||||
$template->macros[$macro]['reflection'] = new ReflectionMethod($template, $template->macros[$macro]['method']);
|
||||
}
|
||||
|
||||
if ($namedCount < 1) {
|
||||
return $template->macros[$macro]['reflection']->invokeArgs($template, $arguments);
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$args = array();
|
||||
foreach ($template->macros[$macro]['arguments'] as $name => $value) {
|
||||
if (isset($namedNames[$name])) {
|
||||
if ($i < $positionalCount) {
|
||||
throw new Twig_Error_Runtime(sprintf('Argument "%s" is defined twice for macro "%s" defined in the template "%s".', $name, $macro, $template->getTemplateName()));
|
||||
}
|
||||
|
||||
$args[] = $arguments[$name];
|
||||
if (--$namedCount < 1) {
|
||||
break;
|
||||
}
|
||||
} elseif ($i < $positionalCount) {
|
||||
$args[] = $arguments[$i];
|
||||
} else {
|
||||
$args[] = $value;
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
if ($namedCount > 0) {
|
||||
$parameters = array_keys(array_diff_key($namedNames, $template->macros[$macro]['arguments']));
|
||||
|
||||
throw new Twig_Error_Runtime(sprintf('Unknown argument%s "%s" for macro "%s" defined in the template "%s".', count($parameters) > 1 ? 's' : '' , implode('", "', $parameters), $macro, $template->getTemplateName()));
|
||||
}
|
||||
|
||||
return $template->macros[$macro]['reflection']->invokeArgs($template, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only useful when testing Twig. Do not use it.
|
||||
*/
|
||||
|
||||
@@ -56,7 +56,7 @@ class Twig_TokenParser_From extends Twig_TokenParser
|
||||
$node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag());
|
||||
|
||||
foreach ($targets as $name => $alias) {
|
||||
$this->parser->addImportedSymbol('macro', $alias, $name, $node->getNode('var'));
|
||||
$this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
|
||||
}
|
||||
|
||||
return $node;
|
||||
|
||||
@@ -226,6 +226,17 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
||||
$parser->parse($env->tokenize('{{ foo.bar(name="Foo") }}', 'index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Twig_Error_Syntax
|
||||
*/
|
||||
public function testMacroCallDoesNotSupportNamedArguments()
|
||||
{
|
||||
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
||||
$parser = new Twig_Parser($env);
|
||||
|
||||
$parser->parse($env->tokenize('{% from _self import foo %}{% macro foo() %}{% endmacro %}{{ foo(name="Foo") }}', 'index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Twig_Error_Syntax
|
||||
* @expectedExceptionMessage An argument must be a name. Unexpected token "string" of value "a" ("name" expected) in "index" at line 1
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
--TEST--
|
||||
Exception for unknown macro
|
||||
--TEMPLATE--
|
||||
{% import _self as macros %}
|
||||
{{ macros.foo() }}
|
||||
--DATA--
|
||||
return array()
|
||||
--EXCEPTION--
|
||||
Twig_Error_Runtime: Macro "foo" is not defined in the template "index.twig" in "index.twig" at line 3.
|
||||
@@ -1,11 +0,0 @@
|
||||
--TEST--
|
||||
Exception for unknown macro in different template
|
||||
--TEMPLATE--
|
||||
{% import foo_template as macros %}
|
||||
{{ macros.foo() }}
|
||||
--TEMPLATE(foo.twig)--
|
||||
foo
|
||||
--DATA--
|
||||
return array('foo_template' => 'foo.twig')
|
||||
--EXCEPTION--
|
||||
Twig_Error_Runtime: Macro "foo" is not defined in the template "foo.twig" in "index.twig" at line 3.
|
||||
@@ -1,20 +0,0 @@
|
||||
--TEST--
|
||||
Auto importing macros in the same file
|
||||
--TEMPLATE--
|
||||
{% macro test(a) %}
|
||||
{{ a }}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro foo(a) %}
|
||||
foo: {{ test(a) }}
|
||||
{%- endmacro %}
|
||||
|
||||
{{ test('foo') }}
|
||||
{{ foo('foo') }}
|
||||
{{ test(a = 'bar') }}
|
||||
--DATA--
|
||||
return array();
|
||||
--EXPECT--
|
||||
foo
|
||||
foo: foo
|
||||
bar
|
||||
@@ -1,31 +0,0 @@
|
||||
--TEST--
|
||||
macro with named arguments
|
||||
--TEMPLATE--
|
||||
{% import _self as test %}
|
||||
{% from _self import test %}
|
||||
|
||||
{% macro test(a, b = 'bar') -%}
|
||||
{{ a }}{{ b }}
|
||||
{%- endmacro %}
|
||||
|
||||
{{ test(b = 'bar', a = 'foo') }}
|
||||
{{ test(b = '2', a = 'foo') }}
|
||||
{{ test('bar', b = 'foo') }}
|
||||
{{ test.test(b = 1) }}
|
||||
{{ test.test(b = 'foo') }}
|
||||
{{ test.test(2, b = 'foo') }}
|
||||
{{ test.test(3, b = 'foobar') }}
|
||||
{{ test.test(a = 1) }}
|
||||
{{ test.test(a = 2) }}
|
||||
--DATA--
|
||||
return array();
|
||||
--EXPECT--
|
||||
foobar
|
||||
foo2
|
||||
barfoo
|
||||
1
|
||||
foo
|
||||
2foo
|
||||
3foobar
|
||||
1bar
|
||||
2bar
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Twig_Tests_Node_Expression_MacroCallTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException Twig_Error_Syntax
|
||||
* @expectedExceptionMessage Positional arguments cannot be used after named arguments for macro "foo".
|
||||
*/
|
||||
public function testGetArgumentsWhenPositionalArgumentsAfterNamedArguments()
|
||||
{
|
||||
$arguments = new Twig_Node_Expression_Array(array(new Twig_Node_Expression_Constant('named', -1), $this->getMock('Twig_Node'), new Twig_Node_Expression_Constant(0, -1), $this->getMock('Twig_Node')), -1);
|
||||
$node = new Twig_Node_Expression_MacroCall($this->getMock('Twig_Node_Expression'), 'foo', $arguments, -1);
|
||||
$node->compile($this->getMock('Twig_Compiler', null, array(), '', false));
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ class Twig_Tests_Node_MacroTest extends Twig_Test_NodeTestCase
|
||||
return array(
|
||||
array($node, <<<EOF
|
||||
// line 1
|
||||
public function getFoo(\$_foo = null, \$_bar = "Foo")
|
||||
public function getfoo(\$_foo = null, \$_bar = "Foo")
|
||||
{
|
||||
\$context = \$this->env->mergeGlobals(array(
|
||||
"foo" => \$_foo,
|
||||
|
||||
@@ -75,9 +75,6 @@ class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c1863
|
||||
|
||||
\$this->blocks = array(
|
||||
);
|
||||
|
||||
\$this->macros = array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function doDisplay(array \$context, array \$blocks = array())
|
||||
@@ -93,7 +90,7 @@ class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c1863
|
||||
|
||||
public function getDebugInfo()
|
||||
{
|
||||
return array ( 22 => 1,);
|
||||
return array ( 19 => 1,);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
@@ -119,9 +116,6 @@ class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c1863
|
||||
|
||||
\$this->blocks = array(
|
||||
);
|
||||
|
||||
\$this->macros = array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function doGetParent(array \$context)
|
||||
@@ -148,7 +142,7 @@ class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c1863
|
||||
|
||||
public function getDebugInfo()
|
||||
{
|
||||
return array ( 27 => 1,);
|
||||
return array ( 24 => 1,);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
@@ -73,9 +73,6 @@ class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c1863
|
||||
|
||||
\$this->blocks = array(
|
||||
);
|
||||
|
||||
\$this->macros = array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function doDisplay(array \$context, array \$blocks = array())
|
||||
@@ -101,7 +98,7 @@ class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c1863
|
||||
|
||||
public function getDebugInfo()
|
||||
{
|
||||
return array ( 23 => 1,);
|
||||
return array ( 20 => 1,);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
@@ -131,9 +128,6 @@ class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c1863
|
||||
|
||||
\$this->blocks = array(
|
||||
);
|
||||
|
||||
\$this->macros = array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function doGetParent(array \$context)
|
||||
|
||||
@@ -363,55 +363,6 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Twig_Error_Runtime
|
||||
* @expectedExceptionMessage Macro "foo" is not defined in the template "my/template".
|
||||
*/
|
||||
public function testCallUnknownMacro()
|
||||
{
|
||||
$template = new Twig_TemplateTest($this->getMock('Twig_Environment'));
|
||||
$template->callMacro(new Twig_Tests_TemplateWithMacros('my/template'), 'foo', array());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Twig_Error_Runtime
|
||||
* @expectedExceptionMessage Argument "format" is defined twice for macro "date" defined in the template "my/template".
|
||||
*/
|
||||
public function testCallMacroWhenArgumentIsDefinedTwice()
|
||||
{
|
||||
$template = new Twig_TemplateTest($this->getMock('Twig_Environment'));
|
||||
$template->callMacro(new Twig_Tests_TemplateWithMacros('my/template', array('date' => array(
|
||||
'method' => 'getDate',
|
||||
'arguments' => array('format' => null, 'template' => null)
|
||||
))), 'date', array('d', 'format' => 'H'), array('format' => 1), 1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Twig_Error_Runtime
|
||||
* @expectedExceptionMessage Unknown argument "unknown" for macro "date" defined in the template "my/template".
|
||||
*/
|
||||
public function testCallMacroWithWrongNamedArgumentName()
|
||||
{
|
||||
$template = new Twig_TemplateTest($this->getMock('Twig_Environment'));
|
||||
$template->callMacro(new Twig_Tests_TemplateWithMacros('my/template', array('date' => array(
|
||||
'method' => 'getDate',
|
||||
'arguments' => array('foo' => 1, 'bar' => 2)
|
||||
))), 'date', array('foo' => 2), array('foo' => 1, 'unknown' => 1), 2, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Twig_Error_Runtime
|
||||
* @expectedExceptionMessage Unknown arguments "unknown1", "unknown2" for macro "date" defined in the template "my/template".
|
||||
*/
|
||||
public function testCallMacroWithWrongNamedArgumentNames()
|
||||
{
|
||||
$template = new Twig_TemplateTest($this->getMock('Twig_Environment'));
|
||||
$template->callMacro(new Twig_Tests_TemplateWithMacros('my/template', array('date' => array(
|
||||
'method' => 'getDate',
|
||||
'arguments' => array()
|
||||
))), 'date', array(), array('unknown1' => 1, 'unknown2' => 2), 2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
class Twig_TemplateTest extends Twig_Template
|
||||
@@ -470,35 +421,6 @@ class Twig_TemplateTest extends Twig_Template
|
||||
return parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
|
||||
}
|
||||
}
|
||||
|
||||
public function callMacro(Twig_Template $template, $macro, array $arguments, array $namedNames = array(), $namedCount = 0, $positionalCount = -1)
|
||||
{
|
||||
return parent::callMacro($template, $macro, $arguments, $namedNames, $namedCount, $positionalCount);
|
||||
}
|
||||
}
|
||||
|
||||
class Twig_Tests_TemplateWithMacros extends Twig_Template
|
||||
{
|
||||
protected $name;
|
||||
|
||||
public function __construct($name, array $macros = array())
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->macros = $macros;
|
||||
}
|
||||
|
||||
public function getTemplateName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getDate()
|
||||
{
|
||||
}
|
||||
|
||||
protected function doDisplay(array $context, array $blocks = array())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class Twig_TemplateArrayAccessObject implements ArrayAccess
|
||||
|
||||
Reference in New Issue
Block a user