Update Twig from 1.35.0 to 1.42.4 (PHP 5.5 is now required!)

This fixes some errors on PHP 7.4 and contains even more fixes
Also bumped PHP version to 5.5 as Twig requires it.
This commit is contained in:
slawkens
2020-02-15 05:41:38 +01:00
parent d9e449b6cf
commit 8021308822
414 changed files with 9276 additions and 5531 deletions

View File

@@ -9,6 +9,10 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents an autoescape node.
*
@@ -20,17 +24,17 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_AutoEscape extends Twig_Node
class AutoEscapeNode extends Node
{
public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape')
public function __construct($value, \Twig_NodeInterface $body, $lineno, $tag = 'autoescape')
{
parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag);
parent::__construct(['body' => $body], ['value' => $value], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler->subcompile($this->getNode('body'));
}
}
class_alias('Twig_Node_AutoEscape', 'Twig\Node\AutoEscapeNode', false);
class_alias('Twig\Node\AutoEscapeNode', 'Twig_Node_AutoEscape');

View File

@@ -10,23 +10,27 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents a block node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Block extends Twig_Node
class BlockNode extends Node
{
public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null)
public function __construct($name, \Twig_NodeInterface $body, $lineno, $tag = null)
{
parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag);
parent::__construct(['body' => $body], ['name' => $name], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n")
->write(sprintf("public function block_%s(\$context, array \$blocks = [])\n", $this->getAttribute('name')), "{\n")
->indent()
;
@@ -38,4 +42,4 @@ class Twig_Node_Block extends Twig_Node
}
}
class_alias('Twig_Node_Block', 'Twig\Node\BlockNode', false);
class_alias('Twig\Node\BlockNode', 'Twig_Node_Block');

View File

@@ -10,19 +10,23 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents a block call node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface
class BlockReferenceNode extends Node implements NodeOutputInterface
{
public function __construct($name, $lineno, $tag = null)
{
parent::__construct(array(), array('name' => $name), $lineno, $tag);
parent::__construct([], ['name' => $name], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
@@ -31,4 +35,4 @@ class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInter
}
}
class_alias('Twig_Node_BlockReference', 'Twig\Node\BlockReferenceNode', false);
class_alias('Twig\Node\BlockReferenceNode', 'Twig_Node_BlockReference');

View File

@@ -9,13 +9,15 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
/**
* Represents a body node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Body extends Twig_Node
class BodyNode extends Node
{
}
class_alias('Twig_Node_Body', 'Twig\Node\BodyNode', false);
class_alias('Twig\Node\BodyNode', 'Twig_Node_Body');

View File

@@ -9,10 +9,14 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_CheckSecurity extends Twig_Node
class CheckSecurityNode extends Node
{
protected $usedFilters;
protected $usedTags;
@@ -27,12 +31,12 @@ class Twig_Node_CheckSecurity extends Twig_Node
parent::__construct();
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$tags = $filters = $functions = array();
foreach (array('tags', 'filters', 'functions') as $type) {
$tags = $filters = $functions = [];
foreach (['tags', 'filters', 'functions'] as $type) {
foreach ($this->{'used'.ucfirst($type)} as $name => $node) {
if ($node instanceof Twig_Node) {
if ($node instanceof Node) {
${$type}[$name] = $node->getTemplateLine();
} else {
${$type}[$node] = null;
@@ -41,31 +45,32 @@ class Twig_Node_CheckSecurity extends Twig_Node
}
$compiler
->write("\$this->sandbox = \$this->env->getExtension('\Twig\Extension\SandboxExtension');\n")
->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")
->write("\$this->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")
->write(!$tags ? "[],\n" : "['".implode("', '", array_keys($tags))."'],\n")
->write(!$filters ? "[],\n" : "['".implode("', '", array_keys($filters))."'],\n")
->write(!$functions ? "[]\n" : "['".implode("', '", array_keys($functions))."']\n")
->outdent()
->write(");\n")
->outdent()
->write("} catch (Twig_Sandbox_SecurityError \$e) {\n")
->write("} catch (SecurityError \$e) {\n")
->indent()
->write("\$e->setSourceContext(\$this->getSourceContext());\n\n")
->write("if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n")
->write("if (\$e instanceof 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")
->write("} elseif (\$e instanceof 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")
->write("} elseif (\$e instanceof SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n")
->indent()
->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n")
->outdent()
@@ -77,4 +82,4 @@ class Twig_Node_CheckSecurity extends Twig_Node
}
}
class_alias('Twig_Node_CheckSecurity', 'Twig\Node\CheckSecurityNode', false);
class_alias('Twig\Node\CheckSecurityNode', 'Twig_Node_CheckSecurity');

View File

@@ -0,0 +1,42 @@
<?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.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
/**
* Checks if casting an expression to __toString() is allowed by the sandbox.
*
* For instance, when there is a simple Print statement, like {{ article }},
* and if the sandbox is enabled, we need to check that the __toString()
* method is allowed if 'article' is an object. The same goes for {{ article|upper }}
* or {{ random(article) }}
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class CheckToStringNode extends AbstractExpression
{
public function __construct(AbstractExpression $expr)
{
parent::__construct(['expr' => $expr], [], $expr->getTemplateLine(), $expr->getNodeTag());
}
public function compile(Compiler $compiler)
{
$compiler
->raw('$this->sandbox->ensureToStringAllowed(')
->subcompile($this->getNode('expr'))
->raw(')')
;
}
}

View File

@@ -0,0 +1,55 @@
<?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.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\ConstantExpression;
/**
* Represents a deprecated node.
*
* @author Yonel Ceruto <yonelceruto@gmail.com>
*/
class DeprecatedNode extends Node
{
public function __construct(AbstractExpression $expr, $lineno, $tag = null)
{
parent::__construct(['expr' => $expr], [], $lineno, $tag);
}
public function compile(Compiler $compiler)
{
$compiler->addDebugInfo($this);
$expr = $this->getNode('expr');
if ($expr instanceof ConstantExpression) {
$compiler->write('@trigger_error(')
->subcompile($expr);
} else {
$varName = $compiler->getVarName();
$compiler->write(sprintf('$%s = ', $varName))
->subcompile($expr)
->raw(";\n")
->write(sprintf('@trigger_error($%s', $varName));
}
$compiler
->raw('.')
->string(sprintf(' ("%s" at line %d).', $this->getTemplateName(), $this->getTemplateLine()))
->raw(", E_USER_DEPRECATED);\n")
;
}
}
class_alias('Twig\Node\DeprecatedNode', 'Twig_Node_Deprecated');

View File

@@ -9,19 +9,24 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
/**
* Represents a do node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Do extends Twig_Node
class DoNode extends Node
{
public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
public function __construct(AbstractExpression $expr, $lineno, $tag = null)
{
parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
parent::__construct(['expr' => $expr], [], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
@@ -32,4 +37,4 @@ class Twig_Node_Do extends Twig_Node
}
}
class_alias('Twig_Node_Do', 'Twig\Node\DoNode', false);
class_alias('Twig\Node\DoNode', 'Twig_Node_Do');

View File

@@ -9,17 +9,23 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\ConstantExpression;
/**
* Represents an embed node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Embed extends Twig_Node_Include
class EmbedNode extends IncludeNode
{
// 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($name, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
public function __construct($name, $index, AbstractExpression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
{
parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
parent::__construct(new ConstantExpression('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
$this->setAttribute('name', $name);
// to be removed in 2.0, used name instead
@@ -27,7 +33,7 @@ class Twig_Node_Embed extends Twig_Node_Include
$this->setAttribute('index', $index);
}
protected function addGetTemplate(Twig_Compiler $compiler)
protected function addGetTemplate(Compiler $compiler)
{
$compiler
->write('$this->loadTemplate(')
@@ -43,4 +49,4 @@ class Twig_Node_Embed extends Twig_Node_Include
}
}
class_alias('Twig_Node_Embed', 'Twig\Node\EmbedNode', false);
class_alias('Twig\Node\EmbedNode', 'Twig_Node_Embed');

View File

@@ -10,13 +10,17 @@
* file that was distributed with this source code.
*/
namespace Twig\Node\Expression;
use Twig\Node\Node;
/**
* Abstract class for all nodes that represents an expression.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class Twig_Node_Expression extends Twig_Node
abstract class AbstractExpression extends Node
{
}
class_alias('Twig_Node_Expression', 'Twig\Node\Expression\AbstractExpression', false);
class_alias('Twig\Node\Expression\AbstractExpression', 'Twig_Node_Expression');

View File

@@ -8,17 +8,22 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Array extends Twig_Node_Expression
namespace Twig\Node\Expression;
use Twig\Compiler;
class ArrayExpression extends AbstractExpression
{
protected $index;
public function __construct(array $elements, $lineno)
{
parent::__construct($elements, array(), $lineno);
parent::__construct($elements, [], $lineno);
$this->index = -1;
foreach ($this->getKeyValuePairs() as $pair) {
if ($pair['key'] instanceof Twig_Node_Expression_Constant && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) {
if ($pair['key'] instanceof ConstantExpression && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) {
$this->index = $pair['key']->getAttribute('value');
}
}
@@ -26,19 +31,19 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
public function getKeyValuePairs()
{
$pairs = array();
$pairs = [];
foreach (array_chunk($this->nodes, 2) as $pair) {
$pairs[] = array(
$pairs[] = [
'key' => $pair[0],
'value' => $pair[1],
);
];
}
return $pairs;
}
public function hasElement(Twig_Node_Expression $key)
public function hasElement(AbstractExpression $key)
{
foreach ($this->getKeyValuePairs() as $pair) {
// we compare the string representation of the keys
@@ -51,18 +56,18 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
return false;
}
public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null)
public function addElement(AbstractExpression $value, AbstractExpression $key = null)
{
if (null === $key) {
$key = new Twig_Node_Expression_Constant(++$this->index, $value->getTemplateLine());
$key = new ConstantExpression(++$this->index, $value->getTemplateLine());
}
array_push($this->nodes, $key, $value);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler->raw('array(');
$compiler->raw('[');
$first = true;
foreach ($this->getKeyValuePairs() as $pair) {
if (!$first) {
@@ -76,8 +81,8 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
->subcompile($pair['value'])
;
}
$compiler->raw(')');
$compiler->raw(']');
}
}
class_alias('Twig_Node_Expression_Array', 'Twig\Node\Expression\ArrayExpression', false);
class_alias('Twig\Node\Expression\ArrayExpression', 'Twig_Node_Expression_Array');

View File

@@ -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.
*/
namespace Twig\Node\Expression;
use Twig\Compiler;
use Twig\Node\Node;
/**
* Represents an arrow function.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ArrowFunctionExpression extends AbstractExpression
{
public function __construct(AbstractExpression $expr, Node $names, $lineno, $tag = null)
{
parent::__construct(['expr' => $expr, 'names' => $names], [], $lineno, $tag);
}
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->raw('function (')
;
foreach ($this->getNode('names') as $i => $name) {
if ($i) {
$compiler->raw(', ');
}
$compiler
->raw('$__')
->raw($name->getAttribute('name'))
->raw('__')
;
}
$compiler
->raw(') use ($context) { ')
;
foreach ($this->getNode('names') as $name) {
$compiler
->raw('$context["')
->raw($name->getAttribute('name'))
->raw('"] = $__')
->raw($name->getAttribute('name'))
->raw('__; ')
;
}
$compiler
->raw('return ')
->subcompile($this->getNode('expr'))
->raw('; }')
;
}
}

View File

@@ -10,9 +10,13 @@
* file that was distributed with this source code.
*/
class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
namespace Twig\Node\Expression;
use Twig\Compiler;
class AssignNameExpression extends NameExpression
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('$context[')
@@ -22,4 +26,4 @@ class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
}
}
class_alias('Twig_Node_Expression_AssignName', 'Twig\Node\Expression\AssignNameExpression', false);
class_alias('Twig\Node\Expression\AssignNameExpression', 'Twig_Node_Expression_AssignName');

