} elseif ('|' == $token->getValue()) {
$node = $this->parseFilterExpression($node);
} elseif ($firstPass && $node instanceof Twig_Node_Expression_Name && '(' == $token->getValue()) {
- $node = new Twig_Node_Expression_Function($node, $this->parseArguments(), $node->getLine());
+ if (null !== $alias = $this->parser->getImportedFunction($node->getAttribute('name'))) {
+ $node = new Twig_Node_Expression_GetAttr($alias['node'], new Twig_Node_Expression_Constant($alias['name'], $node->getLine()), $this->parseArguments(), $node->getLine(), Twig_Node_Expression_GetAttr::TYPE_METHOD);
+ } else {
+ $node = new Twig_Node_Expression_Function($node, $this->parseArguments(), $node->getLine());
+ }
} else {
break;
}
*/
class Twig_Node_From extends Twig_Node_Import
{
- public function __construct(Twig_Node_Expression $expr, array $imports, $lineno, $tag = null)
+ public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
{
- parent::__construct($expr, new Twig_Node_Expression_AssignName('_imported_'.rand(10000, 99999), $lineno), $lineno, $tag);
-
- $this->setAttribute('imports', $imports);
- }
-
- /**
- * Compiles the node to PHP.
- *
- * @param Twig_Compiler A Twig_Compiler instance
- */
- public function compile($compiler)
- {
- parent::compile($compiler);
-
- foreach ($this->getAttribute('imports') as $name => $alias) {
- $compiler
- ->write('$context[')
- ->repr('fn_'.$alias)
- ->raw('] = new Twig_Function(')
- ->subcompile($this->getNode('var'))
- ->raw(', ')
- ->repr($name)
- ->raw(");\n")
- ;
- }
+ parent::__construct($expr, new Twig_Node_Expression_AssignLocalName(null, $lineno), $lineno, $tag);
}
}
*/
class Twig_Node_Import extends Twig_Node
{
- public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression_AssignName $var, $lineno, $tag = null)
+ public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null)
{
parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag);
}
protected $macros;
protected $env;
protected $reservedMacroNames;
+ protected $importedFunctions;
public function __construct(Twig_Environment $env)
{
$this->blocks = array();
$this->macros = array();
$this->blockStack = array();
+ $this->importedFunctions = array(array());
try {
$body = $this->subparse(null);
$this->macros[$name] = $node;
}
+ public function addImportedFunction($alias, $name, Twig_Node_Expression $node)
+ {
+ $this->importedFunctions[0][$alias] = array(
+ 'name' => $name,
+ 'node' => $node,
+ );
+ }
+
+ public function getImportedFunction($alias)
+ {
+ if (!isset($this->importedFunctions[0][$alias])) {
+ return null;
+ }
+ return $this->importedFunctions[0][$alias];
+ }
+
+ public function pushLocalScope()
+ {
+ array_unshift($this->importedFunctions, array());
+ }
+
+ public function popLocalScope()
+ {
+ array_shift($this->importedFunctions);
+ }
+
public function getExpressionParser()
{
return $this->expressionParser;
if ($this->parser->hasBlock($name)) {
throw new Twig_Error_Syntax("The block '$name' has already been defined", $lineno);
}
+ $this->parser->pushLocalScope();
$this->parser->pushBlockStack($name);
if ($stream->test(Twig_Token::BLOCK_END_TYPE)) {
$block = new Twig_Node_Block($name, $body, $lineno);
$this->parser->setBlock($name, $block);
$this->parser->popBlockStack();
+ $this->parser->popLocalScope();
return new Twig_Node_BlockReference($name, $lineno, $this->getTag());
}
$stream->expect(Twig_Token::BLOCK_END_TYPE);
- return new Twig_Node_From($macro, $targets, $token->getLine(), $this->getTag());
+ $node = new Twig_Node_From($macro, $token->getLine(), $this->getTag());
+
+ foreach($targets as $name => $alias)
+ {
+ $this->parser->addImportedFunction($alias, $name, $node->getNode('var'));
+ }
+
+ return $node;
}
/**
$arguments = $this->parser->getExpressionParser()->parseArguments();
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+ $this->parser->pushLocalScope();
$body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
+ $this->parser->popLocalScope();
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
$this->parser->setMacro($name, new Twig_Node_Macro($name, $body, $arguments, $lineno, $this->getTag()));