mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-16 12:26:30 +00:00
Refactored parsing of macros
This commit is contained in:
@@ -318,16 +318,10 @@ 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_TemplateInterface::ANY_CALL, $line);
|
||||
default:
|
||||
if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
|
||||
$arguments = new Twig_Node_Expression_Array(array(), $line);
|
||||
foreach ($this->parseArguments() as $n) {
|
||||
$arguments->addElement($n);
|
||||
}
|
||||
if (null !== $alias = $this->parser->getImportedSymbol('macro', $name)) {
|
||||
$arguments = $this->createArrayFromArguments($this->parseArguments());
|
||||
|
||||
$node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line);
|
||||
$node->setAttribute('safe', true);
|
||||
|
||||
return $node;
|
||||
return new Twig_Node_Expression_MacroCall($alias['node'], $alias['name'], $arguments, $line);
|
||||
}
|
||||
|
||||
$args = $this->parseArguments(true);
|
||||
@@ -354,13 +348,6 @@ 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());
|
||||
}
|
||||
@@ -370,10 +357,14 @@ 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());
|
||||
}
|
||||
|
||||
$node = new Twig_Node_Expression_MethodCall($node, 'get'.$arg->getAttribute('value'), $arguments, $lineno);
|
||||
$node->setAttribute('safe', true);
|
||||
$arguments = $this->createArrayFromArguments($this->parseArguments());
|
||||
|
||||
return $node;
|
||||
return new Twig_Node_Expression_MacroCall($node, $arg->getAttribute('value'), $arguments, $lineno);
|
||||
}
|
||||
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$type = Twig_TemplateInterface::METHOD_CALL;
|
||||
$arguments = $this->createArrayFromArguments($this->parseArguments());
|
||||
}
|
||||
} else {
|
||||
$type = Twig_TemplateInterface::ARRAY_CALL;
|
||||
@@ -452,6 +443,8 @@ 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)
|
||||
{
|
||||
@@ -490,18 +483,15 @@ class Twig_ExpressionParser
|
||||
}
|
||||
}
|
||||
|
||||
if ($definition) {
|
||||
if (null === $name) {
|
||||
$name = $value->getAttribute('name');
|
||||
$value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
$args[$name] = $value;
|
||||
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 (null === $name) {
|
||||
$args[] = $value;
|
||||
} else {
|
||||
$args[$name] = $value;
|
||||
}
|
||||
$args[$name] = $value;
|
||||
}
|
||||
}
|
||||
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
|
||||
@@ -597,4 +587,15 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?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)
|
||||
{
|
||||
$compiler
|
||||
->raw('$this->callMacro(')
|
||||
->subcompile($this->getNode('template'))
|
||||
->raw(', ')
|
||||
->repr($this->getAttribute('name'))
|
||||
->raw(', ')
|
||||
->subcompile($this->getNode('arguments'))
|
||||
->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), $lineno, $tag);
|
||||
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name, 'method' => 'get'.ucfirst($name)), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ class Twig_Node_Macro extends Twig_Node
|
||||
{
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write(sprintf("public function get%s(", $this->getAttribute('name')))
|
||||
->write(sprintf("public function %s(", $this->getAttribute('method')))
|
||||
;
|
||||
|
||||
$count = count($this->getNode('arguments'));
|
||||
|
||||
@@ -235,9 +235,32 @@ class Twig_Node_Module extends Twig_Node
|
||||
|
||||
$compiler
|
||||
->outdent()
|
||||
->write(");\n")
|
||||
->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")
|
||||
->outdent()
|
||||
->write("),\n")
|
||||
;
|
||||
}
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("}\n\n");
|
||||
->write(");\n")
|
||||
;
|
||||
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ 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,6 +24,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
||||
protected $env;
|
||||
protected $blocks;
|
||||
protected $traits;
|
||||
protected $macros;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -35,6 +36,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
||||
$this->env = $env;
|
||||
$this->blocks = array();
|
||||
$this->traits = array();
|
||||
$this->macros = array();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -445,6 +447,24 @@ 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
|
||||
*
|
||||
* @return string The content of a macro
|
||||
*/
|
||||
protected function callMacro(Twig_Template $template, $macro, array $arguments)
|
||||
{
|
||||
if (!isset($template->macros[$macro]['reflection'])) {
|
||||
$template->macros[$macro]['reflection'] = new ReflectionMethod($template, $template->macros[$macro]['method']);
|
||||
}
|
||||
|
||||
return $template->macros[$macro]['reflection']->invokeArgs($template, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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('function', $alias, 'get'.$name, $node->getNode('var'));
|
||||
$this->parser->addImportedSymbol('macro', $alias, $name, $node->getNode('var'));
|
||||
}
|
||||
|
||||
return $node;
|
||||
|
||||
@@ -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,6 +75,9 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||
|
||||
\$this->blocks = array(
|
||||
);
|
||||
|
||||
\$this->macros = array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function doDisplay(array \$context, array \$blocks = array())
|
||||
@@ -90,7 +93,7 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||
|
||||
public function getDebugInfo()
|
||||
{
|
||||
return array ( 19 => 1,);
|
||||
return array ( 22 => 1,);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
@@ -116,6 +119,9 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||
|
||||
\$this->blocks = array(
|
||||
);
|
||||
|
||||
\$this->macros = array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function doGetParent(array \$context)
|
||||
@@ -142,7 +148,7 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||
|
||||
public function getDebugInfo()
|
||||
{
|
||||
return array ( 24 => 1,);
|
||||
return array ( 27 => 1,);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
@@ -73,6 +73,9 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||
|
||||
\$this->blocks = array(
|
||||
);
|
||||
|
||||
\$this->macros = array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function doDisplay(array \$context, array \$blocks = array())
|
||||
@@ -98,7 +101,7 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||
|
||||
public function getDebugInfo()
|
||||
{
|
||||
return array ( 20 => 1,);
|
||||
return array ( 23 => 1,);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
@@ -128,6 +131,9 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
|
||||
|
||||
\$this->blocks = array(
|
||||
);
|
||||
|
||||
\$this->macros = array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function doGetParent(array \$context)
|
||||
|
||||
Reference in New Issue
Block a user