View File

@@ -9,14 +9,20 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
abstract class AbstractBinary extends AbstractExpression
{
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
public function __construct(\Twig_NodeInterface $left, \Twig_NodeInterface $right, $lineno)
{
parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno);
parent::__construct(['left' => $left, 'right' => $right], [], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('(')
@@ -31,7 +37,7 @@ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
;
}
abstract public function operator(Twig_Compiler $compiler);
abstract public function operator(Compiler $compiler);
}
class_alias('Twig_Node_Expression_Binary', 'Twig\Node\Expression\Binary\AbstractBinary', false);
class_alias('Twig\Node\Expression\Binary\AbstractBinary', 'Twig_Node_Expression_Binary');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class AddBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('+');
}
}
class_alias('Twig_Node_Expression_Binary_Add', 'Twig\Node\Expression\Binary\AddBinary', false);
class_alias('Twig\Node\Expression\Binary\AddBinary', 'Twig_Node_Expression_Binary_Add');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class AndBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('&&');
}
}
class_alias('Twig_Node_Expression_Binary_And', 'Twig\Node\Expression\Binary\AndBinary', false);
class_alias('Twig\Node\Expression\Binary\AndBinary', 'Twig_Node_Expression_Binary_And');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class BitwiseAndBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('&');
}
}
class_alias('Twig_Node_Expression_Binary_BitwiseAnd', 'Twig\Node\Expression\Binary\BitwiseAndBinary', false);
class_alias('Twig\Node\Expression\Binary\BitwiseAndBinary', 'Twig_Node_Expression_Binary_BitwiseAnd');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class BitwiseOrBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('|');
}
}
class_alias('Twig_Node_Expression_Binary_BitwiseOr', 'Twig\Node\Expression\Binary\BitwiseOrBinary', false);
class_alias('Twig\Node\Expression\Binary\BitwiseOrBinary', 'Twig_Node_Expression_Binary_BitwiseOr');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class BitwiseXorBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('^');
}
}
class_alias('Twig_Node_Expression_Binary_BitwiseXor', 'Twig\Node\Expression\Binary\BitwiseXorBinary', false);
class_alias('Twig\Node\Expression\Binary\BitwiseXorBinary', 'Twig_Node_Expression_Binary_BitwiseXor');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class ConcatBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('.');
}
}
class_alias('Twig_Node_Expression_Binary_Concat', 'Twig\Node\Expression\Binary\ConcatBinary', false);
class_alias('Twig\Node\Expression\Binary\ConcatBinary', 'Twig_Node_Expression_Binary_Concat');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class DivBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('/');
}
}
class_alias('Twig_Node_Expression_Binary_Div', 'Twig\Node\Expression\Binary\DivBinary', false);
class_alias('Twig\Node\Expression\Binary\DivBinary', 'Twig_Node_Expression_Binary_Div');

View File

@@ -8,9 +8,14 @@
* 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
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class EndsWithBinary extends AbstractBinary
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$left = $compiler->getVarName();
$right = $compiler->getVarName();
@@ -23,10 +28,10 @@ class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary
;
}
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('');
}
}
class_alias('Twig_Node_Expression_Binary_EndsWith', 'Twig\Node\Expression\Binary\EndsWithBinary', false);
class_alias('Twig\Node\Expression\Binary\EndsWithBinary', 'Twig_Node_Expression_Binary_EndsWith');

View File

@@ -8,12 +8,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class EqualBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('==');
}
}
class_alias('Twig_Node_Expression_Binary_Equal', 'Twig\Node\Expression\Binary\EqualBinary', false);
class_alias('Twig\Node\Expression\Binary\EqualBinary', 'Twig_Node_Expression_Binary_Equal');

View File

@@ -8,19 +8,24 @@
* 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
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class FloorDivBinary extends AbstractBinary
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler->raw('(int) floor(');
parent::compile($compiler);
$compiler->raw(')');
}
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('/');
}
}
class_alias('Twig_Node_Expression_Binary_FloorDiv', 'Twig\Node\Expression\Binary\FloorDivBinary', false);
class_alias('Twig\Node\Expression\Binary\FloorDivBinary', 'Twig_Node_Expression_Binary_FloorDiv');

View File

@@ -8,12 +8,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class GreaterBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('>');
}
}
class_alias('Twig_Node_Expression_Binary_Greater', 'Twig\Node\Expression\Binary\GreaterBinary', false);
class_alias('Twig\Node\Expression\Binary\GreaterBinary', 'Twig_Node_Expression_Binary_Greater');

View File

@@ -1,19 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Binary
{
public function operator(Twig_Compiler $compiler)
{
return $compiler->raw('>=');
}
}
class_alias('Twig_Node_Expression_Binary_GreaterEqual', 'Twig\Node\Expression\Binary\GreaterEqualBinary', false);

View File

@@ -0,0 +1,24 @@
<?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.
*/
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class GreaterEqualBinary extends AbstractBinary
{
public function operator(Compiler $compiler)
{
return $compiler->raw('>=');
}
}
class_alias('Twig\Node\Expression\Binary\GreaterEqualBinary', 'Twig_Node_Expression_Binary_GreaterEqual');

View File

@@ -8,9 +8,14 @@
* 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
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class InBinary extends AbstractBinary
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('twig_in_filter(')
@@ -21,10 +26,10 @@ class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary
;
}
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('in');
}
}
class_alias('Twig_Node_Expression_Binary_In', 'Twig\Node\Expression\Binary\InBinary', false);
class_alias('Twig\Node\Expression\Binary\InBinary', 'Twig_Node_Expression_Binary_In');

View File

@@ -8,12 +8,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class LessBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('<');
}
}
class_alias('Twig_Node_Expression_Binary_Less', 'Twig\Node\Expression\Binary\LessBinary', false);
class_alias('Twig\Node\Expression\Binary\LessBinary', 'Twig_Node_Expression_Binary_Less');

View File

@@ -1,19 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary
{
public function operator(Twig_Compiler $compiler)
{
return $compiler->raw('<=');
}
}
class_alias('Twig_Node_Expression_Binary_LessEqual', 'Twig\Node\Expression\Binary\LessEqualBinary', false);

View File

@@ -0,0 +1,24 @@
<?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.
*/
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class LessEqualBinary extends AbstractBinary
{
public function operator(Compiler $compiler)
{
return $compiler->raw('<=');
}
}
class_alias('Twig\Node\Expression\Binary\LessEqualBinary', 'Twig_Node_Expression_Binary_LessEqual');

View File

@@ -8,9 +8,14 @@
* 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
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class MatchesBinary extends AbstractBinary
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('preg_match(')
@@ -21,10 +26,10 @@ class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary
;
}
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('');
}
}
class_alias('Twig_Node_Expression_Binary_Matches', 'Twig\Node\Expression\Binary\MatchesBinary', false);
class_alias('Twig\Node\Expression\Binary\MatchesBinary', 'Twig_Node_Expression_Binary_Matches');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class ModBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('%');
}
}
class_alias('Twig_Node_Expression_Binary_Mod', 'Twig\Node\Expression\Binary\ModBinary', false);
class_alias('Twig\Node\Expression\Binary\ModBinary', 'Twig_Node_Expression_Binary_Mod');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class MulBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('*');
}
}
class_alias('Twig_Node_Expression_Binary_Mul', 'Twig\Node\Expression\Binary\MulBinary', false);
class_alias('Twig\Node\Expression\Binary\MulBinary', 'Twig_Node_Expression_Binary_Mul');

View File

@@ -8,12 +8,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class NotEqualBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('!=');
}
}
class_alias('Twig_Node_Expression_Binary_NotEqual', 'Twig\Node\Expression\Binary\NotEqualBinary', false);
class_alias('Twig\Node\Expression\Binary\NotEqualBinary', 'Twig_Node_Expression_Binary_NotEqual');

View File

@@ -8,9 +8,14 @@
* 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
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class NotInBinary extends AbstractBinary
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('!twig_in_filter(')
@@ -21,10 +26,10 @@ class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary
;
}
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('not in');
}
}
class_alias('Twig_Node_Expression_Binary_NotIn', 'Twig\Node\Expression\Binary\NotInBinary', false);
class_alias('Twig\Node\Expression\Binary\NotInBinary', 'Twig_Node_Expression_Binary_NotIn');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class OrBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('||');
}
}
class_alias('Twig_Node_Expression_Binary_Or', 'Twig\Node\Expression\Binary\OrBinary', false);
class_alias('Twig\Node\Expression\Binary\OrBinary', 'Twig_Node_Expression_Binary_Or');

View File

@@ -8,11 +8,16 @@
* 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
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class PowerBinary extends AbstractBinary
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
if (PHP_VERSION_ID >= 50600) {
if (\PHP_VERSION_ID >= 50600) {
return parent::compile($compiler);
}
@@ -25,10 +30,10 @@ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
;
}
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('**');
}
}
class_alias('Twig_Node_Expression_Binary_Power', 'Twig\Node\Expression\Binary\PowerBinary', false);
class_alias('Twig\Node\Expression\Binary\PowerBinary', 'Twig_Node_Expression_Binary_Power');

View File

@@ -8,9 +8,14 @@
* 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
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class RangeBinary extends AbstractBinary
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('range(')
@@ -21,10 +26,10 @@ class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary
;
}
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('..');
}
}
class_alias('Twig_Node_Expression_Binary_Range', 'Twig\Node\Expression\Binary\RangeBinary', false);
class_alias('Twig\Node\Expression\Binary\RangeBinary', 'Twig_Node_Expression_Binary_Range');

View File

@@ -8,9 +8,14 @@
* 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
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class StartsWithBinary extends AbstractBinary
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$left = $compiler->getVarName();
$right = $compiler->getVarName();
@@ -23,10 +28,10 @@ class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary
;
}
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('');
}
}
class_alias('Twig_Node_Expression_Binary_StartsWith', 'Twig\Node\Expression\Binary\StartsWithBinary', false);
class_alias('Twig\Node\Expression\Binary\StartsWithBinary', 'Twig_Node_Expression_Binary_StartsWith');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary
namespace Twig\Node\Expression\Binary;
use Twig\Compiler;
class SubBinary extends AbstractBinary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
return $compiler->raw('-');
}
}
class_alias('Twig_Node_Expression_Binary_Sub', 'Twig\Node\Expression\Binary\SubBinary', false);
class_alias('Twig\Node\Expression\Binary\SubBinary', 'Twig_Node_Expression_Binary_Sub');

View File

