diff options
| author | Benjamin Southall <applemansigloo@gmail.com> | 2019-02-26 10:11:12 +1000 |
|---|---|---|
| committer | Benjamin Southall <applemansigloo@gmail.com> | 2019-02-26 10:11:12 +1000 |
| commit | f79395851b044689567e0e6c9504acbcaa742782 (patch) | |
| tree | ee539aee9ffa90e8accd6f130b30a8ebed7a232e /inc/lib/Twig/Node | |
| parent | 28f32baf0125ca5085266e73dc5071e5814d8e3b (diff) | |
Twig update to latest Twig 1.x legacy as per vichan
Diffstat (limited to 'inc/lib/Twig/Node')
78 files changed, 1125 insertions, 522 deletions
diff --git a/inc/lib/Twig/Node/AutoEscape.php b/inc/lib/Twig/Node/AutoEscape.php index 8f190e0b..17e4e381 100644 --- a/inc/lib/Twig/Node/AutoEscape.php +++ b/inc/lib/Twig/Node/AutoEscape.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -27,13 +27,10 @@ class Twig_Node_AutoEscape extends Twig_Node parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler->subcompile($this->getNode('body')); } } + +class_alias('Twig_Node_AutoEscape', 'Twig\Node\AutoEscapeNode', false); diff --git a/inc/lib/Twig/Node/Block.php b/inc/lib/Twig/Node/Block.php index 50eb67ed..91752ad2 100644 --- a/inc/lib/Twig/Node/Block.php +++ b/inc/lib/Twig/Node/Block.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -22,11 +22,6 @@ class Twig_Node_Block extends Twig_Node parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -42,3 +37,5 @@ class Twig_Node_Block extends Twig_Node ; } } + +class_alias('Twig_Node_Block', 'Twig\Node\BlockNode', false); diff --git a/inc/lib/Twig/Node/BlockReference.php b/inc/lib/Twig/Node/BlockReference.php index 013e369e..92a9f398 100644 --- a/inc/lib/Twig/Node/BlockReference.php +++ b/inc/lib/Twig/Node/BlockReference.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -22,11 +22,6 @@ class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInter parent::__construct(array(), array('name' => $name), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -35,3 +30,5 @@ class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInter ; } } + +class_alias('Twig_Node_BlockReference', 'Twig\Node\BlockReferenceNode', false); diff --git a/inc/lib/Twig/Node/Body.php b/inc/lib/Twig/Node/Body.php index 3ffb1342..07dfef8b 100644 --- a/inc/lib/Twig/Node/Body.php +++ b/inc/lib/Twig/Node/Body.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,3 +17,5 @@ class Twig_Node_Body extends Twig_Node { } + +class_alias('Twig_Node_Body', 'Twig\Node\BodyNode', false); diff --git a/inc/lib/Twig/Node/CheckSecurity.php b/inc/lib/Twig/Node/CheckSecurity.php new file mode 100644 index 00000000..7258acb6 --- /dev/null +++ b/inc/lib/Twig/Node/CheckSecurity.php @@ -0,0 +1,80 @@ +<?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. + */ + +/** + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_CheckSecurity extends Twig_Node +{ + protected $usedFilters; + protected $usedTags; + protected $usedFunctions; + + public function __construct(array $usedFilters, array $usedTags, array $usedFunctions) + { + $this->usedFilters = $usedFilters; + $this->usedTags = $usedTags; + $this->usedFunctions = $usedFunctions; + + parent::__construct(); + } + + public function compile(Twig_Compiler $compiler) + { + $tags = $filters = $functions = array(); + foreach (array('tags', 'filters', 'functions') as $type) { + foreach ($this->{'used'.ucfirst($type)} as $name => $node) { + if ($node instanceof Twig_Node) { + ${$type}[$name] = $node->getTemplateLine(); + } else { + ${$type}[$node] = null; + } + } + } + + $compiler + ->write('$tags = ')->repr(array_filter($tags))->raw(";\n") + ->write('$filters = ')->repr(array_filter($filters))->raw(";\n") + ->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n") + ->write("try {\n") + ->indent() + ->write("\$this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity(\n") + ->indent() + ->write(!$tags ? "array(),\n" : "array('".implode("', '", array_keys($tags))."'),\n") + ->write(!$filters ? "array(),\n" : "array('".implode("', '", array_keys($filters))."'),\n") + ->write(!$functions ? "array()\n" : "array('".implode("', '", array_keys($functions))."')\n") + ->outdent() + ->write(");\n") + ->outdent() + ->write("} catch (Twig_Sandbox_SecurityError \$e) {\n") + ->indent() + ->write("\$e->setSourceContext(\$this->getSourceContext());\n\n") + ->write("if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n") + ->indent() + ->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n") + ->outdent() + ->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n") + ->indent() + ->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n") + ->outdent() + ->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n") + ->indent() + ->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n") + ->outdent() + ->write("}\n\n") + ->write("throw \$e;\n") + ->outdent() + ->write("}\n\n") + ; + } +} + +class_alias('Twig_Node_CheckSecurity', 'Twig\Node\CheckSecurityNode', false); diff --git a/inc/lib/Twig/Node/Do.php b/inc/lib/Twig/Node/Do.php index c528066b..cdd7e77a 100644 --- a/inc/lib/Twig/Node/Do.php +++ b/inc/lib/Twig/Node/Do.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,11 +21,6 @@ class Twig_Node_Do extends Twig_Node parent::__construct(array('expr' => $expr), array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -36,3 +31,5 @@ class Twig_Node_Do extends Twig_Node ; } } + +class_alias('Twig_Node_Do', 'Twig\Node\DoNode', false); diff --git a/inc/lib/Twig/Node/Embed.php b/inc/lib/Twig/Node/Embed.php index 4c9456dc..3785d3a9 100644 --- a/inc/lib/Twig/Node/Embed.php +++ b/inc/lib/Twig/Node/Embed.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2012 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,22 +17,30 @@ class Twig_Node_Embed extends Twig_Node_Include { // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module) - public function __construct($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) + public function __construct($name, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) { parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); - $this->setAttribute('filename', $filename); + $this->setAttribute('name', $name); + // to be removed in 2.0, used name instead + $this->setAttribute('filename', $name); $this->setAttribute('index', $index); } protected function addGetTemplate(Twig_Compiler $compiler) { $compiler - ->write("\$this->env->loadTemplate(") - ->string($this->getAttribute('filename')) + ->write('$this->loadTemplate(') + ->string($this->getAttribute('name')) + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) ->raw(', ') ->string($this->getAttribute('index')) - ->raw(")") + ->raw(')') ; } } + +class_alias('Twig_Node_Embed', 'Twig\Node\EmbedNode', false); diff --git a/inc/lib/Twig/Node/Expression.php b/inc/lib/Twig/Node/Expression.php index a7382e7d..a99c4e63 100644 --- a/inc/lib/Twig/Node/Expression.php +++ b/inc/lib/Twig/Node/Expression.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,3 +18,5 @@ abstract class Twig_Node_Expression extends Twig_Node { } + +class_alias('Twig_Node_Expression', 'Twig\Node\Expression\AbstractExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Array.php b/inc/lib/Twig/Node/Expression/Array.php index 1da785fe..0e77bb08 100644 --- a/inc/lib/Twig/Node/Expression/Array.php +++ b/inc/lib/Twig/Node/Expression/Array.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -43,7 +43,7 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression foreach ($this->getKeyValuePairs() as $pair) { // we compare the string representation of the keys // to avoid comparing the line numbers which are not relevant here. - if ((string) $key == (string) $pair['key']) { + if ((string) $key === (string) $pair['key']) { return true; } } @@ -54,17 +54,12 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null) { if (null === $key) { - $key = new Twig_Node_Expression_Constant(++$this->index, $value->getLine()); + $key = new Twig_Node_Expression_Constant(++$this->index, $value->getTemplateLine()); } array_push($this->nodes, $key, $value); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler->raw('array('); @@ -84,3 +79,5 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression $compiler->raw(')'); } } + +class_alias('Twig_Node_Expression_Array', 'Twig\Node\Expression\ArrayExpression', false); diff --git a/inc/lib/Twig/Node/Expression/AssignName.php b/inc/lib/Twig/Node/Expression/AssignName.php index 2ddea78c..2e6b4c7c 100644 --- a/inc/lib/Twig/Node/Expression/AssignName.php +++ b/inc/lib/Twig/Node/Expression/AssignName.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,11 +12,6 @@ class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name { - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -26,3 +21,5 @@ class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name ; } } + +class_alias('Twig_Node_Expression_AssignName', 'Twig\Node\Expression\AssignNameExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Binary.php b/inc/lib/Twig/Node/Expression/Binary.php index 9dd5de2c..2b545d98 100644 --- a/inc/lib/Twig/Node/Expression/Binary.php +++ b/inc/lib/Twig/Node/Expression/Binary.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,11 +16,6 @@ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -38,3 +33,5 @@ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression abstract public function operator(Twig_Compiler $compiler); } + +class_alias('Twig_Node_Expression_Binary', 'Twig\Node\Expression\Binary\AbstractBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Add.php b/inc/lib/Twig/Node/Expression/Binary/Add.php index 0ef8e117..5a09d836 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Add.php +++ b/inc/lib/Twig/Node/Expression/Binary/Add.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary return $compiler->raw('+'); } } + +class_alias('Twig_Node_Expression_Binary_Add', 'Twig\Node\Expression\Binary\AddBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/And.php b/inc/lib/Twig/Node/Expression/Binary/And.php index d5752ebb..9ffddce6 100644 --- a/inc/lib/Twig/Node/Expression/Binary/And.php +++ b/inc/lib/Twig/Node/Expression/Binary/And.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary return $compiler->raw('&&'); } } + +class_alias('Twig_Node_Expression_Binary_And', 'Twig\Node\Expression\Binary\AndBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/BitwiseAnd.php b/inc/lib/Twig/Node/Expression/Binary/BitwiseAnd.php index 9a46d845..e46e9ebf 100644 --- a/inc/lib/Twig/Node/Expression/Binary/BitwiseAnd.php +++ b/inc/lib/Twig/Node/Expression/Binary/BitwiseAnd.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary return $compiler->raw('&'); } } + +class_alias('Twig_Node_Expression_Binary_BitwiseAnd', 'Twig\Node\Expression\Binary\BitwiseAndBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/BitwiseOr.php b/inc/lib/Twig/Node/Expression/Binary/BitwiseOr.php index 058a20bf..5d7f1b7c 100644 --- a/inc/lib/Twig/Node/Expression/Binary/BitwiseOr.php +++ b/inc/lib/Twig/Node/Expression/Binary/BitwiseOr.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary return $compiler->raw('|'); } } + +class_alias('Twig_Node_Expression_Binary_BitwiseOr', 'Twig\Node\Expression\Binary\BitwiseOrBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/BitwiseXor.php b/inc/lib/Twig/Node/Expression/Binary/BitwiseXor.php index f4da73d4..82edf516 100644 --- a/inc/lib/Twig/Node/Expression/Binary/BitwiseXor.php +++ b/inc/lib/Twig/Node/Expression/Binary/BitwiseXor.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary return $compiler->raw('^'); } } + +class_alias('Twig_Node_Expression_Binary_BitwiseXor', 'Twig\Node\Expression\Binary\BitwiseXorBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Concat.php b/inc/lib/Twig/Node/Expression/Binary/Concat.php index f9a64627..91abca60 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Concat.php +++ b/inc/lib/Twig/Node/Expression/Binary/Concat.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary return $compiler->raw('.'); } } + +class_alias('Twig_Node_Expression_Binary_Concat', 'Twig\Node\Expression\Binary\ConcatBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Div.php b/inc/lib/Twig/Node/Expression/Binary/Div.php index e0797a61..38ffa30c 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Div.php +++ b/inc/lib/Twig/Node/Expression/Binary/Div.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary return $compiler->raw('/'); } } + +class_alias('Twig_Node_Expression_Binary_Div', 'Twig\Node\Expression\Binary\DivBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/EndsWith.php b/inc/lib/Twig/Node/Expression/Binary/EndsWith.php new file mode 100644 index 00000000..85c52937 --- /dev/null +++ b/inc/lib/Twig/Node/Expression/Binary/EndsWith.php @@ -0,0 +1,32 @@ +<?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_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary +{ + public function compile(Twig_Compiler $compiler) + { + $left = $compiler->getVarName(); + $right = $compiler->getVarName(); + $compiler + ->raw(sprintf('(is_string($%s = ', $left)) + ->subcompile($this->getNode('left')) + ->raw(sprintf(') && is_string($%s = ', $right)) + ->subcompile($this->getNode('right')) + ->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right)) + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw(''); + } +} + +class_alias('Twig_Node_Expression_Binary_EndsWith', 'Twig\Node\Expression\Binary\EndsWithBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Equal.php b/inc/lib/Twig/Node/Expression/Binary/Equal.php index 7b1236d0..a6a6946b 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Equal.php +++ b/inc/lib/Twig/Node/Expression/Binary/Equal.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary return $compiler->raw('=='); } } + +class_alias('Twig_Node_Expression_Binary_Equal', 'Twig\Node\Expression\Binary\EqualBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/FloorDiv.php b/inc/lib/Twig/Node/Expression/Binary/FloorDiv.php index 7fbd0556..7393bcb8 100644 --- a/inc/lib/Twig/Node/Expression/Binary/FloorDiv.php +++ b/inc/lib/Twig/Node/Expression/Binary/FloorDiv.php @@ -3,23 +3,18 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary { - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { - $compiler->raw('intval(floor('); + $compiler->raw('(int) floor('); parent::compile($compiler); - $compiler->raw('))'); + $compiler->raw(')'); } public function operator(Twig_Compiler $compiler) @@ -27,3 +22,5 @@ class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary return $compiler->raw('/'); } } + +class_alias('Twig_Node_Expression_Binary_FloorDiv', 'Twig\Node\Expression\Binary\FloorDivBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Greater.php b/inc/lib/Twig/Node/Expression/Binary/Greater.php index a110bd92..832f9797 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Greater.php +++ b/inc/lib/Twig/Node/Expression/Binary/Greater.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary return $compiler->raw('>'); } } + +class_alias('Twig_Node_Expression_Binary_Greater', 'Twig\Node\Expression\Binary\GreaterBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/GreaterEqual.php b/inc/lib/Twig/Node/Expression/Binary/GreaterEqual.php index 3754fed2..c5f76245 100644 --- a/inc/lib/Twig/Node/Expression/Binary/GreaterEqual.php +++ b/inc/lib/Twig/Node/Expression/Binary/GreaterEqual.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Bina return $compiler->raw('>='); } } + +class_alias('Twig_Node_Expression_Binary_GreaterEqual', 'Twig\Node\Expression\Binary\GreaterEqualBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/In.php b/inc/lib/Twig/Node/Expression/Binary/In.php index 788f9377..af112448 100644 --- a/inc/lib/Twig/Node/Expression/Binary/In.php +++ b/inc/lib/Twig/Node/Expression/Binary/In.php @@ -3,18 +3,13 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary { - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -31,3 +26,5 @@ class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary return $compiler->raw('in'); } } + +class_alias('Twig_Node_Expression_Binary_In', 'Twig\Node\Expression\Binary\InBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Less.php b/inc/lib/Twig/Node/Expression/Binary/Less.php index 45fd3004..ab8fc1f9 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Less.php +++ b/inc/lib/Twig/Node/Expression/Binary/Less.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary return $compiler->raw('<'); } } + +class_alias('Twig_Node_Expression_Binary_Less', 'Twig\Node\Expression\Binary\LessBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/LessEqual.php b/inc/lib/Twig/Node/Expression/Binary/LessEqual.php index e38e257c..71a279e9 100644 --- a/inc/lib/Twig/Node/Expression/Binary/LessEqual.php +++ b/inc/lib/Twig/Node/Expression/Binary/LessEqual.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary return $compiler->raw('<='); } } + +class_alias('Twig_Node_Expression_Binary_LessEqual', 'Twig\Node\Expression\Binary\LessEqualBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Matches.php b/inc/lib/Twig/Node/Expression/Binary/Matches.php new file mode 100644 index 00000000..5cb85584 --- /dev/null +++ b/inc/lib/Twig/Node/Expression/Binary/Matches.php @@ -0,0 +1,30 @@ +<?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_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('preg_match(') + ->subcompile($this->getNode('right')) + ->raw(', ') + ->subcompile($this->getNode('left')) + ->raw(')') + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw(''); + } +} + +class_alias('Twig_Node_Expression_Binary_Matches', 'Twig\Node\Expression\Binary\MatchesBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Mod.php b/inc/lib/Twig/Node/Expression/Binary/Mod.php index 9924114f..28109633 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Mod.php +++ b/inc/lib/Twig/Node/Expression/Binary/Mod.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary return $compiler->raw('%'); } } + +class_alias('Twig_Node_Expression_Binary_Mod', 'Twig\Node\Expression\Binary\ModBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Mul.php b/inc/lib/Twig/Node/Expression/Binary/Mul.php index c91529ca..790c6a22 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Mul.php +++ b/inc/lib/Twig/Node/Expression/Binary/Mul.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary return $compiler->raw('*'); } } + +class_alias('Twig_Node_Expression_Binary_Mul', 'Twig\Node\Expression\Binary\MulBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/NotEqual.php b/inc/lib/Twig/Node/Expression/Binary/NotEqual.php index 26867ba2..bb45c9ed 100644 --- a/inc/lib/Twig/Node/Expression/Binary/NotEqual.php +++ b/inc/lib/Twig/Node/Expression/Binary/NotEqual.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,3 +15,5 @@ class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary return $compiler->raw('!='); } } + +class_alias('Twig_Node_Expression_Binary_NotEqual', 'Twig\Node\Expression\Binary\NotEqualBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/NotIn.php b/inc/lib/Twig/Node/Expression/Binary/NotIn.php index f347b7b6..9dedf92f 100644 --- a/inc/lib/Twig/Node/Expression/Binary/NotIn.php +++ b/inc/lib/Twig/Node/Expression/Binary/NotIn.php @@ -3,18 +3,13 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary { - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -31,3 +26,5 @@ class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary return $compiler->raw('not in'); } } + +class_alias('Twig_Node_Expression_Binary_NotIn', 'Twig\Node\Expression\Binary\NotInBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Or.php b/inc/lib/Twig/Node/Expression/Binary/Or.php index adba49c6..dc9eece1 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Or.php +++ b/inc/lib/Twig/Node/Expression/Binary/Or.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary return $compiler->raw('||'); } } + +class_alias('Twig_Node_Expression_Binary_Or', 'Twig\Node\Expression\Binary\OrBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Power.php b/inc/lib/Twig/Node/Expression/Binary/Power.php index b2c59040..d24777bd 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Power.php +++ b/inc/lib/Twig/Node/Expression/Binary/Power.php @@ -3,20 +3,19 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary { - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { + if (PHP_VERSION_ID >= 50600) { + return parent::compile($compiler); + } + $compiler ->raw('pow(') ->subcompile($this->getNode('left')) @@ -31,3 +30,5 @@ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary return $compiler->raw('**'); } } + +class_alias('Twig_Node_Expression_Binary_Power', 'Twig\Node\Expression\Binary\PowerBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Range.php b/inc/lib/Twig/Node/Expression/Binary/Range.php index bea4f2a6..187f6765 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Range.php +++ b/inc/lib/Twig/Node/Expression/Binary/Range.php @@ -3,18 +3,13 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary { - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -31,3 +26,5 @@ class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary return $compiler->raw('..'); } } + +class_alias('Twig_Node_Expression_Binary_Range', 'Twig\Node\Expression\Binary\RangeBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/StartsWith.php b/inc/lib/Twig/Node/Expression/Binary/StartsWith.php new file mode 100644 index 00000000..7e43b8de --- /dev/null +++ b/inc/lib/Twig/Node/Expression/Binary/StartsWith.php @@ -0,0 +1,32 @@ +<?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_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary +{ + public function compile(Twig_Compiler $compiler) + { + $left = $compiler->getVarName(); + $right = $compiler->getVarName(); + $compiler + ->raw(sprintf('(is_string($%s = ', $left)) + ->subcompile($this->getNode('left')) + ->raw(sprintf(') && is_string($%s = ', $right)) + ->subcompile($this->getNode('right')) + ->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right)) + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw(''); + } +} + +class_alias('Twig_Node_Expression_Binary_StartsWith', 'Twig\Node\Expression\Binary\StartsWithBinary', false); diff --git a/inc/lib/Twig/Node/Expression/Binary/Sub.php b/inc/lib/Twig/Node/Expression/Binary/Sub.php index d4463991..cff8ed07 100644 --- a/inc/lib/Twig/Node/Expression/Binary/Sub.php +++ b/inc/lib/Twig/Node/Expression/Binary/Sub.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary return $compiler->raw('-'); } } + +class_alias('Twig_Node_Expression_Binary_Sub', 'Twig\Node\Expression\Binary\SubBinary', false); diff --git a/inc/lib/Twig/Node/Expression/BlockReference.php b/inc/lib/Twig/Node/Expression/BlockReference.php index 647196eb..37a3983d 100644 --- a/inc/lib/Twig/Node/Expression/BlockReference.php +++ b/inc/lib/Twig/Node/Expression/BlockReference.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -17,35 +17,77 @@ */ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression { - public function __construct(Twig_NodeInterface $name, $asString = false, $lineno, $tag = null) + /** + * @param Twig_Node|null $template + */ + public function __construct(Twig_NodeInterface $name, $template = null, $lineno, $tag = null) { - parent::__construct(array('name' => $name), array('as_string' => $asString, 'output' => false), $lineno, $tag); + if (is_bool($template)) { + @trigger_error(sprintf('The %s method "$asString" argument is deprecated since version 1.28 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED); + + $template = null; + } + + $nodes = array('name' => $name); + if (null !== $template) { + $nodes['template'] = $template; + } + + parent::__construct($nodes, array('is_defined_test' => false, 'output' => false), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { - if ($this->getAttribute('as_string')) { - $compiler->raw('(string) '); + if ($this->getAttribute('is_defined_test')) { + $this->compileTemplateCall($compiler, 'hasBlock'); + } else { + if ($this->getAttribute('output')) { + $compiler->addDebugInfo($this); + + $this + ->compileTemplateCall($compiler, 'displayBlock') + ->raw(";\n"); + } else { + $this->compileTemplateCall($compiler, 'renderBlock'); + } } + } - if ($this->getAttribute('output')) { - $compiler - ->addDebugInfo($this) - ->write("\$this->displayBlock(") - ->subcompile($this->getNode('name')) - ->raw(", \$context, \$blocks);\n") - ; + private function compileTemplateCall(Twig_Compiler $compiler, $method) + { + if (!$this->hasNode('template')) { + $compiler->write('$this'); } else { $compiler - ->raw("\$this->renderBlock(") - ->subcompile($this->getNode('name')) - ->raw(", \$context, \$blocks)") + ->write('$this->loadTemplate(') + ->subcompile($this->getNode('template')) + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) + ->raw(')') ; } + + $compiler->raw(sprintf('->%s', $method)); + $this->compileBlockArguments($compiler); + + return $compiler; + } + + private function compileBlockArguments(Twig_Compiler $compiler) + { + $compiler + ->raw('(') + ->subcompile($this->getNode('name')) + ->raw(', $context'); + + if (!$this->hasNode('template')) { + $compiler->raw(', $blocks'); + } + + return $compiler->raw(')'); } } + +class_alias('Twig_Node_Expression_BlockReference', 'Twig\Node\Expression\BlockReferenceExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Call.php b/inc/lib/Twig/Node/Expression/Call.php index dba9b0e6..d962b6a5 100644 --- a/inc/lib/Twig/Node/Expression/Call.php +++ b/inc/lib/Twig/Node/Expression/Call.php @@ -3,27 +3,36 @@ /* * This file is part of Twig. * - * (c) 2012 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression { + private $reflector; + protected function compileCallable(Twig_Compiler $compiler) { - $callable = $this->getAttribute('callable'); - $closingParenthesis = false; - if ($callable) { - if (is_string($callable)) { + if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) { + if (is_string($callable) && false === strpos($callable, '::')) { $compiler->raw($callable); - } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) { - $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1])); } else { - $type = ucfirst($this->getAttribute('type')); - $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name'))); - $closingParenthesis = true; + list($r, $callable) = $this->reflectCallable($callable); + if ($r instanceof ReflectionMethod && is_string($callable[0])) { + if ($r->isStatic()) { + $compiler->raw(sprintf('%s::%s', $callable[0], $callable[1])); + } else { + $compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1])); + } + } elseif ($r instanceof ReflectionMethod && $callable[0] instanceof Twig_ExtensionInterface) { + $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', get_class($callable[0]), $callable[1])); + } else { + $type = ucfirst($this->getAttribute('type')); + $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name'))); + $closingParenthesis = true; + } } } else { $compiler->raw($this->getAttribute('thing')->compile()); @@ -73,7 +82,7 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression $first = false; } - if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) { + if ($this->hasNode('arguments')) { $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null; $arguments = $this->getArguments($callable, $this->getNode('arguments')); @@ -92,6 +101,9 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression protected function getArguments($callable, $arguments) { + $callType = $this->getAttribute('type'); + $callName = $this->getAttribute('name'); + $parameters = array(); $named = false; foreach ($arguments as $name => $node) { @@ -99,73 +111,101 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression $named = true; $name = $this->normalizeName($name); } elseif ($named) { - throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name'))); + throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName)); } $parameters[$name] = $node; } - if (!$named) { + $isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic'); + if (!$named && !$isVariadic) { return $parameters; } if (!$callable) { - throw new LogicException(sprintf('Named arguments are not supported for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name'))); - } - - // manage named arguments - if (is_array($callable)) { - $r = new ReflectionMethod($callable[0], $callable[1]); - } elseif (is_object($callable) && !$callable instanceof Closure) { - $r = new ReflectionObject($callable); - $r = $r->getMethod('__invoke'); - } else { - $r = new ReflectionFunction($callable); - } - - $definition = $r->getParameters(); - if ($this->hasNode('node')) { - array_shift($definition); - } - if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { - array_shift($definition); - } - if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { - array_shift($definition); - } - if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) { - foreach ($this->getAttribute('arguments') as $argument) { - array_shift($definition); + if ($named) { + $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName); + } else { + $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName); } + + throw new LogicException($message); } + $callableParameters = $this->getCallableParameters($callable, $isVariadic); $arguments = array(); + $names = array(); + $missingArguments = array(); + $optionalArguments = array(); $pos = 0; - foreach ($definition as $param) { - $name = $this->normalizeName($param->name); + foreach ($callableParameters as $callableParameter) { + $names[] = $name = $this->normalizeName($callableParameter->name); if (array_key_exists($name, $parameters)) { if (array_key_exists($pos, $parameters)) { - throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name'))); + throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName)); + } + + if (count($missingArguments)) { + throw new Twig_Error_Syntax(sprintf( + 'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".', + $name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments)) + ); } + $arguments = array_merge($arguments, $optionalArguments); $arguments[] = $parameters[$name]; unset($parameters[$name]); + $optionalArguments = array(); } elseif (array_key_exists($pos, $parameters)) { + $arguments = array_merge($arguments, $optionalArguments); $arguments[] = $parameters[$pos]; unset($parameters[$pos]); + $optionalArguments = array(); ++$pos; - } elseif ($param->isDefaultValueAvailable()) { - $arguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1); - } elseif ($param->isOptional()) { - break; + } elseif ($callableParameter->isDefaultValueAvailable()) { + $optionalArguments[] = new Twig_Node_Expression_Constant($callableParameter->getDefaultValue(), -1); + } elseif ($callableParameter->isOptional()) { + if (empty($parameters)) { + break; + } else { + $missingArguments[] = $name; + } } else { - throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name'))); + throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName)); + } + } + + if ($isVariadic) { + $arbitraryArguments = new Twig_Node_Expression_Array(array(), -1); + foreach ($parameters as $key => $value) { + if (is_int($key)) { + $arbitraryArguments->addElement($value); + } else { + $arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1)); + } + unset($parameters[$key]); + } + + if ($arbitraryArguments->count()) { + $arguments = array_merge($arguments, $optionalArguments); + $arguments[] = $arbitraryArguments; } } if (!empty($parameters)) { - throw new Twig_Error_Syntax(sprintf('Unknown argument%s "%s" for %s "%s".', count($parameters) > 1 ? 's' : '' , implode('", "', array_keys($parameters)), $this->getAttribute('type'), $this->getAttribute('name'))); + $unknownParameter = null; + foreach ($parameters as $parameter) { + if ($parameter instanceof Twig_Node) { + $unknownParameter = $parameter; + break; + } + } + + throw new Twig_Error_Syntax(sprintf( + 'Unknown argument%s "%s" for %s "%s(%s)".', + count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names) + ), $unknownParameter ? $unknownParameter->getTemplateLine() : -1); } return $arguments; @@ -175,4 +215,77 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression { return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name)); } + + private function getCallableParameters($callable, $isVariadic) + { + list($r) = $this->reflectCallable($callable); + if (null === $r) { + return array(); + } + + $parameters = $r->getParameters(); + if ($this->hasNode('node')) { + array_shift($parameters); + } + if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { + array_shift($parameters); + } + if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { + array_shift($parameters); + } + if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) { + foreach ($this->getAttribute('arguments') as $argument) { + array_shift($parameters); + } + } + if ($isVariadic) { + $argument = end($parameters); + if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) { + array_pop($parameters); + } else { + $callableName = $r->name; + if ($r instanceof ReflectionMethod) { + $callableName = $r->getDeclaringClass()->name.'::'.$callableName; + } + + throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $this->getAttribute('type'), $this->getAttribute('name'))); + } + } + + return $parameters; + } + + private function reflectCallable($callable) + { + if (null !== $this->reflector) { + return $this->reflector; + } + + if (is_array($callable)) { + if (!method_exists($callable[0], $callable[1])) { + // __call() + return array(null, array()); + } + $r = new ReflectionMethod($callable[0], $callable[1]); + } elseif (is_object($callable) && !$callable instanceof Closure) { + $r = new ReflectionObject($callable); + $r = $r->getMethod('__invoke'); + $callable = array($callable, '__invoke'); + } elseif (is_string($callable) && false !== $pos = strpos($callable, '::')) { + $class = substr($callable, 0, $pos); + $method = substr($callable, $pos + 2); + if (!method_exists($class, $method)) { + // __staticCall() + return array(null, array()); + } + $r = new ReflectionMethod($callable); + $callable = array($class, $method); + } else { + $r = new ReflectionFunction($callable); + } + + return $this->reflector = array($r, $callable); + } } + +class_alias('Twig_Node_Expression_Call', 'Twig\Node\Expression\CallExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Conditional.php b/inc/lib/Twig/Node/Expression/Conditional.php index edcb1e2d..c339d773 100644 --- a/inc/lib/Twig/Node/Expression/Conditional.php +++ b/inc/lib/Twig/Node/Expression/Conditional.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -29,3 +29,5 @@ class Twig_Node_Expression_Conditional extends Twig_Node_Expression ; } } + +class_alias('Twig_Node_Expression_Conditional', 'Twig\Node\Expression\ConditionalExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Constant.php b/inc/lib/Twig/Node/Expression/Constant.php index a91dc698..bf4d031c 100644 --- a/inc/lib/Twig/Node/Expression/Constant.php +++ b/inc/lib/Twig/Node/Expression/Constant.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,3 +21,5 @@ class Twig_Node_Expression_Constant extends Twig_Node_Expression $compiler->repr($this->getAttribute('value')); } } + +class_alias('Twig_Node_Expression_Constant', 'Twig\Node\Expression\ConstantExpression', false); diff --git a/inc/lib/Twig/Node/Expression/ExtensionReference.php b/inc/lib/Twig/Node/Expression/ExtensionReference.php index 00ac6701..114b5cd9 100644 --- a/inc/lib/Twig/Node/Expression/ExtensionReference.php +++ b/inc/lib/Twig/Node/Expression/ExtensionReference.php @@ -3,16 +3,20 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ +@trigger_error('The Twig_Node_Expression_ExtensionReference class is deprecated since version 1.23 and will be removed in 2.0.', E_USER_DEPRECATED); + /** * Represents an extension call node. * * @author Fabien Potencier <fabien@symfony.com> + * + * @deprecated since 1.23 and will be removed in 2.0. */ class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression { @@ -21,11 +25,6 @@ class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression parent::__construct(array(), array('name' => $name), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name'))); diff --git a/inc/lib/Twig/Node/Expression/Filter.php b/inc/lib/Twig/Node/Expression/Filter.php index 207b062a..12da1d67 100644 --- a/inc/lib/Twig/Node/Expression/Filter.php +++ b/inc/lib/Twig/Node/Expression/Filter.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -30,7 +30,12 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) { $this->setAttribute('callable', $filter->getCallable()); } + if ($filter instanceof Twig_SimpleFilter) { + $this->setAttribute('is_variadic', $filter->isVariadic()); + } $this->compileCallable($compiler); } } + +class_alias('Twig_Node_Expression_Filter', 'Twig\Node\Expression\FilterExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Filter/Default.php b/inc/lib/Twig/Node/Expression/Filter/Default.php index 1827c888..d2e19d54 100644 --- a/inc/lib/Twig/Node/Expression/Filter/Default.php +++ b/inc/lib/Twig/Node/Expression/Filter/Default.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -22,13 +22,13 @@ class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter { public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null) { - $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getLine()), $arguments, $node->getLine()); + $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine()); if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) { - $test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getLine()); - $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getLine()); + $test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getTemplateLine()); + $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getTemplateLine()); - $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getLine()); + $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getTemplateLine()); } else { $node = $default; } @@ -41,3 +41,5 @@ class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter $compiler->subcompile($this->getNode('node')); } } + +class_alias('Twig_Node_Expression_Filter_Default', 'Twig\Node\Expression\Filter\DefaultFilter', false); diff --git a/inc/lib/Twig/Node/Expression/Function.php b/inc/lib/Twig/Node/Expression/Function.php index 3e1f6b55..cdee7c97 100644 --- a/inc/lib/Twig/Node/Expression/Function.php +++ b/inc/lib/Twig/Node/Expression/Function.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call { public function __construct($name, Twig_NodeInterface $arguments, $lineno) { - parent::__construct(array('arguments' => $arguments), array('name' => $name), $lineno); + parent::__construct(array('arguments' => $arguments), array('name' => $name, 'is_defined_test' => false), $lineno); } public function compile(Twig_Compiler $compiler) @@ -27,9 +27,19 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call $this->setAttribute('needs_context', $function->needsContext()); $this->setAttribute('arguments', $function->getArguments()); if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) { - $this->setAttribute('callable', $function->getCallable()); + $callable = $function->getCallable(); + if ('constant' === $name && $this->getAttribute('is_defined_test')) { + $callable = 'twig_constant_is_defined'; + } + + $this->setAttribute('callable', $callable); + } + if ($function instanceof Twig_SimpleFunction) { + $this->setAttribute('is_variadic', $function->isVariadic()); } $this->compileCallable($compiler); } } + +class_alias('Twig_Node_Expression_Function', 'Twig\Node\Expression\FunctionExpression', false); diff --git a/inc/lib/Twig/Node/Expression/GetAttr.php b/inc/lib/Twig/Node/Expression/GetAttr.php index 55d9fcc3..b7823acc 100644 --- a/inc/lib/Twig/Node/Expression/GetAttr.php +++ b/inc/lib/Twig/Node/Expression/GetAttr.php @@ -3,21 +3,30 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression { - public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno) + public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression $arguments = null, $type, $lineno) { - parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno); + $nodes = array('node' => $node, 'attribute' => $attribute); + if (null !== $arguments) { + $nodes['arguments'] = $arguments; + } + + parent::__construct($nodes, array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno); } public function compile(Twig_Compiler $compiler) { + if ($this->getAttribute('disable_c_ext')) { + @trigger_error(sprintf('Using the "disable_c_ext" attribute on %s is deprecated since version 1.30 and will be removed in 2.0.', __CLASS__), E_USER_DEPRECATED); + } + if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) { $compiler->raw('twig_template_get_attributes($this, '); } else { @@ -32,22 +41,34 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression $compiler->raw(', ')->subcompile($this->getNode('attribute')); - if (count($this->getNode('arguments')) || Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { - $compiler->raw(', ')->subcompile($this->getNode('arguments')); + // only generate optional arguments when needed (to make generated code more readable) + $needFourth = $this->getAttribute('ignore_strict_check'); + $needThird = $needFourth || $this->getAttribute('is_defined_test'); + $needSecond = $needThird || Twig_Template::ANY_CALL !== $this->getAttribute('type'); + $needFirst = $needSecond || $this->hasNode('arguments'); - if (Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { - $compiler->raw(', ')->repr($this->getAttribute('type')); + if ($needFirst) { + if ($this->hasNode('arguments')) { + $compiler->raw(', ')->subcompile($this->getNode('arguments')); + } else { + $compiler->raw(', array()'); } + } - if ($this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { - $compiler->raw(', '.($this->getAttribute('is_defined_test') ? 'true' : 'false')); - } + if ($needSecond) { + $compiler->raw(', ')->repr($this->getAttribute('type')); + } - if ($this->getAttribute('ignore_strict_check')) { - $compiler->raw(', '.($this->getAttribute('ignore_strict_check') ? 'true' : 'false')); - } + if ($needThird) { + $compiler->raw(', ')->repr($this->getAttribute('is_defined_test')); + } + + if ($needFourth) { + $compiler->raw(', ')->repr($this->getAttribute('ignore_strict_check')); } $compiler->raw(')'); } } + +class_alias('Twig_Node_Expression_GetAttr', 'Twig\Node\Expression\GetAttrExpression', false); diff --git a/inc/lib/Twig/Node/Expression/MethodCall.php b/inc/lib/Twig/Node/Expression/MethodCall.php index 620b02bf..709016eb 100644 --- a/inc/lib/Twig/Node/Expression/MethodCall.php +++ b/inc/lib/Twig/Node/Expression/MethodCall.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2012 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -39,3 +39,5 @@ class Twig_Node_Expression_MethodCall extends Twig_Node_Expression $compiler->raw(')'); } } + +class_alias('Twig_Node_Expression_MethodCall', 'Twig\Node\Expression\MethodCallExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Name.php b/inc/lib/Twig/Node/Expression/Name.php index 3b8fae01..9d5a21f8 100644 --- a/inc/lib/Twig/Node/Expression/Name.php +++ b/inc/lib/Twig/Node/Expression/Name.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,7 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression { protected $specialVars = array( - '_self' => '$this', + '_self' => '$this', '_context' => '$context', '_charset' => '$this->env->getCharset()', ); @@ -26,6 +26,8 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression { $name = $this->getAttribute('name'); + $compiler->addDebugInfo($this); + if ($this->getAttribute('is_defined_test')) { if ($this->isSpecial()) { $compiler->repr(true); @@ -41,10 +43,20 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression ->raw(']') ; } else { - // remove the non-PHP 5.4 version when PHP 5.3 support is dropped - // as the non-optimized version is just a workaround for slow ternary operator - // when the context has a lot of variables - if (version_compare(phpversion(), '5.4.0RC1', '>=')) { + if (PHP_VERSION_ID >= 70000) { + // use PHP 7 null coalescing operator + $compiler + ->raw('($context[') + ->string($name) + ->raw('] ?? ') + ; + + if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) { + $compiler->raw('null)'); + } else { + $compiler->raw('$this->getContext($context, ')->string($name)->raw('))'); + } + } elseif (PHP_VERSION_ID >= 50400) { // PHP 5.4 ternary operator performance was optimized $compiler ->raw('(isset($context[') @@ -86,3 +98,5 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression return !$this->isSpecial() && !$this->getAttribute('is_defined_test'); } } + +class_alias('Twig_Node_Expression_Name', 'Twig\Node\Expression\NameExpression', false); diff --git a/inc/lib/Twig/Node/Expression/NullCoalesce.php b/inc/lib/Twig/Node/Expression/NullCoalesce.php new file mode 100644 index 00000000..eaafa4c9 --- /dev/null +++ b/inc/lib/Twig/Node/Expression/NullCoalesce.php @@ -0,0 +1,48 @@ +<?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_Node_Expression_NullCoalesce extends Twig_Node_Expression_Conditional +{ + public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno) + { + $test = new Twig_Node_Expression_Binary_And( + new Twig_Node_Expression_Test_Defined(clone $left, 'defined', new Twig_Node(), $left->getTemplateLine()), + new Twig_Node_Expression_Unary_Not(new Twig_Node_Expression_Test_Null($left, 'null', new Twig_Node(), $left->getTemplateLine()), $left->getTemplateLine()), + $left->getTemplateLine() + ); + + parent::__construct($test, $left, $right, $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + /* + * This optimizes only one case. PHP 7 also supports more complex expressions + * that can return null. So, for instance, if log is defined, log("foo") ?? "..." works, + * but log($a["foo"]) ?? "..." does not if $a["foo"] is not defined. More advanced + * cases might be implemented as an optimizer node visitor, but has not been done + * as benefits are probably not worth the added complexity. + */ + if (PHP_VERSION_ID >= 70000 && $this->getNode('expr2') instanceof Twig_Node_Expression_Name) { + $this->getNode('expr2')->setAttribute('always_defined', true); + $compiler + ->raw('((') + ->subcompile($this->getNode('expr2')) + ->raw(') ?? (') + ->subcompile($this->getNode('expr3')) + ->raw('))') + ; + } else { + parent::compile($compiler); + } + } +} + +class_alias('Twig_Node_Expression_NullCoalesce', 'Twig\Node\Expression\NullCoalesceExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Parent.php b/inc/lib/Twig/Node/Expression/Parent.php index dcf618c0..78692db2 100644 --- a/inc/lib/Twig/Node/Expression/Parent.php +++ b/inc/lib/Twig/Node/Expression/Parent.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -22,26 +22,23 @@ class Twig_Node_Expression_Parent extends Twig_Node_Expression parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { if ($this->getAttribute('output')) { $compiler ->addDebugInfo($this) - ->write("\$this->displayParentBlock(") + ->write('$this->displayParentBlock(') ->string($this->getAttribute('name')) ->raw(", \$context, \$blocks);\n") ; } else { $compiler - ->raw("\$this->renderParentBlock(") + ->raw('$this->renderParentBlock(') ->string($this->getAttribute('name')) - ->raw(", \$context, \$blocks)") + ->raw(', $context, $blocks)') ; } } } + +class_alias('Twig_Node_Expression_Parent', 'Twig\Node\Expression\ParentExpression', false); diff --git a/inc/lib/Twig/Node/Expression/TempName.php b/inc/lib/Twig/Node/Expression/TempName.php index e6b058e8..0a86e003 100644 --- a/inc/lib/Twig/Node/Expression/TempName.php +++ b/inc/lib/Twig/Node/Expression/TempName.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -24,3 +24,5 @@ class Twig_Node_Expression_TempName extends Twig_Node_Expression ; } } + +class_alias('Twig_Node_Expression_TempName', 'Twig\Node\Expression\TempNameExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Test.php b/inc/lib/Twig/Node/Expression/Test.php index 639f501a..ad102ba6 100644 --- a/inc/lib/Twig/Node/Expression/Test.php +++ b/inc/lib/Twig/Node/Expression/Test.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,7 +12,12 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call { public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) { - parent::__construct(array('node' => $node, 'arguments' => $arguments), array('name' => $name), $lineno); + $nodes = array('node' => $node); + if (null !== $arguments) { + $nodes['arguments'] = $arguments; + } + + parent::__construct($nodes, array('name' => $name), $lineno); } public function compile(Twig_Compiler $compiler) @@ -26,7 +31,12 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) { $this->setAttribute('callable', $test->getCallable()); } + if ($test instanceof Twig_SimpleTest) { + $this->setAttribute('is_variadic', $test->isVariadic()); + } $this->compileCallable($compiler); } } + +class_alias('Twig_Node_Expression_Test', 'Twig\Node\Expression\TestExpression', false); diff --git a/inc/lib/Twig/Node/Expression/Test/Constant.php b/inc/lib/Twig/Node/Expression/Test/Constant.php index de55f5f5..a51a4ba1 100644 --- a/inc/lib/Twig/Node/Expression/Test/Constant.php +++ b/inc/lib/Twig/Node/Expression/Test/Constant.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -44,3 +44,5 @@ class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test ; } } + +class_alias('Twig_Node_Expression_Test_Constant', 'Twig\Node\Expression\Test\ConstantTest', false); diff --git a/inc/lib/Twig/Node/Expression/Test/Defined.php b/inc/lib/Twig/Node/Expression/Test/Defined.php index 247b2e23..2136c390 100644 --- a/inc/lib/Twig/Node/Expression/Test/Defined.php +++ b/inc/lib/Twig/Node/Expression/Test/Defined.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -25,17 +25,22 @@ class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test { public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) { - parent::__construct($node, $name, $arguments, $lineno); - if ($node instanceof Twig_Node_Expression_Name) { $node->setAttribute('is_defined_test', true); } elseif ($node instanceof Twig_Node_Expression_GetAttr) { $node->setAttribute('is_defined_test', true); - $this->changeIgnoreStrictCheck($node); + } elseif ($node instanceof Twig_Node_Expression_BlockReference) { + $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof Twig_Node_Expression_Function && 'constant' === $node->getAttribute('name')) { + $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array) { + $node = new Twig_Node_Expression_Constant(true, $node->getTemplateLine()); } else { - throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine()); + throw new Twig_Error_Syntax('The "defined" test only works with simple variables.', $this->getTemplateLine()); } + + parent::__construct($node, $name, $arguments, $lineno); } protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node) @@ -52,3 +57,5 @@ class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test $compiler->subcompile($this->getNode('node')); } } + +class_alias('Twig_Node_Expression_Test_Defined', 'Twig\Node\Expression\Test\DefinedTest', false); diff --git a/inc/lib/Twig/Node/Expression/Test/Divisibleby.php b/inc/lib/Twig/Node/Expression/Test/Divisibleby.php index 0aceb530..a5d71961 100644 --- a/inc/lib/Twig/Node/Expression/Test/Divisibleby.php +++ b/inc/lib/Twig/Node/Expression/Test/Divisibleby.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,7 +13,7 @@ * Checks if a variable is divisible by a number. * * <pre> - * {% if loop.index is divisibleby(3) %} + * {% if loop.index is divisible by(3) %} * </pre> * * @author Fabien Potencier <fabien@symfony.com> @@ -31,3 +31,5 @@ class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test ; } } + +class_alias('Twig_Node_Expression_Test_Divisibleby', 'Twig\Node\Expression\Test\DivisiblebyTest', false); diff --git a/inc/lib/Twig/Node/Expression/Test/Even.php b/inc/lib/Twig/Node/Expression/Test/Even.php index d7853e89..7e198bea 100644 --- a/inc/lib/Twig/Node/Expression/Test/Even.php +++ b/inc/lib/Twig/Node/Expression/Test/Even.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -30,3 +30,5 @@ class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test ; } } + +class_alias('Twig_Node_Expression_Test_Even', 'Twig\Node\Expression\Test\EvenTest', false); diff --git a/inc/lib/Twig/Node/Expression/Test/Null.php b/inc/lib/Twig/Node/Expression/Test/Null.php index 1c83825a..3746e4cb 100644 --- a/inc/lib/Twig/Node/Expression/Test/Null.php +++ b/inc/lib/Twig/Node/Expression/Test/Null.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -29,3 +29,5 @@ class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test ; } } + +class_alias('Twig_Node_Expression_Test_Null', 'Twig\Node\Expression\Test\NullTest', false); diff --git a/inc/lib/Twig/Node/Expression/Test/Odd.php b/inc/lib/Twig/Node/Expression/Test/Odd.php index 421c19e8..0c6c099b 100644 --- a/inc/lib/Twig/Node/Expression/Test/Odd.php +++ b/inc/lib/Twig/Node/Expression/Test/Odd.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -30,3 +30,5 @@ class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test ; } } + +class_alias('Twig_Node_Expression_Test_Odd', 'Twig\Node\Expression\Test\OddTest', false); diff --git a/inc/lib/Twig/Node/Expression/Test/Sameas.php b/inc/lib/Twig/Node/Expression/Test/Sameas.php index b48905ee..e95ff1f2 100644 --- a/inc/lib/Twig/Node/Expression/Test/Sameas.php +++ b/inc/lib/Twig/Node/Expression/Test/Sameas.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -27,3 +27,5 @@ class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test ; } } + +class_alias('Twig_Node_Expression_Test_Sameas', 'Twig\Node\Expression\Test\SameasTest', false); diff --git a/inc/lib/Twig/Node/Expression/Unary.php b/inc/lib/Twig/Node/Expression/Unary.php index c514388e..5804485e 100644 --- a/inc/lib/Twig/Node/Expression/Unary.php +++ b/inc/lib/Twig/Node/Expression/Unary.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -18,13 +18,12 @@ abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression public function compile(Twig_Compiler $compiler) { - $compiler->raw('('); + $compiler->raw(' '); $this->operator($compiler); - $compiler - ->subcompile($this->getNode('node')) - ->raw(')') - ; + $compiler->subcompile($this->getNode('node')); } abstract public function operator(Twig_Compiler $compiler); } + +class_alias('Twig_Node_Expression_Unary', 'Twig\Node\Expression\Unary\AbstractUnary', false); diff --git a/inc/lib/Twig/Node/Expression/Unary/Neg.php b/inc/lib/Twig/Node/Expression/Unary/Neg.php index 2a3937ec..039d933d 100644 --- a/inc/lib/Twig/Node/Expression/Unary/Neg.php +++ b/inc/lib/Twig/Node/Expression/Unary/Neg.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary $compiler->raw('-'); } } + +class_alias('Twig_Node_Expression_Unary_Neg', 'Twig\Node\Expression\Unary\NegUnary', false); diff --git a/inc/lib/Twig/Node/Expression/Unary/Not.php b/inc/lib/Twig/Node/Expression/Unary/Not.php index f94073cf..a0860b18 100644 --- a/inc/lib/Twig/Node/Expression/Unary/Not.php +++ b/inc/lib/Twig/Node/Expression/Unary/Not.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary $compiler->raw('!'); } } + +class_alias('Twig_Node_Expression_Unary_Not', 'Twig\Node\Expression\Unary\NotUnary', false); diff --git a/inc/lib/Twig/Node/Expression/Unary/Pos.php b/inc/lib/Twig/Node/Expression/Unary/Pos.php index 04edb52a..eeff5452 100644 --- a/inc/lib/Twig/Node/Expression/Unary/Pos.php +++ b/inc/lib/Twig/Node/Expression/Unary/Pos.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,3 +16,5 @@ class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary $compiler->raw('+'); } } + +class_alias('Twig_Node_Expression_Unary_Pos', 'Twig\Node\Expression\Unary\PosUnary', false); diff --git a/inc/lib/Twig/Node/Flush.php b/inc/lib/Twig/Node/Flush.php index 0467ddce..fcc461ac 100644 --- a/inc/lib/Twig/Node/Flush.php +++ b/inc/lib/Twig/Node/Flush.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,11 +21,6 @@ class Twig_Node_Flush extends Twig_Node parent::__construct(array(), array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -34,3 +29,5 @@ class Twig_Node_Flush extends Twig_Node ; } } + +class_alias('Twig_Node_Flush', 'Twig\Node\FlushNode', false); diff --git a/inc/lib/Twig/Node/For.php b/inc/lib/Twig/Node/For.php index d1ff371d..914b70c9 100644 --- a/inc/lib/Twig/Node/For.php +++ b/inc/lib/Twig/Node/For.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -27,26 +27,25 @@ class Twig_Node_For extends Twig_Node $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag); } - parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag); + $nodes = array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body); + if (null !== $else) { + $nodes['else'] = $else; + } + + parent::__construct($nodes, array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) - // the (array) cast bypasses a PHP 5.2.6 bug - ->write("\$context['_parent'] = (array) \$context;\n") + ->write("\$context['_parent'] = \$context;\n") ->write("\$context['_seq'] = twig_ensure_traversable(") ->subcompile($this->getNode('seq')) ->raw(");\n") ; - if (null !== $this->getNode('else')) { + if ($this->hasNode('else')) { $compiler->write("\$context['_iterated'] = false;\n"); } @@ -75,14 +74,14 @@ class Twig_Node_For extends Twig_Node } } - $this->loop->setAttribute('else', null !== $this->getNode('else')); + $this->loop->setAttribute('else', $this->hasNode('else')); $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop')); $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr')); $compiler ->write("foreach (\$context['_seq'] as ") ->subcompile($this->getNode('key_target')) - ->raw(" => ") + ->raw(' => ') ->subcompile($this->getNode('value_target')) ->raw(") {\n") ->indent() @@ -91,7 +90,7 @@ class Twig_Node_For extends Twig_Node ->write("}\n") ; - if (null !== $this->getNode('else')) { + if ($this->hasNode('else')) { $compiler ->write("if (!\$context['_iterated']) {\n") ->indent() @@ -110,3 +109,5 @@ class Twig_Node_For extends Twig_Node $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n"); } } + +class_alias('Twig_Node_For', 'Twig\Node\ForNode', false); diff --git a/inc/lib/Twig/Node/ForLoop.php b/inc/lib/Twig/Node/ForLoop.php index b8841583..06477cf1 100644 --- a/inc/lib/Twig/Node/ForLoop.php +++ b/inc/lib/Twig/Node/ForLoop.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,11 +21,6 @@ class Twig_Node_ForLoop extends Twig_Node parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { if ($this->getAttribute('else')) { @@ -53,3 +48,5 @@ class Twig_Node_ForLoop extends Twig_Node } } } + +class_alias('Twig_Node_ForLoop', 'Twig\Node\ForLoopNode', false); diff --git a/inc/lib/Twig/Node/If.php b/inc/lib/Twig/Node/If.php index 4296a8d6..d82edec7 100644 --- a/inc/lib/Twig/Node/If.php +++ b/inc/lib/Twig/Node/If.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -19,22 +19,22 @@ class Twig_Node_If extends Twig_Node { public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null) { - parent::__construct(array('tests' => $tests, 'else' => $else), array(), $lineno, $tag); + $nodes = array('tests' => $tests); + if (null !== $else) { + $nodes['else'] = $else; + } + + parent::__construct($nodes, array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler->addDebugInfo($this); - for ($i = 0; $i < count($this->getNode('tests')); $i += 2) { + for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) { if ($i > 0) { $compiler ->outdent() - ->write("} elseif (") + ->write('} elseif (') ; } else { $compiler @@ -50,7 +50,7 @@ class Twig_Node_If extends Twig_Node ; } - if ($this->hasNode('else') && null !== $this->getNode('else')) { + if ($this->hasNode('else')) { $compiler ->outdent() ->write("} else {\n") @@ -64,3 +64,5 @@ class Twig_Node_If extends Twig_Node ->write("}\n"); } } + +class_alias('Twig_Node_If', 'Twig\Node\IfNode', false); diff --git a/inc/lib/Twig/Node/Import.php b/inc/lib/Twig/Node/Import.php index 99efc091..c77e320b 100644 --- a/inc/lib/Twig/Node/Import.php +++ b/inc/lib/Twig/Node/Import.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,11 +21,6 @@ class Twig_Node_Import extends Twig_Node parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -36,15 +31,21 @@ class Twig_Node_Import extends Twig_Node ; if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) { - $compiler->raw("\$this"); + $compiler->raw('$this'); } else { $compiler - ->raw('$this->env->loadTemplate(') + ->raw('$this->loadTemplate(') ->subcompile($this->getNode('expr')) - ->raw(")") + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) + ->raw(')') ; } $compiler->raw(";\n"); } } + +class_alias('Twig_Node_Import', 'Twig\Node\ImportNode', false); diff --git a/inc/lib/Twig/Node/Include.php b/inc/lib/Twig/Node/Include.php index ed4a3751..2a5114cb 100644 --- a/inc/lib/Twig/Node/Include.php +++ b/inc/lib/Twig/Node/Include.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -19,14 +19,14 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface { public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) { - parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (Boolean) $only, 'ignore_missing' => (Boolean) $ignoreMissing), $lineno, $tag); + $nodes = array('expr' => $expr); + if (null !== $variables) { + $nodes['variables'] = $variables; + } + + parent::__construct($nodes, array('only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler->addDebugInfo($this); @@ -60,40 +60,31 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface protected function addGetTemplate(Twig_Compiler $compiler) { - if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) { - $compiler - ->write("\$this->env->loadTemplate(") - ->subcompile($this->getNode('expr')) - ->raw(")") - ; - } else { - $compiler - ->write("\$template = \$this->env->resolveTemplate(") - ->subcompile($this->getNode('expr')) - ->raw(");\n") - ->write('$template') - ; - } + $compiler + ->write('$this->loadTemplate(') + ->subcompile($this->getNode('expr')) + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) + ->raw(')') + ; } protected function addTemplateArguments(Twig_Compiler $compiler) { - if (false === $this->getAttribute('only')) { - if (null === $this->getNode('variables')) { - $compiler->raw('$context'); - } else { - $compiler - ->raw('array_merge($context, ') - ->subcompile($this->getNode('variables')) - ->raw(')') - ; - } + if (!$this->hasNode('variables')) { + $compiler->raw(false === $this->getAttribute('only') ? '$context' : 'array()'); + } elseif (false === $this->getAttribute('only')) { + $compiler + ->raw('array_merge($context, ') + ->subcompile($this->getNode('variables')) + ->raw(')') + ; } else { - if (null === $this->getNode('variables')) { - $compiler->raw('array()'); - } else { - $compiler->subcompile($this->getNode('variables')); - } + $compiler->subcompile($this->getNode('variables')); } } } + +class_alias('Twig_Node_Include', 'Twig\Node\IncludeNode', false); diff --git a/inc/lib/Twig/Node/Macro.php b/inc/lib/Twig/Node/Macro.php index 43c75e5c..3cf54977 100644 --- a/inc/lib/Twig/Node/Macro.php +++ b/inc/lib/Twig/Node/Macro.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -16,28 +16,31 @@ */ class Twig_Node_Macro extends Twig_Node { + const VARARGS_NAME = 'varargs'; + 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); + 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->getTemplateLine()); + } + } + + parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $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')); $pos = 0; foreach ($this->getNode('arguments') as $name => $default) { $compiler - ->raw('$_'.$name.' = ') + ->raw('$__'.$name.'__ = ') ->subcompile($default) ; @@ -46,36 +49,55 @@ class Twig_Node_Macro extends Twig_Node } } + if (PHP_VERSION_ID >= 50600) { + if ($count) { + $compiler->raw(', '); + } + + $compiler->raw('...$__varargs__'); + } + $compiler ->raw(")\n") ->write("{\n") ->indent() ; - if (!count($this->getNode('arguments'))) { - $compiler->write("\$context = \$this->env->getGlobals();\n\n"); - } else { + $compiler + ->write("\$context = \$this->env->mergeGlobals(array(\n") + ->indent() + ; + + foreach ($this->getNode('arguments') as $name => $default) { $compiler - ->write("\$context = \$this->env->mergeGlobals(array(\n") - ->indent() + ->write('') + ->string($name) + ->raw(' => $__'.$name.'__') + ->raw(",\n") ; + } - foreach ($this->getNode('arguments') as $name => $default) { - $compiler - ->write('') - ->string($name) - ->raw(' => $_'.$name) - ->raw(",\n") - ; - } + $compiler + ->write('') + ->string(self::VARARGS_NAME) + ->raw(' => ') + ; + if (PHP_VERSION_ID >= 50600) { + $compiler->raw("\$__varargs__,\n"); + } else { $compiler - ->outdent() - ->write("));\n\n") + ->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("ob_start();\n") ->write("try {\n") @@ -87,6 +109,11 @@ class Twig_Node_Macro extends Twig_Node ->write("ob_end_clean();\n\n") ->write("throw \$e;\n") ->outdent() + ->write("} catch (Throwable \$e) {\n") + ->indent() + ->write("ob_end_clean();\n\n") + ->write("throw \$e;\n") + ->outdent() ->write("}\n\n") ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n") ->outdent() @@ -94,3 +121,5 @@ class Twig_Node_Macro extends Twig_Node ; } } + +class_alias('Twig_Node_Macro', 'Twig\Node\MacroNode', false); diff --git a/inc/lib/Twig/Node/Module.php b/inc/lib/Twig/Node/Module.php index 224410a2..5cd8d050 100644 --- a/inc/lib/Twig/Node/Module.php +++ b/inc/lib/Twig/Node/Module.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -13,14 +13,52 @@ /** * Represents a module node. * + * Consider this class as being final. If you need to customize the behavior of + * the generated class, consider adding nodes to the following nodes: display_start, + * display_end, constructor_start, constructor_end, and class_end. + * * @author Fabien Potencier <fabien@symfony.com> */ class Twig_Node_Module extends Twig_Node { - public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename) + private $source; + + public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '') { + if (!$name instanceof Twig_Source) { + @trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED); + $this->source = new Twig_Source($source, $name); + } else { + $this->source = $name; + } + + $nodes = array( + 'body' => $body, + 'blocks' => $blocks, + 'macros' => $macros, + 'traits' => $traits, + 'display_start' => new Twig_Node(), + 'display_end' => new Twig_Node(), + 'constructor_start' => new Twig_Node(), + 'constructor_end' => new Twig_Node(), + 'class_end' => new Twig_Node(), + ); + if (null !== $parent) { + $nodes['parent'] = $parent; + } + // embedded templates are set as attributes so that they are only visited once by the visitors - parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits), array('filename' => $filename, 'index' => null, 'embedded_templates' => $embeddedTemplates), 1); + parent::__construct($nodes, array( + // source to be remove in 2.0 + 'source' => $this->source->getCode(), + // filename to be remove in 2.0 (use getTemplateName() instead) + 'filename' => $this->source->getName(), + 'index' => null, + 'embedded_templates' => $embeddedTemplates, + ), 1); + + // populate the template name of all node children + $this->setTemplateName($this->source->getName()); } public function setIndex($index) @@ -28,11 +66,6 @@ class Twig_Node_Module extends Twig_Node $this->setAttribute('index', $index); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $this->compileTemplate($compiler); @@ -50,17 +83,20 @@ class Twig_Node_Module extends Twig_Node $this->compileClassHeader($compiler); - if (count($this->getNode('blocks')) || count($this->getNode('traits')) || null === $this->getNode('parent') || $this->getNode('parent') instanceof Twig_Node_Expression_Constant) { + if ( + count($this->getNode('blocks')) + || count($this->getNode('traits')) + || !$this->hasNode('parent') + || $this->getNode('parent') instanceof Twig_Node_Expression_Constant + || count($this->getNode('constructor_start')) + || count($this->getNode('constructor_end')) + ) { $this->compileConstructor($compiler); } $this->compileGetParent($compiler); - $this->compileDisplayHeader($compiler); - - $this->compileDisplayBody($compiler); - - $this->compileDisplayFooter($compiler); + $this->compileDisplay($compiler); $compiler->subcompile($this->getNode('blocks')); @@ -72,28 +108,38 @@ class Twig_Node_Module extends Twig_Node $this->compileDebugInfo($compiler); + $this->compileGetSource($compiler); + + $this->compileGetSourceContext($compiler); + $this->compileClassFooter($compiler); } protected function compileGetParent(Twig_Compiler $compiler) { - if (null === $this->getNode('parent')) { + if (!$this->hasNode('parent')) { return; } + $parent = $this->getNode('parent'); $compiler ->write("protected function doGetParent(array \$context)\n", "{\n") ->indent() - ->write("return ") + ->addDebugInfo($parent) + ->write('return ') ; - if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) { - $compiler->subcompile($this->getNode('parent')); + if ($parent instanceof Twig_Node_Expression_Constant) { + $compiler->subcompile($parent); } else { $compiler - ->raw("\$this->env->resolveTemplate(") - ->subcompile($this->getNode('parent')) - ->raw(")") + ->raw('$this->loadTemplate(') + ->subcompile($parent) + ->raw(', ') + ->repr($this->source->getName()) + ->raw(', ') + ->repr($parent->getTemplateLine()) + ->raw(')') ; } @@ -104,27 +150,13 @@ class Twig_Node_Module extends Twig_Node ; } - protected function compileDisplayBody(Twig_Compiler $compiler) - { - $compiler->subcompile($this->getNode('body')); - - if (null !== $this->getNode('parent')) { - if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) { - $compiler->write("\$this->parent"); - } else { - $compiler->write("\$this->getParent(\$context)"); - } - $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n"); - } - } - protected function compileClassHeader(Twig_Compiler $compiler) { $compiler ->write("\n\n") - // if the filename contains */, add a blank to avoid a PHP parse error - ->write("/* ".str_replace('*/', '* /', $this->getAttribute('filename'))." */\n") - ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index'))) + // if the template name contains */, add a blank to avoid a PHP parse error + ->write('/* '.str_replace('*/', '* /', $this->source->getName())." */\n") + ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->source->getName(), $this->getAttribute('index'))) ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass())) ->write("{\n") ->indent() @@ -136,17 +168,23 @@ class Twig_Node_Module extends Twig_Node $compiler ->write("public function __construct(Twig_Environment \$env)\n", "{\n") ->indent() + ->subcompile($this->getNode('constructor_start')) ->write("parent::__construct(\$env);\n\n") ; // parent - if (null === $this->getNode('parent')) { + if (!$this->hasNode('parent')) { $compiler->write("\$this->parent = false;\n\n"); - } elseif ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) { + } elseif (($parent = $this->getNode('parent')) && $parent instanceof Twig_Node_Expression_Constant) { $compiler - ->write("\$this->parent = \$this->env->loadTemplate(") - ->subcompile($this->getNode('parent')) - ->raw(");\n\n") + ->addDebugInfo($parent) + ->write('$this->parent = $this->loadTemplate(') + ->subcompile($parent) + ->raw(', ') + ->repr($this->source->getName()) + ->raw(', ') + ->repr($parent->getTemplateLine()) + ->raw(");\n") ; } @@ -170,11 +208,23 @@ class Twig_Node_Module extends Twig_Node foreach ($trait->getNode('targets') as $key => $value) { $compiler - ->write(sprintf("\$_trait_%s_blocks[", $i)) + ->write(sprintf('if (!isset($_trait_%s_blocks[', $i)) + ->string($key) + ->raw("])) {\n") + ->indent() + ->write("throw new Twig_Error_Runtime(sprintf('Block ") + ->string($key) + ->raw(' is not defined in trait ') + ->subcompile($trait->getNode('template')) + ->raw(".'));\n") + ->outdent() + ->write("}\n\n") + + ->write(sprintf('$_trait_%s_blocks[', $i)) ->subcompile($value) - ->raw(sprintf("] = \$_trait_%s_blocks[", $i)) + ->raw(sprintf('] = $_trait_%s_blocks[', $i)) ->string($key) - ->raw(sprintf("]; unset(\$_trait_%s_blocks[", $i)) + ->raw(sprintf(']; unset($_trait_%s_blocks[', $i)) ->string($key) ->raw("]);\n\n") ; @@ -187,9 +237,9 @@ class Twig_Node_Module extends Twig_Node ->indent() ; - for ($i = 0; $i < $countTraits; $i++) { + for ($i = 0; $i < $countTraits; ++$i) { $compiler - ->write(sprintf("\$_trait_%s_blocks".($i == $countTraits - 1 ? '' : ',')."\n", $i)) + ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i)) ; } @@ -235,55 +285,35 @@ 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() + ->subcompile($this->getNode('constructor_end')) ->write("}\n\n") ; } - protected function compileDisplayHeader(Twig_Compiler $compiler) + protected function compileDisplay(Twig_Compiler $compiler) { $compiler ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n") ->indent() + ->subcompile($this->getNode('display_start')) + ->subcompile($this->getNode('body')) ; - } - protected function compileDisplayFooter(Twig_Compiler $compiler) - { + if ($this->hasNode('parent')) { + $parent = $this->getNode('parent'); + $compiler->addDebugInfo($parent); + if ($parent instanceof Twig_Node_Expression_Constant) { + $compiler->write('$this->parent'); + } else { + $compiler->write('$this->getParent($context)'); + } + $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n"); + } + $compiler + ->subcompile($this->getNode('display_end')) ->outdent() ->write("}\n\n") ; @@ -292,6 +322,7 @@ class Twig_Node_Module extends Twig_Node protected function compileClassFooter(Twig_Compiler $compiler) { $compiler + ->subcompile($this->getNode('class_end')) ->outdent() ->write("}\n") ; @@ -308,7 +339,7 @@ class Twig_Node_Module extends Twig_Node ->write("public function getTemplateName()\n", "{\n") ->indent() ->write('return ') - ->repr($this->getAttribute('filename')) + ->repr($this->source->getName()) ->raw(";\n") ->outdent() ->write("}\n\n") @@ -324,7 +355,7 @@ class Twig_Node_Module extends Twig_Node // // Put another way, a template can be used as a trait if it // only contains blocks and use statements. - $traitable = null === $this->getNode('parent') && 0 === count($this->getNode('macros')); + $traitable = !$this->hasNode('parent') && 0 === count($this->getNode('macros')); if ($traitable) { if ($this->getNode('body') instanceof Twig_Node_Body) { $nodes = $this->getNode('body')->getNode(0); @@ -374,6 +405,37 @@ class Twig_Node_Module extends Twig_Node ->indent() ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true)))) ->outdent() + ->write("}\n\n") + ; + } + + protected function compileGetSource(Twig_Compiler $compiler) + { + $compiler + ->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n") + ->write("public function getSource()\n", "{\n") + ->indent() + ->write("@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);\n\n") + ->write('return $this->getSourceContext()->getCode();') + ->raw("\n") + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileGetSourceContext(Twig_Compiler $compiler) + { + $compiler + ->write("public function getSourceContext()\n", "{\n") + ->indent() + ->write('return new Twig_Source(') + ->string($compiler->getEnvironment()->isDebug() ? $this->source->getCode() : '') + ->raw(', ') + ->string($this->source->getName()) + ->raw(', ') + ->string($this->source->getPath()) + ->raw(");\n") + ->outdent() ->write("}\n") ; } @@ -382,22 +444,18 @@ class Twig_Node_Module extends Twig_Node { if ($node instanceof Twig_Node_Expression_Constant) { $compiler - ->write(sprintf("%s = \$this->env->loadTemplate(", $var)) + ->write(sprintf('%s = $this->loadTemplate(', $var)) ->subcompile($node) + ->raw(', ') + ->repr($node->getTemplateName()) + ->raw(', ') + ->repr($node->getTemplateLine()) ->raw(");\n") ; } else { - $compiler - ->write(sprintf("%s = ", $var)) - ->subcompile($node) - ->raw(";\n") - ->write(sprintf("if (!%s", $var)) - ->raw(" instanceof Twig_Template) {\n") - ->indent() - ->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var)) - ->outdent() - ->write("}\n") - ; + throw new LogicException('Trait templates can only be constant nodes.'); } } } + +class_alias('Twig_Node_Module', 'Twig\Node\ModuleNode', false); diff --git a/inc/lib/Twig/Node/Print.php b/inc/lib/Twig/Node/Print.php index b0c41d1d..374db89b 100644 --- a/inc/lib/Twig/Node/Print.php +++ b/inc/lib/Twig/Node/Print.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -22,11 +22,6 @@ class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface parent::__construct(array('expr' => $expr), array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -37,3 +32,5 @@ class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface ; } } + +class_alias('Twig_Node_Print', 'Twig\Node\PrintNode', false); diff --git a/inc/lib/Twig/Node/Sandbox.php b/inc/lib/Twig/Node/Sandbox.php index 8cf3ed44..44b30ab9 100644 --- a/inc/lib/Twig/Node/Sandbox.php +++ b/inc/lib/Twig/Node/Sandbox.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,16 +21,11 @@ class Twig_Node_Sandbox extends Twig_Node parent::__construct(array('body' => $body), array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) - ->write("\$sandbox = \$this->env->getExtension('sandbox');\n") + ->write("\$sandbox = \$this->env->getExtension('Twig_Extension_Sandbox');\n") ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n") ->indent() ->write("\$sandbox->enableSandbox();\n") @@ -45,3 +40,5 @@ class Twig_Node_Sandbox extends Twig_Node ; } } + +class_alias('Twig_Node_Sandbox', 'Twig\Node\SandboxNode', false); diff --git a/inc/lib/Twig/Node/SandboxedPrint.php b/inc/lib/Twig/Node/SandboxedPrint.php index 73dfaa96..a08f21f5 100644 --- a/inc/lib/Twig/Node/SandboxedPrint.php +++ b/inc/lib/Twig/Node/SandboxedPrint.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -21,21 +21,11 @@ */ class Twig_Node_SandboxedPrint extends Twig_Node_Print { - public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) - { - parent::__construct($expr, $lineno, $tag); - } - - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) - ->write('echo $this->env->getExtension(\'sandbox\')->ensureToStringAllowed(') + ->write('echo $this->env->getExtension(\'Twig_Extension_Sandbox\')->ensureToStringAllowed(') ->subcompile($this->getNode('expr')) ->raw(");\n") ; @@ -46,9 +36,9 @@ class Twig_Node_SandboxedPrint extends Twig_Node_Print * * This is mostly needed when another visitor adds filters (like the escaper one). * - * @param Twig_Node $node A Node + * @return Twig_Node */ - protected function removeNodeFilter($node) + protected function removeNodeFilter(Twig_Node $node) { if ($node instanceof Twig_Node_Expression_Filter) { return $this->removeNodeFilter($node->getNode('node')); @@ -57,3 +47,5 @@ class Twig_Node_SandboxedPrint extends Twig_Node_Print return $node; } } + +class_alias('Twig_Node_SandboxedPrint', 'Twig\Node\SandboxedPrintNode', false); diff --git a/inc/lib/Twig/Node/Set.php b/inc/lib/Twig/Node/Set.php index 4c9c16ce..6c6743ee 100644 --- a/inc/lib/Twig/Node/Set.php +++ b/inc/lib/Twig/Node/Set.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -14,7 +14,7 @@ * * @author Fabien Potencier <fabien@symfony.com> */ -class Twig_Node_Set extends Twig_Node +class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface { public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null) { @@ -30,17 +30,12 @@ class Twig_Node_Set extends Twig_Node $values = $this->getNode('values'); if ($values instanceof Twig_Node_Text) { - $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getLine())); + $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getTemplateLine())); $this->setAttribute('capture', false); } } } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler->addDebugInfo($this); @@ -99,3 +94,5 @@ class Twig_Node_Set extends Twig_Node $compiler->raw(";\n"); } } + +class_alias('Twig_Node_Set', 'Twig\Node\SetNode', false); diff --git a/inc/lib/Twig/Node/SetTemp.php b/inc/lib/Twig/Node/SetTemp.php index 3bdd1cb7..996fdcde 100644 --- a/inc/lib/Twig/Node/SetTemp.php +++ b/inc/lib/Twig/Node/SetTemp.php @@ -3,12 +3,15 @@ /* * This file is part of Twig. * - * (c) 2011 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ +/** + * @internal + */ class Twig_Node_SetTemp extends Twig_Node { public function __construct($name, $lineno) @@ -33,3 +36,5 @@ class Twig_Node_SetTemp extends Twig_Node ; } } + +class_alias('Twig_Node_SetTemp', 'Twig\Node\SetTempNode', false); diff --git a/inc/lib/Twig/Node/Spaceless.php b/inc/lib/Twig/Node/Spaceless.php index 7555fa0f..76f90cde 100644 --- a/inc/lib/Twig/Node/Spaceless.php +++ b/inc/lib/Twig/Node/Spaceless.php @@ -3,7 +3,7 @@ /* * This file is part of Twig. * - * (c) 2010 Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -23,11 +23,6 @@ class Twig_Node_Spaceless extends Twig_Node parent::__construct(array('body' => $body), array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -38,3 +33,5 @@ class Twig_Node_Spaceless extends Twig_Node ; } } + +class_alias('Twig_Node_Spaceless', 'Twig\Node\SpacelessNode', false); diff --git a/inc/lib/Twig/Node/Text.php b/inc/lib/Twig/Node/Text.php index 21bdcea1..f4577fee 100644 --- a/inc/lib/Twig/Node/Text.php +++ b/inc/lib/Twig/Node/Text.php @@ -3,8 +3,8 @@ /* * This file is part of Twig. * - * (c) 2009 Fabien Potencier - * (c) 2009 Armin Ronacher + * (c) Fabien Potencier + * (c) Armin Ronacher * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -22,11 +22,6 @@ class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface parent::__construct(array(), array('data' => $data), $lineno); } - /** - * Compiles the node to PHP. - * - * @param Twig_Compiler A Twig_Compiler instance - */ public function compile(Twig_Compiler $compiler) { $compiler @@ -37,3 +32,5 @@ class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface ; } } + +class_alias('Twig_Node_Text', 'Twig\Node\TextNode', false); diff --git a/inc/lib/Twig/Node/With.php b/inc/lib/Twig/Node/With.php new file mode 100644 index 00000000..2ab0ea5d --- /dev/null +++ b/inc/lib/Twig/Node/With.php @@ -0,0 +1,64 @@ +<?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. + */ + +/** + * Represents a nested "with" scope. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_With extends Twig_Node +{ + public function __construct(Twig_Node $body, Twig_Node $variables = null, $only = false, $lineno, $tag = null) + { + $nodes = array('body' => $body); + if (null !== $variables) { + $nodes['variables'] = $variables; + } + + parent::__construct($nodes, array('only' => (bool) $only), $lineno, $tag); + } + + public function compile(Twig_Compiler $compiler) + { + $compiler->addDebugInfo($this); + + if ($this->hasNode('variables')) { + $varsName = $compiler->getVarName(); + $compiler + ->write(sprintf('$%s = ', $varsName)) + ->subcompile($this->getNode('variables')) + ->raw(";\n") + ->write(sprintf("if (!is_array(\$%s)) {\n", $varsName)) + ->indent() + ->write("throw new Twig_Error_Runtime('Variables passed to the \"with\" tag must be a hash.');\n") + ->outdent() + ->write("}\n") + ; + + if ($this->getAttribute('only')) { + $compiler->write("\$context = array('_parent' => \$context);\n"); + } else { + $compiler->write("\$context['_parent'] = \$context;\n"); + } + + $compiler->write(sprintf("\$context = array_merge(\$context, \$%s);\n", $varsName)); + } else { + $compiler->write("\$context['_parent'] = \$context;\n"); + } + + $compiler + ->subcompile($this->getNode('body')) + ->write("\$context = \$context['_parent'];\n") + ; + } +} + +class_alias('Twig_Node_With', 'Twig\Node\WithNode', false); |