@@ -10,33 +10,38 @@
* file that was distributed with this source code.
*/
namespace Twig\Node\Expression;
use Twig\Compiler;
use Twig\Node\Node;
/**
* Represents a block call node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
class BlockReferenceExpression extends AbstractExpression
{
/**
* @param Twig_Node|null $template
* @param Node|null $template
*/
public function __construct(Twig_NodeInterface $name, $template = null, $lineno, $tag = null)
public function __construct(\Twig_NodeInterface $name, $template = null, $lineno, $tag = null)
{
if (is_bool($template)) {
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);
$nodes = ['name' => $name];
if (null !== $template) {
$nodes['template'] = $template;
}
parent::__construct($nodes, array('is_defined_test' => false, 'output' => false), $lineno, $tag);
parent::__construct($nodes, ['is_defined_test' => false, 'output' => false], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
if ($this->getAttribute('is_defined_test')) {
$this->compileTemplateCall($compiler, 'hasBlock');
@@ -53,7 +58,7 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
}
}
private function compileTemplateCall(Twig_Compiler $compiler, $method)
private function compileTemplateCall(Compiler $compiler, $method)
{
if (!$this->hasNode('template')) {
$compiler->write('$this');
@@ -75,7 +80,7 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
return $compiler;
}
private function compileBlockArguments(Twig_Compiler $compiler)
private function compileBlockArguments(Compiler $compiler)
{
$compiler
->raw('(')
@@ -90,4 +95,4 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
}
}
class_alias('Twig_Node_Expression_BlockReference', 'Twig\Node\Expression\BlockReferenceExpression', false);
class_alias('Twig\Node\Expression\BlockReferenceExpression', 'Twig_Node_Expression_BlockReference');

View File

@@ -8,46 +8,56 @@
* 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
namespace Twig\Node\Expression;
use Twig\Compiler;
use Twig\Error\SyntaxError;
use Twig\Extension\ExtensionInterface;
use Twig\Node\Node;
abstract class CallExpression extends AbstractExpression
{
private $reflector;
protected function compileCallable(Twig_Compiler $compiler)
protected function compileCallable(Compiler $compiler)
{
$closingParenthesis = false;
$isArray = false;
if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) {
if (is_string($callable) && false === strpos($callable, '::')) {
if (\is_string($callable) && false === strpos($callable, '::')) {
$compiler->raw($callable);
} else {
list($r, $callable) = $this->reflectCallable($callable);
if ($r instanceof ReflectionMethod && is_string($callable[0])) {
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]));
} elseif ($r instanceof \ReflectionMethod && $callable[0] instanceof 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')));
$compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), ', $type, $this->getAttribute('name')));
$closingParenthesis = true;
$isArray = true;
}
}
} else {
$compiler->raw($this->getAttribute('thing')->compile());
}
$this->compileArguments($compiler);
$this->compileArguments($compiler, $isArray);
if ($closingParenthesis) {
$compiler->raw(')');
}
}
protected function compileArguments(Twig_Compiler $compiler)
protected function compileArguments(Compiler $compiler, $isArray = false)
{
$compiler->raw('(');
$compiler->raw($isArray ? '[' : '(');
$first = true;
@@ -96,7 +106,7 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
}
}
$compiler->raw(')');
$compiler->raw($isArray ? ']' : ')');
}
protected function getArguments($callable, $arguments)
@@ -104,14 +114,14 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
$callType = $this->getAttribute('type');
$callName = $this->getAttribute('name');
$parameters = array();
$parameters = [];
$named = false;
foreach ($arguments as $name => $node) {
if (!is_int($name)) {
if (!\is_int($name)) {
$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".', $callType, $callName));
throw new SyntaxError(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName), $this->getTemplateLine(), $this->getSourceContext());
}
$parameters[$name] = $node;
@@ -129,42 +139,42 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
$message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
}
throw new LogicException($message);
throw new \LogicException($message);
}
$callableParameters = $this->getCallableParameters($callable, $isVariadic);
$arguments = array();
$names = array();
$missingArguments = array();
$optionalArguments = array();
$arguments = [];
$names = [];
$missingArguments = [];
$optionalArguments = [];
$pos = 0;
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, $callType, $callName));
if (\array_key_exists($name, $parameters)) {
if (\array_key_exists($pos, $parameters)) {
throw new SyntaxError(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext());
}
if (count($missingArguments)) {
throw new Twig_Error_Syntax(sprintf(
if (\count($missingArguments)) {
throw new SyntaxError(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))
);
$name, $callType, $callName, implode(', ', $names), \count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments)
), $this->getTemplateLine(), $this->getSourceContext());
}
$arguments = array_merge($arguments, $optionalArguments);
$arguments[] = $parameters[$name];
unset($parameters[$name]);
$optionalArguments = array();
} elseif (array_key_exists($pos, $parameters)) {
$optionalArguments = [];
} elseif (\array_key_exists($pos, $parameters)) {
$arguments = array_merge($arguments, $optionalArguments);
$arguments[] = $parameters[$pos];
unset($parameters[$pos]);
$optionalArguments = array();
$optionalArguments = [];
++$pos;
} elseif ($callableParameter->isDefaultValueAvailable()) {
$optionalArguments[] = new Twig_Node_Expression_Constant($callableParameter->getDefaultValue(), -1);
$optionalArguments[] = new ConstantExpression($callableParameter->getDefaultValue(), -1);
} elseif ($callableParameter->isOptional()) {
if (empty($parameters)) {
break;
@@ -172,17 +182,17 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
$missingArguments[] = $name;
}
} else {
throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName));
throw new SyntaxError(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext());
}
}
if ($isVariadic) {
$arbitraryArguments = new Twig_Node_Expression_Array(array(), -1);
$arbitraryArguments = new ArrayExpression([], -1);
foreach ($parameters as $key => $value) {
if (is_int($key)) {
if (\is_int($key)) {
$arbitraryArguments->addElement($value);
} else {
$arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1));
$arbitraryArguments->addElement($value, new ConstantExpression($key, -1));
}
unset($parameters[$key]);
}
@@ -196,16 +206,20 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
if (!empty($parameters)) {
$unknownParameter = null;
foreach ($parameters as $parameter) {
if ($parameter instanceof Twig_Node) {
if ($parameter instanceof 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);
throw new SyntaxError(
sprintf(
'Unknown argument%s "%s" for %s "%s(%s)".',
\count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)
),
$unknownParameter ? $unknownParameter->getTemplateLine() : $this->getTemplateLine(),
$unknownParameter ? $unknownParameter->getSourceContext() : $this->getSourceContext()
);
}
return $arguments;
@@ -213,14 +227,14 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
protected function normalizeName($name)
{
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], $name));
}
private function getCallableParameters($callable, $isVariadic)
{
list($r) = $this->reflectCallable($callable);
if (null === $r) {
return array();
return [];
}
$parameters = $r->getParameters();
@@ -240,15 +254,15 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
}
if ($isVariadic) {
$argument = end($parameters);
if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) {
if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && [] === $argument->getDefaultValue()) {
array_pop($parameters);
} else {
$callableName = $r->name;
if ($r instanceof ReflectionMethod) {
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')));
throw new \LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = []".', $callableName, $this->getAttribute('type'), $this->getAttribute('name')));
}
}
@@ -261,31 +275,31 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
return $this->reflector;
}
if (is_array($callable)) {
if (\is_array($callable)) {
if (!method_exists($callable[0], $callable[1])) {
// __call()
return array(null, array());
return [null, []];
}
$r = new ReflectionMethod($callable[0], $callable[1]);
} elseif (is_object($callable) && !$callable instanceof Closure) {
$r = new ReflectionObject($callable);
$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, '::')) {
$callable = [$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());
return [null, []];
}
$r = new ReflectionMethod($callable);
$callable = array($class, $method);
$r = new \ReflectionMethod($callable);
$callable = [$class, $method];
} else {
$r = new ReflectionFunction($callable);
$r = new \ReflectionFunction($callable);
}
return $this->reflector = array($r, $callable);
return $this->reflector = [$r, $callable];
}
}
class_alias('Twig_Node_Expression_Call', 'Twig\Node\Expression\CallExpression', false);
class_alias('Twig\Node\Expression\CallExpression', 'Twig_Node_Expression_Call');

View File

@@ -9,14 +9,19 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Conditional extends Twig_Node_Expression
namespace Twig\Node\Expression;
use Twig\Compiler;
class ConditionalExpression extends AbstractExpression
{
public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno)
public function __construct(AbstractExpression $expr1, AbstractExpression $expr2, AbstractExpression $expr3, $lineno)
{
parent::__construct(array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno);
parent::__construct(['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3], [], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('((')
@@ -30,4 +35,4 @@ class Twig_Node_Expression_Conditional extends Twig_Node_Expression
}
}
class_alias('Twig_Node_Expression_Conditional', 'Twig\Node\Expression\ConditionalExpression', false);
class_alias('Twig\Node\Expression\ConditionalExpression', 'Twig_Node_Expression_Conditional');

View File

@@ -9,17 +9,22 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Constant extends Twig_Node_Expression
namespace Twig\Node\Expression;
use Twig\Compiler;
class ConstantExpression extends AbstractExpression
{
public function __construct($value, $lineno)
{
parent::__construct(array(), array('value' => $value), $lineno);
parent::__construct([], ['value' => $value], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler->repr($this->getAttribute('value'));
}
}
class_alias('Twig_Node_Expression_Constant', 'Twig\Node\Expression\ConstantExpression', false);
class_alias('Twig\Node\Expression\ConstantExpression', 'Twig_Node_Expression_Constant');

View File

@@ -1,32 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
@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
{
public function __construct($name, $lineno, $tag = null)
{
parent::__construct(array(), array('name' => $name), $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
{
$compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name')));
}
}

View File

@@ -1,45 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Returns the value or the default value when it is undefined or empty.
*
* <pre>
* {{ var.foo|default('foo item on var is not defined') }}
* </pre>
*
* @author Fabien Potencier <fabien@symfony.com>
*/
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->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->getTemplateLine());
$false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getTemplateLine());
$node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getTemplateLine());
} else {
$node = $default;
}
parent::__construct($node, $filterName, $arguments, $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
{
$compiler->subcompile($this->getNode('node'));
}
}
class_alias('Twig_Node_Expression_Filter_Default', 'Twig\Node\Expression\Filter\DefaultFilter', false);

View File

@@ -0,0 +1,54 @@
<?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.
*/
namespace Twig\Node\Expression\Filter;
use Twig\Compiler;
use Twig\Node\Expression\ConditionalExpression;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Expression\FilterExpression;
use Twig\Node\Expression\GetAttrExpression;
use Twig\Node\Expression\NameExpression;
use Twig\Node\Expression\Test\DefinedTest;
use Twig\Node\Node;
/**
* Returns the value or the default value when it is undefined or empty.
*
* {{ var.foo|default('foo item on var is not defined') }}
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class DefaultFilter extends FilterExpression
{
public function __construct(\Twig_NodeInterface $node, ConstantExpression $filterName, \Twig_NodeInterface $arguments, $lineno, $tag = null)
{
$default = new FilterExpression($node, new ConstantExpression('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine());
if ('default' === $filterName->getAttribute('value') && ($node instanceof NameExpression || $node instanceof GetAttrExpression)) {
$test = new DefinedTest(clone $node, 'defined', new Node(), $node->getTemplateLine());
$false = \count($arguments) ? $arguments->getNode(0) : new ConstantExpression('', $node->getTemplateLine());
$node = new ConditionalExpression($test, $default, $false, $node->getTemplateLine());
} else {
$node = $default;
}
parent::__construct($node, $filterName, $arguments, $lineno, $tag);
}
public function compile(Compiler $compiler)
{
$compiler->subcompile($this->getNode('node'));
}
}
class_alias('Twig\Node\Expression\Filter\DefaultFilter', 'Twig_Node_Expression_Filter_Default');

View File

@@ -9,14 +9,20 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
namespace Twig\Node\Expression;
use Twig\Compiler;
use Twig\TwigFilter;
class FilterExpression extends CallExpression
{
public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
public function __construct(\Twig_NodeInterface $node, ConstantExpression $filterName, \Twig_NodeInterface $arguments, $lineno, $tag = null)
{
parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag);
parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], [], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$name = $this->getNode('filter')->getAttribute('value');
$filter = $compiler->getEnvironment()->getFilter($name);
@@ -27,10 +33,10 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
$this->setAttribute('needs_environment', $filter->needsEnvironment());
$this->setAttribute('needs_context', $filter->needsContext());
$this->setAttribute('arguments', $filter->getArguments());
if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
if ($filter instanceof \Twig_FilterCallableInterface || $filter instanceof TwigFilter) {
$this->setAttribute('callable', $filter->getCallable());
}
if ($filter instanceof Twig_SimpleFilter) {
if ($filter instanceof TwigFilter) {
$this->setAttribute('is_variadic', $filter->isVariadic());
}
@@ -38,4 +44,4 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
}
}
class_alias('Twig_Node_Expression_Filter', 'Twig\Node\Expression\FilterExpression', false);
class_alias('Twig\Node\Expression\FilterExpression', 'Twig_Node_Expression_Filter');

View File

@@ -8,14 +8,20 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
namespace Twig\Node\Expression;
use Twig\Compiler;
use Twig\TwigFunction;
class FunctionExpression extends CallExpression
{
public function __construct($name, Twig_NodeInterface $arguments, $lineno)
public function __construct($name, \Twig_NodeInterface $arguments, $lineno)
{
parent::__construct(array('arguments' => $arguments), array('name' => $name, 'is_defined_test' => false), $lineno);
parent::__construct(['arguments' => $arguments], ['name' => $name, 'is_defined_test' => false], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$name = $this->getAttribute('name');
$function = $compiler->getEnvironment()->getFunction($name);
@@ -26,7 +32,7 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
$this->setAttribute('needs_environment', $function->needsEnvironment());
$this->setAttribute('needs_context', $function->needsContext());
$this->setAttribute('arguments', $function->getArguments());
if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
if ($function instanceof \Twig_FunctionCallableInterface || $function instanceof TwigFunction) {
$callable = $function->getCallable();
if ('constant' === $name && $this->getAttribute('is_defined_test')) {
$callable = 'twig_constant_is_defined';
@@ -34,7 +40,7 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
$this->setAttribute('callable', $callable);
}
if ($function instanceof Twig_SimpleFunction) {
if ($function instanceof TwigFunction) {
$this->setAttribute('is_variadic', $function->isVariadic());
}
@@ -42,4 +48,4 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
}
}
class_alias('Twig_Node_Expression_Function', 'Twig\Node\Expression\FunctionExpression', false);
class_alias('Twig\Node\Expression\FunctionExpression', 'Twig_Node_Expression_Function');

View File

@@ -9,25 +9,31 @@
* 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
namespace Twig\Node\Expression;
use Twig\Compiler;
use Twig\Template;
class GetAttrExpression extends AbstractExpression
{
public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression $arguments = null, $type, $lineno)
public function __construct(AbstractExpression $node, AbstractExpression $attribute, AbstractExpression $arguments = null, $type, $lineno)
{
$nodes = array('node' => $node, 'attribute' => $attribute);
$nodes = ['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);
parent::__construct($nodes, ['type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(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')) {
if (\function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) {
$compiler->raw('twig_template_get_attributes($this, ');
} else {
$compiler->raw('$this->getAttribute(');
@@ -44,14 +50,14 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
// 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');
$needSecond = $needThird || Template::ANY_CALL !== $this->getAttribute('type');
$needFirst = $needSecond || $this->hasNode('arguments');
if ($needFirst) {
if ($this->hasNode('arguments')) {
$compiler->raw(', ')->subcompile($this->getNode('arguments'));
} else {
$compiler->raw(', array()');
$compiler->raw(', []');
}
}
@@ -71,4 +77,4 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
}
}
class_alias('Twig_Node_Expression_GetAttr', 'Twig\Node\Expression\GetAttrExpression', false);
class_alias('Twig\Node\Expression\GetAttrExpression', 'Twig_Node_Expression_GetAttr');

View File

@@ -0,0 +1,35 @@
<?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.
*/
namespace Twig\Node\Expression;
use Twig\Compiler;
use Twig\Node\Node;
/**
* @internal
*/
final class InlinePrint extends AbstractExpression
{
public function __construct(Node $node, $lineno)
{
parent::__construct(['node' => $node], [], $lineno);
}
public function compile(Compiler $compiler)
{
$compiler
->raw('print (')
->subcompile($this->getNode('node'))
->raw(')')
;
}
}

View File

@@ -8,18 +8,23 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_MethodCall extends Twig_Node_Expression
{
public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno)
{
parent::__construct(array('node' => $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno);
if ($node instanceof Twig_Node_Expression_Name) {
namespace Twig\Node\Expression;
use Twig\Compiler;
class MethodCallExpression extends AbstractExpression
{
public function __construct(AbstractExpression $node, $method, ArrayExpression $arguments, $lineno)
{
parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false], $lineno);
if ($node instanceof NameExpression) {
$node->setAttribute('always_defined', true);
}
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->subcompile($this->getNode('node'))
@@ -40,4 +45,4 @@ class Twig_Node_Expression_MethodCall extends Twig_Node_Expression
}
}
class_alias('Twig_Node_Expression_MethodCall', 'Twig\Node\Expression\MethodCallExpression', false);
class_alias('Twig\Node\Expression\MethodCallExpression', 'Twig_Node_Expression_MethodCall');

View File

@@ -9,20 +9,25 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Name extends Twig_Node_Expression
namespace Twig\Node\Expression;
use Twig\Compiler;
class NameExpression extends AbstractExpression
{
protected $specialVars = array(
protected $specialVars = [
'_self' => '$this',
'_context' => '$context',
'_charset' => '$this->env->getCharset()',
);
];
public function __construct($name, $lineno)
{
parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false), $lineno);
parent::__construct([], ['name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$name = $this->getAttribute('name');
@@ -31,8 +36,20 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
if ($this->getAttribute('is_defined_test')) {
if ($this->isSpecial()) {
$compiler->repr(true);
} elseif (\PHP_VERSION_ID >= 700400) {
$compiler
->raw('array_key_exists(')
->string($name)
->raw(', $context)')
;
} else {
$compiler->raw('array_key_exists(')->repr($name)->raw(', $context)');
$compiler
->raw('(isset($context[')
->string($name)
->raw(']) || array_key_exists(')
->string($name)
->raw(', $context))')
;
}
} elseif ($this->isSpecial()) {
$compiler->raw($this->specialVars[$name]);
@@ -43,7 +60,7 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
->raw(']')
;
} else {
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
// use PHP 7 null coalescing operator
$compiler
->raw('($context[')
@@ -56,7 +73,7 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
} else {
$compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
}
} elseif (PHP_VERSION_ID >= 50400) {
} elseif (\PHP_VERSION_ID >= 50400) {
// PHP 5.4 ternary operator performance was optimized
$compiler
->raw('(isset($context[')
@@ -99,4 +116,4 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
}
}
class_alias('Twig_Node_Expression_Name', 'Twig\Node\Expression\NameExpression', false);
class_alias('Twig\Node\Expression\NameExpression', 'Twig_Node_Expression_Name');

View File

@@ -1,48 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_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);

View File

@@ -0,0 +1,62 @@
<?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.
*/
namespace Twig\Node\Expression;
use Twig\Compiler;
use Twig\Node\Expression\Binary\AndBinary;
use Twig\Node\Expression\Test\DefinedTest;
use Twig\Node\Expression\Test\NullTest;
use Twig\Node\Expression\Unary\NotUnary;
use Twig\Node\Node;
class NullCoalesceExpression extends ConditionalExpression
{
public function __construct(\Twig_NodeInterface $left, \Twig_NodeInterface $right, $lineno)
{
$test = new DefinedTest(clone $left, 'defined', new Node(), $left->getTemplateLine());
// for "block()", we don't need the null test as the return value is always a string
if (!$left instanceof BlockReferenceExpression) {
$test = new AndBinary(
$test,
new NotUnary(new NullTest($left, 'null', new Node(), $left->getTemplateLine()), $left->getTemplateLine()),
$left->getTemplateLine()
);
}
parent::__construct($test, $left, $right, $lineno);
}
public function compile(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 NameExpression) {
$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\NullCoalesceExpression', 'Twig_Node_Expression_NullCoalesce');

View File

@@ -10,19 +10,23 @@
* file that was distributed with this source code.
*/
namespace Twig\Node\Expression;
use Twig\Compiler;
/**
* Represents a parent node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Expression_Parent extends Twig_Node_Expression
class ParentExpression extends AbstractExpression
{
public function __construct($name, $lineno, $tag = null)
{
parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag);
parent::__construct([], ['output' => false, 'name' => $name], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
if ($this->getAttribute('output')) {
$compiler
@@ -41,4 +45,4 @@ class Twig_Node_Expression_Parent extends Twig_Node_Expression
}
}
class_alias('Twig_Node_Expression_Parent', 'Twig\Node\Expression\ParentExpression', false);
class_alias('Twig\Node\Expression\ParentExpression', 'Twig_Node_Expression_Parent');

View File

@@ -8,14 +8,19 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_TempName extends Twig_Node_Expression
namespace Twig\Node\Expression;
use Twig\Compiler;
class TempNameExpression extends AbstractExpression
{
public function __construct($name, $lineno)
{
parent::__construct(array(), array('name' => $name), $lineno);
parent::__construct([], ['name' => $name], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('$_')
@@ -25,4 +30,4 @@ class Twig_Node_Expression_TempName extends Twig_Node_Expression
}
}
class_alias('Twig_Node_Expression_TempName', 'Twig\Node\Expression\TempNameExpression', false);
class_alias('Twig\Node\Expression\TempNameExpression', 'Twig_Node_Expression_TempName');

View File

@@ -9,20 +9,23 @@
* file that was distributed with this source code.
*/
namespace Twig\Node\Expression\Test;
use Twig\Compiler;
use Twig\Node\Expression\TestExpression;
/**
* Checks if a variable is the exact same value as a constant.
*
* <pre>
* {% if post.status is constant('Post::PUBLISHED') %}
* the status attribute is exactly the same as Post::PUBLISHED
* {% endif %}
* </pre>
* {% if post.status is constant('Post::PUBLISHED') %}
* the status attribute is exactly the same as Post::PUBLISHED
* {% endif %}
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
class ConstantTest extends TestExpression
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('(')
@@ -45,4 +48,4 @@ class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
}
}
class_alias('Twig_Node_Expression_Test_Constant', 'Twig\Node\Expression\Test\ConstantTest', false);
class_alias('Twig\Node\Expression\Test\ConstantTest', 'Twig_Node_Expression_Test_Constant');

View File

@@ -1,61 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Checks if a variable is defined in the current context.
*
* <pre>
* {# defined works with variable names and variable attributes #}
* {% if foo is defined %}
* {# ... #}
* {% endif %}
* </pre>
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
{
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $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->getTemplateLine());
}
parent::__construct($node, $name, $arguments, $lineno);
}
protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node)
{
$node->setAttribute('ignore_strict_check', true);
if ($node->getNode('node') instanceof Twig_Node_Expression_GetAttr) {
$this->changeIgnoreStrictCheck($node->getNode('node'));
}
}
public function compile(Twig_Compiler $compiler)
{
$compiler->subcompile($this->getNode('node'));
}
}
class_alias('Twig_Node_Expression_Test_Defined', 'Twig\Node\Expression\Test\DefinedTest', false);

View File

@@ -0,0 +1,71 @@
<?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.
*/
namespace Twig\Node\Expression\Test;
use Twig\Compiler;
use Twig\Error\SyntaxError;
use Twig\Node\Expression\ArrayExpression;
use Twig\Node\Expression\BlockReferenceExpression;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Expression\FunctionExpression;
use Twig\Node\Expression\GetAttrExpression;
use Twig\Node\Expression\NameExpression;
use Twig\Node\Expression\TestExpression;
/**
* Checks if a variable is defined in the current context.
*
* {# defined works with variable names and variable attributes #}
* {% if foo is defined %}
* {# ... #}
* {% endif %}
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class DefinedTest extends TestExpression
{
public function __construct(\Twig_NodeInterface $node, $name, \Twig_NodeInterface $arguments = null, $lineno)
{
if ($node instanceof NameExpression) {
$node->setAttribute('is_defined_test', true);
} elseif ($node instanceof GetAttrExpression) {
$node->setAttribute('is_defined_test', true);
$this->changeIgnoreStrictCheck($node);
} elseif ($node instanceof BlockReferenceExpression) {
$node->setAttribute('is_defined_test', true);
} elseif ($node instanceof FunctionExpression && 'constant' === $node->getAttribute('name')) {
$node->setAttribute('is_defined_test', true);
} elseif ($node instanceof ConstantExpression || $node instanceof ArrayExpression) {
$node = new ConstantExpression(true, $node->getTemplateLine());
} else {
throw new SyntaxError('The "defined" test only works with simple variables.', $lineno);
}
parent::__construct($node, $name, $arguments, $lineno);
}
protected function changeIgnoreStrictCheck(GetAttrExpression $node)
{
$node->setAttribute('ignore_strict_check', true);
if ($node->getNode('node') instanceof GetAttrExpression) {
$this->changeIgnoreStrictCheck($node->getNode('node'));
}
}
public function compile(Compiler $compiler)
{
$compiler->subcompile($this->getNode('node'));
}
}
class_alias('Twig\Node\Expression\Test\DefinedTest', 'Twig_Node_Expression_Test_Defined');

View File

@@ -9,18 +9,21 @@
* file that was distributed with this source code.
*/
namespace Twig\Node\Expression\Test;
use Twig\Compiler;
use Twig\Node\Expression\TestExpression;
/**
* Checks if a variable is divisible by a number.
*
* <pre>
* {% if loop.index is divisible by(3) %}
* </pre>
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test
class DivisiblebyTest extends TestExpression
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('(0 == ')
@@ -32,4 +35,4 @@ class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test
}
}
class_alias('Twig_Node_Expression_Test_Divisibleby', 'Twig\Node\Expression\Test\DivisiblebyTest', false);
class_alias('Twig\Node\Expression\Test\DivisiblebyTest', 'Twig_Node_Expression_Test_Divisibleby');

View File

@@ -9,18 +9,21 @@
* file that was distributed with this source code.
*/
namespace Twig\Node\Expression\Test;
use Twig\Compiler;
use Twig\Node\Expression\TestExpression;
/**
* Checks if a number is even.
*
* <pre>
* {{ var is even }}
* </pre>
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
class EvenTest extends TestExpression
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('(')
@@ -31,4 +34,4 @@ class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
}
}
class_alias('Twig_Node_Expression_Test_Even', 'Twig\Node\Expression\Test\EvenTest', false);
class_alias('Twig\Node\Expression\Test\EvenTest', 'Twig_Node_Expression_Test_Even');

View File

@@ -9,18 +9,21 @@
* file that was distributed with this source code.
*/
namespace Twig\Node\Expression\Test;
use Twig\Compiler;
use Twig\Node\Expression\TestExpression;
/**
* Checks that a variable is null.
*
* <pre>
* {{ var is none }}
* </pre>
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
class NullTest extends TestExpression
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('(null === ')
@@ -30,4 +33,4 @@ class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
}
}
class_alias('Twig_Node_Expression_Test_Null', 'Twig\Node\Expression\Test\NullTest', false);
class_alias('Twig\Node\Expression\Test\NullTest', 'Twig_Node_Expression_Test_Null');

View File

@@ -9,18 +9,21 @@
* file that was distributed with this source code.
*/
namespace Twig\Node\Expression\Test;
use Twig\Compiler;
use Twig\Node\Expression\TestExpression;
/**
* Checks if a number is odd.
*
* <pre>
* {{ var is odd }}
* </pre>
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
class OddTest extends TestExpression
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('(')
@@ -31,4 +34,4 @@ class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
}
}
class_alias('Twig_Node_Expression_Test_Odd', 'Twig\Node\Expression\Test\OddTest', false);
class_alias('Twig\Node\Expression\Test\OddTest', 'Twig_Node_Expression_Test_Odd');

View File

@@ -9,14 +9,19 @@
* file that was distributed with this source code.
*/
namespace Twig\Node\Expression\Test;
use Twig\Compiler;
use Twig\Node\Expression\TestExpression;
/**
* Checks if a variable is the same as another one (=== in PHP).
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test
class SameasTest extends TestExpression
{
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->raw('(')
@@ -28,4 +33,4 @@ class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test
}
}
class_alias('Twig_Node_Expression_Test_Sameas', 'Twig\Node\Expression\Test\SameasTest', false);
class_alias('Twig\Node\Expression\Test\SameasTest', 'Twig_Node_Expression_Test_Sameas');

View File

@@ -8,19 +8,25 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
namespace Twig\Node\Expression;
use Twig\Compiler;
use Twig\TwigTest;
class TestExpression extends CallExpression
{
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
public function __construct(\Twig_NodeInterface $node, $name, \Twig_NodeInterface $arguments = null, $lineno)
{
$nodes = array('node' => $node);
$nodes = ['node' => $node];
if (null !== $arguments) {
$nodes['arguments'] = $arguments;
}
parent::__construct($nodes, array('name' => $name), $lineno);
parent::__construct($nodes, ['name' => $name], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$name = $this->getAttribute('name');
$test = $compiler->getEnvironment()->getTest($name);
@@ -28,10 +34,13 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
$this->setAttribute('name', $name);
$this->setAttribute('type', 'test');
$this->setAttribute('thing', $test);
if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
if ($test instanceof TwigTest) {
$this->setAttribute('arguments', $test->getArguments());
}
if ($test instanceof \Twig_TestCallableInterface || $test instanceof TwigTest) {
$this->setAttribute('callable', $test->getCallable());
}
if ($test instanceof Twig_SimpleTest) {
if ($test instanceof TwigTest) {
$this->setAttribute('is_variadic', $test->isVariadic());
}
@@ -39,4 +48,4 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
}
}
class_alias('Twig_Node_Expression_Test', 'Twig\Node\Expression\TestExpression', false);
class_alias('Twig\Node\Expression\TestExpression', 'Twig_Node_Expression_Test');

View File

@@ -1,29 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (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.
*/
abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression
{
public function __construct(Twig_NodeInterface $node, $lineno)
{
parent::__construct(array('node' => $node), array(), $lineno);
}
public function compile(Twig_Compiler $compiler)
{
$compiler->raw(' ');
$this->operator($compiler);
$compiler->subcompile($this->getNode('node'));
}
abstract public function operator(Twig_Compiler $compiler);
}
class_alias('Twig_Node_Expression_Unary', 'Twig\Node\Expression\Unary\AbstractUnary', false);

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of Twig.
*
* (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.
*/
namespace Twig\Node\Expression\Unary;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
abstract class AbstractUnary extends AbstractExpression
{
public function __construct(\Twig_NodeInterface $node, $lineno)
{
parent::__construct(['node' => $node], [], $lineno);
}
public function compile(Compiler $compiler)
{
$compiler->raw(' ');
$this->operator($compiler);
$compiler->subcompile($this->getNode('node'));
}
abstract public function operator(Compiler $compiler);
}
class_alias('Twig\Node\Expression\Unary\AbstractUnary', 'Twig_Node_Expression_Unary');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary
namespace Twig\Node\Expression\Unary;
use Twig\Compiler;
class NegUnary extends AbstractUnary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
$compiler->raw('-');
}
}
class_alias('Twig_Node_Expression_Unary_Neg', 'Twig\Node\Expression\Unary\NegUnary', false);
class_alias('Twig\Node\Expression\Unary\NegUnary', 'Twig_Node_Expression_Unary_Neg');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary
namespace Twig\Node\Expression\Unary;
use Twig\Compiler;
class NotUnary extends AbstractUnary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
$compiler->raw('!');
}
}
class_alias('Twig_Node_Expression_Unary_Not', 'Twig\Node\Expression\Unary\NotUnary', false);
class_alias('Twig\Node\Expression\Unary\NotUnary', 'Twig_Node_Expression_Unary_Not');

View File

@@ -9,12 +9,17 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary
namespace Twig\Node\Expression\Unary;
use Twig\Compiler;
class PosUnary extends AbstractUnary
{
public function operator(Twig_Compiler $compiler)
public function operator(Compiler $compiler)
{
$compiler->raw('+');
}
}
class_alias('Twig_Node_Expression_Unary_Pos', 'Twig\Node\Expression\Unary\PosUnary', false);
class_alias('Twig\Node\Expression\Unary\PosUnary', 'Twig_Node_Expression_Unary_Pos');

View File

@@ -9,19 +9,23 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents a flush node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Flush extends Twig_Node
class FlushNode extends Node
{
public function __construct($lineno, $tag)
{
parent::__construct(array(), array(), $lineno, $tag);
parent::__construct([], [], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
@@ -30,4 +34,4 @@ class Twig_Node_Flush extends Twig_Node
}
}
class_alias('Twig_Node_Flush', 'Twig\Node\FlushNode', false);
class_alias('Twig\Node\FlushNode', 'Twig_Node_Flush');

View File

@@ -9,19 +9,23 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Internal node used by the for node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_ForLoop extends Twig_Node
class ForLoopNode extends Node
{
public function __construct($lineno, $tag = null)
{
parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag);
parent::__construct([], ['with_loop' => false, 'ifexpr' => false, 'else' => false], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
if ($this->getAttribute('else')) {
$compiler->write("\$context['_iterated'] = true;\n");
@@ -49,4 +53,4 @@ class Twig_Node_ForLoop extends Twig_Node
}
}
class_alias('Twig_Node_ForLoop', 'Twig\Node\ForLoopNode', false);
class_alias('Twig\Node\ForLoopNode', 'Twig_Node_ForLoop');

View File

@@ -10,32 +10,38 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\AssignNameExpression;
/**
* Represents a for node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_For extends Twig_Node
class ForNode extends Node
{
protected $loop;
public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_Node_Expression $ifexpr = null, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null)
public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, AbstractExpression $ifexpr = null, \Twig_NodeInterface $body, \Twig_NodeInterface $else = null, $lineno, $tag = null)
{
$body = new Twig_Node(array($body, $this->loop = new Twig_Node_ForLoop($lineno, $tag)));
$body = new Node([$body, $this->loop = new ForLoopNode($lineno, $tag)]);
if (null !== $ifexpr) {
$body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag);
$body = new IfNode(new Node([$ifexpr, $body]), null, $lineno, $tag);
}
$nodes = array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body);
$nodes = ['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);
parent::__construct($nodes, ['with_loop' => true, 'ifexpr' => null !== $ifexpr], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
@@ -51,17 +57,17 @@ class Twig_Node_For extends Twig_Node
if ($this->getAttribute('with_loop')) {
$compiler
->write("\$context['loop'] = array(\n")
->write("\$context['loop'] = [\n")
->write(" 'parent' => \$context['_parent'],\n")
->write(" 'index0' => 0,\n")
->write(" 'index' => 1,\n")
->write(" 'first' => true,\n")
->write(");\n")
->write("];\n")
;
if (!$this->getAttribute('ifexpr')) {
$compiler
->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n")
->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof \Countable)) {\n")
->indent()
->write("\$length = count(\$context['_seq']);\n")
->write("\$context['loop']['revindex0'] = \$length - 1;\n")
@@ -110,4 +116,4 @@ class Twig_Node_For extends Twig_Node
}
}
class_alias('Twig_Node_For', 'Twig\Node\ForNode', false);
class_alias('Twig\Node\ForNode', 'Twig_Node_For');

View File

@@ -10,27 +10,31 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents an if node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_If extends Twig_Node
class IfNode extends Node
{
public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null)
public function __construct(\Twig_NodeInterface $tests, \Twig_NodeInterface $else = null, $lineno, $tag = null)
{
$nodes = array('tests' => $tests);
$nodes = ['tests' => $tests];
if (null !== $else) {
$nodes['else'] = $else;
}
parent::__construct($nodes, array(), $lineno, $tag);
parent::__construct($nodes, [], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler->addDebugInfo($this);
for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) {
for ($i = 0, $count = \count($this->getNode('tests')); $i < $count; $i += 2) {
if ($i > 0) {
$compiler
->outdent()
@@ -65,4 +69,4 @@ class Twig_Node_If extends Twig_Node
}
}
class_alias('Twig_Node_If', 'Twig\Node\IfNode', false);
class_alias('Twig\Node\IfNode', 'Twig_Node_If');

View File

@@ -9,19 +9,25 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\NameExpression;
/**
* Represents an import node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Import extends Twig_Node
class ImportNode extends Node
{
public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null)
public function __construct(AbstractExpression $expr, AbstractExpression $var, $lineno, $tag = null)
{
parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag);
parent::__construct(['expr' => $expr, 'var' => $var], [], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
@@ -30,7 +36,7 @@ class Twig_Node_Import extends Twig_Node
->raw(' = ')
;
if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
if ($this->getNode('expr') instanceof NameExpression && '_self' === $this->getNode('expr')->getAttribute('name')) {
$compiler->raw('$this');
} else {
$compiler
@@ -40,7 +46,7 @@ class Twig_Node_Import extends Twig_Node
->repr($this->getTemplateName())
->raw(', ')
->repr($this->getTemplateLine())
->raw(')')
->raw(')->unwrap()')
;
}
@@ -48,4 +54,4 @@ class Twig_Node_Import extends Twig_Node
}
}
class_alias('Twig_Node_Import', 'Twig\Node\ImportNode', false);
class_alias('Twig\Node\ImportNode', 'Twig_Node_Import');

View File

@@ -1,90 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (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.
*/
/**
* Represents an include node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
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)
{
$nodes = array('expr' => $expr);
if (null !== $variables) {
$nodes['variables'] = $variables;
}
parent::__construct($nodes, array('only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing), $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
if ($this->getAttribute('ignore_missing')) {
$compiler
->write("try {\n")
->indent()
;
}
$this->addGetTemplate($compiler);
$compiler->raw('->display(');
$this->addTemplateArguments($compiler);
$compiler->raw(");\n");
if ($this->getAttribute('ignore_missing')) {
$compiler
->outdent()
->write("} catch (Twig_Error_Loader \$e) {\n")
->indent()
->write("// ignore missing template\n")
->outdent()
->write("}\n\n")
;
}
}
protected function addGetTemplate(Twig_Compiler $compiler)
{
$compiler
->write('$this->loadTemplate(')
->subcompile($this->getNode('expr'))
->raw(', ')
->repr($this->getTemplateName())
->raw(', ')
->repr($this->getTemplateLine())
->raw(')')
;
}
protected function addTemplateArguments(Twig_Compiler $compiler)
{
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 {
$compiler->subcompile($this->getNode('variables'));
}
}
}
class_alias('Twig_Node_Include', 'Twig\Node\IncludeNode', false);

View File

@@ -0,0 +1,108 @@
<?php
/*
* This file is part of Twig.
*
* (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.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
/**
* Represents an include node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class IncludeNode extends Node implements NodeOutputInterface
{
public function __construct(AbstractExpression $expr, AbstractExpression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
{
$nodes = ['expr' => $expr];
if (null !== $variables) {
$nodes['variables'] = $variables;
}
parent::__construct($nodes, ['only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing], $lineno, $tag);
}
public function compile(Compiler $compiler)
{
$compiler->addDebugInfo($this);
if ($this->getAttribute('ignore_missing')) {
$template = $compiler->getVarName();
$compiler
->write(sprintf("$%s = null;\n", $template))
->write("try {\n")
->indent()
->write(sprintf('$%s = ', $template))
;
$this->addGetTemplate($compiler);
$compiler
->raw(";\n")
->outdent()
->write("} catch (LoaderError \$e) {\n")
->indent()
->write("// ignore missing template\n")
->outdent()
->write("}\n")
->write(sprintf("if ($%s) {\n", $template))
->indent()
->write(sprintf('$%s->display(', $template))
;
$this->addTemplateArguments($compiler);
$compiler
->raw(");\n")
->outdent()
->write("}\n")
;
} else {
$this->addGetTemplate($compiler);
$compiler->raw('->display(');
$this->addTemplateArguments($compiler);
$compiler->raw(");\n");
}
}
protected function addGetTemplate(Compiler $compiler)
{
$compiler
->write('$this->loadTemplate(')
->subcompile($this->getNode('expr'))
->raw(', ')
->repr($this->getTemplateName())
->raw(', ')
->repr($this->getTemplateLine())
->raw(')')
;
}
protected function addTemplateArguments(Compiler $compiler)
{
if (!$this->hasNode('variables')) {
$compiler->raw(false === $this->getAttribute('only') ? '$context' : '[]');
} elseif (false === $this->getAttribute('only')) {
$compiler
->raw('twig_array_merge($context, ')
->subcompile($this->getNode('variables'))
->raw(')')
;
} else {
$compiler->raw('twig_to_array(');
$compiler->subcompile($this->getNode('variables'));
$compiler->raw(')');
}
}
}
class_alias('Twig\Node\IncludeNode', 'Twig_Node_Include');

View File

@@ -9,34 +9,39 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Error\SyntaxError;
/**
* Represents a macro node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Macro extends Twig_Node
class MacroNode extends Node
{
const VARARGS_NAME = 'varargs';
public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
public function __construct($name, \Twig_NodeInterface $body, \Twig_NodeInterface $arguments, $lineno, $tag = null)
{
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());
throw new SyntaxError(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(), $argument->getSourceContext());
}
}
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write(sprintf('public function get%s(', $this->getAttribute('name')))
;
$count = count($this->getNode('arguments'));
$count = \count($this->getNode('arguments'));
$pos = 0;
foreach ($this->getNode('arguments') as $name => $default) {
$compiler
@@ -49,7 +54,7 @@ class Twig_Node_Macro extends Twig_Node
}
}
if (PHP_VERSION_ID >= 50600) {
if (\PHP_VERSION_ID >= 50600) {
if ($count) {
$compiler->raw(', ');
}
@@ -64,7 +69,7 @@ class Twig_Node_Macro extends Twig_Node
;
$compiler
->write("\$context = \$this->env->mergeGlobals(array(\n")
->write("\$context = \$this->env->mergeGlobals([\n")
->indent()
;
@@ -83,7 +88,7 @@ class Twig_Node_Macro extends Twig_Node
->raw(' => ')
;
if (PHP_VERSION_ID >= 50600) {
if (\PHP_VERSION_ID >= 50600) {
$compiler->raw("\$__varargs__,\n");
} else {
$compiler
@@ -91,35 +96,41 @@ class Twig_Node_Macro extends Twig_Node
->repr($count)
->raw(' ? array_slice(func_get_args(), ')
->repr($count)
->raw(") : array(),\n")
->raw(") : [],\n")
;
}
$compiler
->outdent()
->write("));\n\n")
->write("\$blocks = array();\n\n")
->write("ob_start();\n")
->write("]);\n\n")
->write("\$blocks = [];\n\n")
;
if ($compiler->getEnvironment()->isDebug()) {
$compiler->write("ob_start();\n");
} else {
$compiler->write("ob_start(function () { return ''; });\n");
}
$compiler
->write("try {\n")
->indent()
->subcompile($this->getNode('body'))
->outdent()
->write("} catch (Exception \$e) {\n")
->write("} catch (\Exception \$e) {\n")
->indent()
->write("ob_end_clean();\n\n")
->write("throw \$e;\n")
->outdent()
->write("} catch (Throwable \$e) {\n")
->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")
->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset());\n")
->outdent()
->write("}\n\n")
;
}
}
class_alias('Twig_Node_Macro', 'Twig\Node\MacroNode', false);
class_alias('Twig\Node\MacroNode', 'Twig_Node_Macro');

View File

@@ -10,6 +10,13 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\ConstantExpression;
use Twig\Source;
/**
* Represents a module node.
*
@@ -19,46 +26,45 @@
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Module extends Twig_Node
class ModuleNode extends Node
{
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 = '')
public function __construct(\Twig_NodeInterface $body, AbstractExpression $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);
if (!$name instanceof 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);
$source = new Source($source, $name);
} else {
$this->source = $name;
$source = $name;
}
$nodes = array(
$nodes = [
'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(),
);
'display_start' => new Node(),
'display_end' => new Node(),
'constructor_start' => new Node(),
'constructor_end' => new Node(),
'class_end' => new 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($nodes, array(
parent::__construct($nodes, [
// source to be remove in 2.0
'source' => $this->source->getCode(),
'source' => $source->getCode(),
// filename to be remove in 2.0 (use getTemplateName() instead)
'filename' => $this->source->getName(),
'filename' => $source->getName(),
'index' => null,
'embedded_templates' => $embeddedTemplates,
), 1);
], 1);
// populate the template name of all node children
$this->setTemplateName($this->source->getName());
$this->setTemplateName($source->getName());
$this->setSourceContext($source);
}
public function setIndex($index)
@@ -66,7 +72,7 @@ class Twig_Node_Module extends Twig_Node
$this->setAttribute('index', $index);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$this->compileTemplate($compiler);
@@ -75,7 +81,7 @@ class Twig_Node_Module extends Twig_Node
}
}
protected function compileTemplate(Twig_Compiler $compiler)
protected function compileTemplate(Compiler $compiler)
{
if (!$this->getAttribute('index')) {
$compiler->write('<?php');
@@ -84,12 +90,12 @@ class Twig_Node_Module extends Twig_Node
$this->compileClassHeader($compiler);
if (
count($this->getNode('blocks'))
|| count($this->getNode('traits'))
\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->getNode('parent') instanceof ConstantExpression
|| \count($this->getNode('constructor_start'))
|| \count($this->getNode('constructor_end'))
) {
$this->compileConstructor($compiler);
}
@@ -115,7 +121,7 @@ class Twig_Node_Module extends Twig_Node
$this->compileClassFooter($compiler);
}
protected function compileGetParent(Twig_Compiler $compiler)
protected function compileGetParent(Compiler $compiler)
{
if (!$this->hasNode('parent')) {
return;
@@ -129,14 +135,14 @@ class Twig_Node_Module extends Twig_Node
->write('return ')
;
if ($parent instanceof Twig_Node_Expression_Constant) {
if ($parent instanceof ConstantExpression) {
$compiler->subcompile($parent);
} else {
$compiler
->raw('$this->loadTemplate(')
->subcompile($parent)
->raw(', ')
->repr($this->source->getName())
->repr($this->getSourceContext()->getName())
->raw(', ')
->repr($parent->getTemplateLine())
->raw(')')
@@ -150,23 +156,39 @@ class Twig_Node_Module extends Twig_Node
;
}
protected function compileClassHeader(Twig_Compiler $compiler)
protected function compileClassHeader(Compiler $compiler)
{
$compiler
->write("\n\n")
;
if (!$this->getAttribute('index')) {
$compiler
->write("use Twig\Environment;\n")
->write("use Twig\Error\LoaderError;\n")
->write("use Twig\Error\RuntimeError;\n")
->write("use Twig\Markup;\n")
->write("use Twig\Sandbox\SecurityError;\n")
->write("use Twig\Sandbox\SecurityNotAllowedTagError;\n")
->write("use Twig\Sandbox\SecurityNotAllowedFilterError;\n")
->write("use Twig\Sandbox\SecurityNotAllowedFunctionError;\n")
->write("use Twig\Source;\n")
->write("use Twig\Template;\n\n")
;
}
$compiler
// 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')))
->write('/* '.str_replace('*/', '* /', $this->getSourceContext()->getName())." */\n")
->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getSourceContext()->getName(), $this->getAttribute('index')))
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
->write("{\n")
->indent()
;
}
protected function compileConstructor(Twig_Compiler $compiler)
protected function compileConstructor(Compiler $compiler)
{
$compiler
->write("public function __construct(Twig_Environment \$env)\n", "{\n")
->write("public function __construct(Environment \$env)\n", "{\n")
->indent()
->subcompile($this->getNode('constructor_start'))
->write("parent::__construct(\$env);\n\n")
@@ -175,32 +197,24 @@ class Twig_Node_Module extends Twig_Node
// parent
if (!$this->hasNode('parent')) {
$compiler->write("\$this->parent = false;\n\n");
} elseif (($parent = $this->getNode('parent')) && $parent instanceof Twig_Node_Expression_Constant) {
$compiler
->addDebugInfo($parent)
->write('$this->parent = $this->loadTemplate(')
->subcompile($parent)
->raw(', ')
->repr($this->source->getName())
->raw(', ')
->repr($parent->getTemplateLine())
->raw(");\n")
;
}
$countTraits = count($this->getNode('traits'));
$countTraits = \count($this->getNode('traits'));
if ($countTraits) {
// traits
foreach ($this->getNode('traits') as $i => $trait) {
$this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i));
$node = $trait->getNode('template');
$compiler
->addDebugInfo($trait->getNode('template'))
->addDebugInfo($node)
->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
->indent()
->write("throw new Twig_Error_Runtime('Template \"'.")
->write("throw new RuntimeError('Template \"'.")
->subcompile($trait->getNode('template'))
->raw(".'\" cannot be used as a trait.');\n")
->raw(".'\" cannot be used as a trait.', ")
->repr($node->getTemplateLine())
->raw(", \$this->getSourceContext());\n")
->outdent()
->write("}\n")
->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
@@ -212,11 +226,13 @@ class Twig_Node_Module extends Twig_Node
->string($key)
->raw("])) {\n")
->indent()
->write("throw new Twig_Error_Runtime(sprintf('Block ")
->write("throw new RuntimeError(sprintf('Block ")
->string($key)
->raw(' is not defined in trait ')
->subcompile($trait->getNode('template'))
->raw(".'));\n")
->raw(".'), ")
->repr($node->getTemplateLine())
->raw(", \$this->getSourceContext());\n")
->outdent()
->write("}\n\n")
@@ -257,11 +273,11 @@ class Twig_Node_Module extends Twig_Node
->write("\$this->blocks = array_merge(\n")
->indent()
->write("\$this->traits,\n")
->write("array(\n")
->write("[\n")
;
} else {
$compiler
->write("\$this->blocks = array(\n")
->write("\$this->blocks = [\n")
;
}
@@ -272,30 +288,35 @@ class Twig_Node_Module extends Twig_Node
foreach ($this->getNode('blocks') as $name => $node) {
$compiler
->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name))
->write(sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name))
;
}
if ($countTraits) {
$compiler
->outdent()
->write(")\n")
->write("]\n")
->outdent()
->write(");\n")
;
} else {
$compiler
->outdent()
->write("];\n")
;
}
$compiler
->outdent()
->write(");\n")
->outdent()
->subcompile($this->getNode('constructor_end'))
->outdent()
->write("}\n\n")
;
}
protected function compileDisplay(Twig_Compiler $compiler)
protected function compileDisplay(Compiler $compiler)
{
$compiler
->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n")
->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n")
->indent()
->subcompile($this->getNode('display_start'))
->subcompile($this->getNode('body'))
@@ -303,8 +324,18 @@ class Twig_Node_Module extends Twig_Node
if ($this->hasNode('parent')) {
$parent = $this->getNode('parent');
$compiler->addDebugInfo($parent);
if ($parent instanceof Twig_Node_Expression_Constant) {
if ($parent instanceof ConstantExpression) {
$compiler
->write('$this->parent = $this->loadTemplate(')
->subcompile($parent)
->raw(', ')
->repr($this->getSourceContext()->getName())
->raw(', ')
->repr($parent->getTemplateLine())
->raw(");\n")
;
$compiler->write('$this->parent');
} else {
$compiler->write('$this->getParent($context)');
@@ -319,7 +350,7 @@ class Twig_Node_Module extends Twig_Node
;
}
protected function compileClassFooter(Twig_Compiler $compiler)
protected function compileClassFooter(Compiler $compiler)
{
$compiler
->subcompile($this->getNode('class_end'))
@@ -328,25 +359,25 @@ class Twig_Node_Module extends Twig_Node
;
}
protected function compileMacros(Twig_Compiler $compiler)
protected function compileMacros(Compiler $compiler)
{
$compiler->subcompile($this->getNode('macros'));
}
protected function compileGetTemplateName(Twig_Compiler $compiler)
protected function compileGetTemplateName(Compiler $compiler)
{
$compiler
->write("public function getTemplateName()\n", "{\n")
->indent()
->write('return ')
->repr($this->source->getName())
->repr($this->getSourceContext()->getName())
->raw(";\n")
->outdent()
->write("}\n\n")
;
}
protected function compileIsTraitable(Twig_Compiler $compiler)
protected function compileIsTraitable(Compiler $compiler)
{
// A template can be used as a trait if:
// * it has no parent
@@ -355,28 +386,28 @@ 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 = !$this->hasNode('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) {
if ($this->getNode('body') instanceof BodyNode) {
$nodes = $this->getNode('body')->getNode(0);
} else {
$nodes = $this->getNode('body');
}
if (!count($nodes)) {
$nodes = new Twig_Node(array($nodes));
if (!\count($nodes)) {
$nodes = new Node([$nodes]);
}
foreach ($nodes as $node) {
if (!count($node)) {
if (!\count($node)) {
continue;
}
if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) {
continue;
}
if ($node instanceof Twig_Node_BlockReference) {
if ($node instanceof BlockReferenceNode) {
continue;
}
@@ -398,7 +429,7 @@ class Twig_Node_Module extends Twig_Node
;
}
protected function compileDebugInfo(Twig_Compiler $compiler)
protected function compileDebugInfo(Compiler $compiler)
{
$compiler
->write("public function getDebugInfo()\n", "{\n")
@@ -409,7 +440,7 @@ class Twig_Node_Module extends Twig_Node
;
}
protected function compileGetSource(Twig_Compiler $compiler)
protected function compileGetSource(Compiler $compiler)
{
$compiler
->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n")
@@ -423,26 +454,26 @@ class Twig_Node_Module extends Twig_Node
;
}
protected function compileGetSourceContext(Twig_Compiler $compiler)
protected function compileGetSourceContext(Compiler $compiler)
{
$compiler
->write("public function getSourceContext()\n", "{\n")
->indent()
->write('return new Twig_Source(')
->string($compiler->getEnvironment()->isDebug() ? $this->source->getCode() : '')
->write('return new Source(')
->string($compiler->getEnvironment()->isDebug() ? $this->getSourceContext()->getCode() : '')
->raw(', ')
->string($this->source->getName())
->string($this->getSourceContext()->getName())
->raw(', ')
->string($this->source->getPath())
->string($this->getSourceContext()->getPath())
->raw(");\n")
->outdent()
->write("}\n")
;
}
protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var)
protected function compileLoadTemplate(Compiler $compiler, $node, $var)
{
if ($node instanceof Twig_Node_Expression_Constant) {
if ($node instanceof ConstantExpression) {
$compiler
->write(sprintf('%s = $this->loadTemplate(', $var))
->subcompile($node)
@@ -453,9 +484,9 @@ class Twig_Node_Module extends Twig_Node
->raw(");\n")
;
} else {
throw new LogicException('Trait templates can only be constant nodes.');
throw new \LogicException('Trait templates can only be constant nodes.');
}
}
}
class_alias('Twig_Node_Module', 'Twig\Node\ModuleNode', false);
class_alias('Twig\Node\ModuleNode', 'Twig_Node_Module');

View File

@@ -0,0 +1,274 @@
<?php
/*
* This file is part of Twig.
*
* (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.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Source;
/**
* Represents a node in the AST.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Node implements \Twig_NodeInterface
{
protected $nodes;
protected $attributes;
protected $lineno;
protected $tag;
private $name;
private $sourceContext;
/**
* @param array $nodes An array of named nodes
* @param array $attributes An array of attributes (should not be nodes)
* @param int $lineno The line number
* @param string $tag The tag name associated with the Node
*/
public function __construct(array $nodes = [], array $attributes = [], $lineno = 0, $tag = null)
{
foreach ($nodes as $name => $node) {
if (!$node instanceof \Twig_NodeInterface) {
@trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', \is_object($node) ? \get_class($node) : (null === $node ? 'null' : \gettype($node)), $name, \get_class($this)), E_USER_DEPRECATED);
}
}
$this->nodes = $nodes;
$this->attributes = $attributes;
$this->lineno = $lineno;
$this->tag = $tag;
}
public function __toString()
{
$attributes = [];
foreach ($this->attributes as $name => $value) {
$attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true)));
}
$repr = [\get_class($this).'('.implode(', ', $attributes)];
if (\count($this->nodes)) {
foreach ($this->nodes as $name => $node) {
$len = \strlen($name) + 4;
$noderepr = [];
foreach (explode("\n", (string) $node) as $line) {
$noderepr[] = str_repeat(' ', $len).$line;
}
$repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr)));
}
$repr[] = ')';
} else {
$repr[0] .= ')';
}
return implode("\n", $repr);
}
/**
* @deprecated since 1.16.1 (to be removed in 2.0)
*/
public function toXml($asDom = false)
{
@trigger_error(sprintf('%s is deprecated since version 1.16.1 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED);
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->appendChild($xml = $dom->createElement('twig'));
$xml->appendChild($node = $dom->createElement('node'));
$node->setAttribute('class', \get_class($this));
foreach ($this->attributes as $name => $value) {
$node->appendChild($attribute = $dom->createElement('attribute'));
$attribute->setAttribute('name', $name);
$attribute->appendChild($dom->createTextNode($value));
}
foreach ($this->nodes as $name => $n) {
if (null === $n) {
continue;
}
$child = $n->toXml(true)->getElementsByTagName('node')->item(0);
$child = $dom->importNode($child, true);
$child->setAttribute('name', $name);
$node->appendChild($child);
}
return $asDom ? $dom : $dom->saveXML();
}
public function compile(Compiler $compiler)
{
foreach ($this->nodes as $node) {
$node->compile($compiler);
}
}
public function getTemplateLine()
{
return $this->lineno;
}
/**
* @deprecated since 1.27 (to be removed in 2.0)
*/
public function getLine()
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateLine() instead.', E_USER_DEPRECATED);
return $this->lineno;
}
public function getNodeTag()
{
return $this->tag;
}
/**
* @return bool
*/
public function hasAttribute($name)
{
return \array_key_exists($name, $this->attributes);
}
/**
* @return mixed
*/
public function getAttribute($name)
{
if (!\array_key_exists($name, $this->attributes)) {
throw new \LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, \get_class($this)));
}
return $this->attributes[$name];
}
/**
* @param string $name
* @param mixed $value
*/
public function setAttribute($name, $value)
{
$this->attributes[$name] = $value;
}
public function removeAttribute($name)
{
unset($this->attributes[$name]);
}
/**
* @return bool
*/
public function hasNode($name)
{
return \array_key_exists($name, $this->nodes);
}
/**
* @return Node
*/
public function getNode($name)
{
if (!\array_key_exists($name, $this->nodes)) {
throw new \LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, \get_class($this)));
}
return $this->nodes[$name];
}
public function setNode($name, $node = null)
{
if (!$node instanceof \Twig_NodeInterface) {
@trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', \is_object($node) ? \get_class($node) : (null === $node ? 'null' : \gettype($node)), $name, \get_class($this)), E_USER_DEPRECATED);
}
$this->nodes[$name] = $node;
}
public function removeNode($name)
{
unset($this->nodes[$name]);
}
public function count()
{
return \count($this->nodes);
}
public function getIterator()
{
return new \ArrayIterator($this->nodes);
}
public function setTemplateName($name)
{
$this->name = $name;
foreach ($this->nodes as $node) {
if (null !== $node) {
$node->setTemplateName($name);
}
}
}
public function getTemplateName()
{
return $this->name;
}
public function setSourceContext(Source $source)
{
$this->sourceContext = $source;
foreach ($this->nodes as $node) {
if ($node instanceof Node) {
$node->setSourceContext($source);
}
}
}
public function getSourceContext()
{
return $this->sourceContext;
}
/**
* @deprecated since 1.27 (to be removed in 2.0)
*/
public function setFilename($name)
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use setTemplateName() instead.', E_USER_DEPRECATED);
$this->setTemplateName($name);
}
/**
* @deprecated since 1.27 (to be removed in 2.0)
*/
public function getFilename()
{
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateName() instead.', E_USER_DEPRECATED);
return $this->name;
}
}
class_alias('Twig\Node\Node', 'Twig_Node');
// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name.
class_exists('Twig\Compiler');

View File

@@ -0,0 +1,23 @@
<?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.
*/
namespace Twig\Node;
/**
* Represents a node that captures any nested displayable nodes.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface NodeCaptureInterface
{
}
class_alias('Twig\Node\NodeCaptureInterface', 'Twig_NodeCaptureInterface');

View File

@@ -0,0 +1,23 @@
<?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.
*/
namespace Twig\Node;
/**
* Represents a displayable node in the AST.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface NodeOutputInterface
{
}
class_alias('Twig\Node\NodeOutputInterface', 'Twig_NodeOutputInterface');

View File

@@ -10,19 +10,24 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\AbstractExpression;
/**
* Represents a node that outputs an expression.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
class PrintNode extends Node implements NodeOutputInterface
{
public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
public function __construct(AbstractExpression $expr, $lineno, $tag = null)
{
parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
parent::__construct(['expr' => $expr], [], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
@@ -33,4 +38,4 @@ class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
}
}
class_alias('Twig_Node_Print', 'Twig\Node\PrintNode', false);
class_alias('Twig\Node\PrintNode', 'Twig_Node_Print');

View File

@@ -9,36 +9,39 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents a sandbox node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Sandbox extends Twig_Node
class SandboxNode extends Node
{
public function __construct(Twig_NodeInterface $body, $lineno, $tag = null)
public function __construct(\Twig_NodeInterface $body, $lineno, $tag = null)
{
parent::__construct(array('body' => $body), array(), $lineno, $tag);
parent::__construct(['body' => $body], [], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write("\$sandbox = \$this->env->getExtension('Twig_Extension_Sandbox');\n")
->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
->write("if (!\$alreadySandboxed = \$this->sandbox->isSandboxed()) {\n")
->indent()
->write("\$sandbox->enableSandbox();\n")
->write("\$this->sandbox->enableSandbox();\n")
->outdent()
->write("}\n")
->subcompile($this->getNode('body'))
->write("if (!\$alreadySandboxed) {\n")
->indent()
->write("\$sandbox->disableSandbox();\n")
->write("\$this->sandbox->disableSandbox();\n")
->outdent()
->write("}\n")
;
}
}
class_alias('Twig_Node_Sandbox', 'Twig\Node\SandboxNode', false);
class_alias('Twig\Node\SandboxNode', 'Twig_Node_Sandbox');

View File

@@ -1,51 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Twig_Node_SandboxedPrint adds a check for the __toString() method
* when the variable is an object and the sandbox is activated.
*
* When there is a simple Print statement, like {{ article }},
* and if the sandbox is enabled, we need to check that the __toString()
* method is allowed if 'article' is an object.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_SandboxedPrint extends Twig_Node_Print
{
public function compile(Twig_Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write('echo $this->env->getExtension(\'Twig_Extension_Sandbox\')->ensureToStringAllowed(')
->subcompile($this->getNode('expr'))
->raw(");\n")
;
}
/**
* Removes node filters.
*
* This is mostly needed when another visitor adds filters (like the escaper one).
*
* @return Twig_Node
*/
protected function removeNodeFilter(Twig_Node $node)
{
if ($node instanceof Twig_Node_Expression_Filter) {
return $this->removeNodeFilter($node->getNode('node'));
}
return $node;
}
}
class_alias('Twig_Node_SandboxedPrint', 'Twig\Node\SandboxedPrintNode', false);

View File

@@ -0,0 +1,69 @@
<?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.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Expression\FilterExpression;
/**
* Adds a check for the __toString() method when the variable is an object and the sandbox is activated.
*
* When there is a simple Print statement, like {{ article }},
* and if the sandbox is enabled, we need to check that the __toString()
* method is allowed if 'article' is an object.
*
* Not used anymore, to be deprecated in 2.x and removed in 3.0
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class SandboxedPrintNode extends PrintNode
{
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write('echo ')
;
$expr = $this->getNode('expr');
if ($expr instanceof ConstantExpression) {
$compiler
->subcompile($expr)
->raw(";\n")
;
} else {
$compiler
->write('$this->env->getExtension(\'\Twig\Extension\SandboxExtension\')->ensureToStringAllowed(')
->subcompile($expr)
->raw(");\n")
;
}
}
/**
* Removes node filters.
*
* This is mostly needed when another visitor adds filters (like the escaper one).
*
* @return Node
*/
protected function removeNodeFilter(Node $node)
{
if ($node instanceof FilterExpression) {
return $this->removeNodeFilter($node->getNode('node'));
}
return $node;
}
}
class_alias('Twig\Node\SandboxedPrintNode', 'Twig_Node_SandboxedPrint');

View File

@@ -9,38 +9,43 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
use Twig\Node\Expression\ConstantExpression;
/**
* Represents a set node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface
class SetNode extends Node implements NodeCaptureInterface
{
public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null)
public function __construct($capture, \Twig_NodeInterface $names, \Twig_NodeInterface $values, $lineno, $tag = null)
{
parent::__construct(array('names' => $names, 'values' => $values), array('capture' => $capture, 'safe' => false), $lineno, $tag);
parent::__construct(['names' => $names, 'values' => $values], ['capture' => $capture, 'safe' => false], $lineno, $tag);
/*
* Optimizes the node when capture is used for a large block of text.
*
* {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig_Markup("foo");
* {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig\Markup("foo");
*/
if ($this->getAttribute('capture')) {
$this->setAttribute('safe', true);
$values = $this->getNode('values');
if ($values instanceof Twig_Node_Text) {
$this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getTemplateLine()));
if ($values instanceof TextNode) {
$this->setNode('values', new ConstantExpression($values->getAttribute('data'), $values->getTemplateLine()));
$this->setAttribute('capture', false);
}
}
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler->addDebugInfo($this);
if (count($this->getNode('names')) > 1) {
if (\count($this->getNode('names')) > 1) {
$compiler->write('list(');
foreach ($this->getNode('names') as $idx => $node) {
if ($idx) {
@@ -52,8 +57,12 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface
$compiler->raw(')');
} else {
if ($this->getAttribute('capture')) {
if ($compiler->getEnvironment()->isDebug()) {
$compiler->write("ob_start();\n");
} else {
$compiler->write("ob_start(function () { return ''; });\n");
}
$compiler
->write("ob_start();\n")
->subcompile($this->getNode('values'))
;
}
@@ -61,15 +70,15 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface
$compiler->subcompile($this->getNode('names'), false);
if ($this->getAttribute('capture')) {
$compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())");
$compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset())");
}
}
if (!$this->getAttribute('capture')) {
$compiler->raw(' = ');
if (count($this->getNode('names')) > 1) {
$compiler->write('array(');
if (\count($this->getNode('names')) > 1) {
$compiler->write('[');
foreach ($this->getNode('values') as $idx => $value) {
if ($idx) {
$compiler->raw(', ');
@@ -77,13 +86,13 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface
$compiler->subcompile($value);
}
$compiler->raw(')');
$compiler->raw(']');
} else {
if ($this->getAttribute('safe')) {
$compiler
->raw("('' === \$tmp = ")
->subcompile($this->getNode('values'))
->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())")
->raw(") ? '' : new Markup(\$tmp, \$this->env->getCharset())")
;
} else {
$compiler->subcompile($this->getNode('values'));
@@ -95,4 +104,4 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface
}
}
class_alias('Twig_Node_Set', 'Twig\Node\SetNode', false);
class_alias('Twig\Node\SetNode', 'Twig_Node_Set');

View File

@@ -9,17 +9,21 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* @internal
*/
class Twig_Node_SetTemp extends Twig_Node
class SetTempNode extends Node
{
public function __construct($name, $lineno)
{
parent::__construct(array(), array('name' => $name), $lineno);
parent::__construct([], ['name' => $name], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$name = $this->getAttribute('name');
$compiler
@@ -37,4 +41,4 @@ class Twig_Node_SetTemp extends Twig_Node
}
}
class_alias('Twig_Node_SetTemp', 'Twig\Node\SetTempNode', false);
class_alias('Twig\Node\SetTempNode', 'Twig_Node_SetTemp');

View File

@@ -1,37 +0,0 @@
<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Represents a spaceless node.
*
* It removes spaces between HTML tags.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Spaceless extends Twig_Node
{
public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
{
parent::__construct(array('body' => $body), array(), $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write("ob_start();\n")
->subcompile($this->getNode('body'))
->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n")
;
}
}
class_alias('Twig_Node_Spaceless', 'Twig\Node\SpacelessNode', false);

View File

@@ -0,0 +1,47 @@
<?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.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents a spaceless node.
*
* It removes spaces between HTML tags.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class SpacelessNode extends Node
{
public function __construct(\Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
{
parent::__construct(['body' => $body], [], $lineno, $tag);
}
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
;
if ($compiler->getEnvironment()->isDebug()) {
$compiler->write("ob_start();\n");
} else {
$compiler->write("ob_start(function () { return ''; });\n");
}
$compiler
->subcompile($this->getNode('body'))
->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n")
;
}
}
class_alias('Twig\Node\SpacelessNode', 'Twig_Node_Spaceless');

View File

@@ -10,19 +10,23 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents a text node.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
class TextNode extends Node implements NodeOutputInterface
{
public function __construct($data, $lineno)
{
parent::__construct(array(), array('data' => $data), $lineno);
parent::__construct([], ['data' => $data], $lineno);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
@@ -33,4 +37,4 @@ class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
}
}
class_alias('Twig_Node_Text', 'Twig\Node\TextNode', false);
class_alias('Twig\Node\TextNode', 'Twig_Node_Text');

View File

@@ -9,47 +9,55 @@
* file that was distributed with this source code.
*/
namespace Twig\Node;
use Twig\Compiler;
/**
* Represents a nested "with" scope.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Twig_Node_With extends Twig_Node
class WithNode extends Node
{
public function __construct(Twig_Node $body, Twig_Node $variables = null, $only = false, $lineno, $tag = null)
public function __construct(Node $body, Node $variables = null, $only = false, $lineno, $tag = null)
{
$nodes = array('body' => $body);
$nodes = ['body' => $body];
if (null !== $variables) {
$nodes['variables'] = $variables;
}
parent::__construct($nodes, array('only' => (bool) $only), $lineno, $tag);
parent::__construct($nodes, ['only' => (bool) $only], $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
public function compile(Compiler $compiler)
{
$compiler->addDebugInfo($this);
if ($this->hasNode('variables')) {
$node = $this->getNode('variables');
$varsName = $compiler->getVarName();
$compiler
->write(sprintf('$%s = ', $varsName))
->subcompile($this->getNode('variables'))
->subcompile($node)
->raw(";\n")
->write(sprintf("if (!is_array(\$%s)) {\n", $varsName))
->write(sprintf("if (!twig_test_iterable(\$%s)) {\n", $varsName))
->indent()
->write("throw new Twig_Error_Runtime('Variables passed to the \"with\" tag must be a hash.');\n")
->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a hash.', ")
->repr($node->getTemplateLine())
->raw(", \$this->getSourceContext());\n")
->outdent()
->write("}\n")
->write(sprintf("\$%s = twig_to_array(\$%s);\n", $varsName, $varsName))
;
if ($this->getAttribute('only')) {
$compiler->write("\$context = array('_parent' => \$context);\n");
$compiler->write("\$context = ['_parent' => \$context];\n");
} else {
$compiler->write("\$context['_parent'] = \$context;\n");
}
$compiler->write(sprintf("\$context = array_merge(\$context, \$%s);\n", $varsName));
$compiler->write(sprintf("\$context = \$this->env->mergeGlobals(array_merge(\$context, \$%s));\n", $varsName));
} else {
$compiler->write("\$context['_parent'] = \$context;\n");
}
@@ -61,4 +69,4 @@ class Twig_Node_With extends Twig_Node
}
}
class_alias('Twig_Node_With', 'Twig\Node\WithNode', false);
class_alias('Twig\Node\WithNode', 'Twig_Node_With');