mirror of
https://github.com/twigphp/Twig.git
synced 2026-08-17 18:44:22 +00:00
Deprecate the fact that the extends and use tags are always allowed in a sandboxed template
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
# 3.12.0 (2024-XX-XX)
|
||||
|
||||
* Deprecate the fact that the `extends` and `use` tags are always allowed in a sandboxed template.
|
||||
This behavior will change in 4.0 where these tags will need to be explicitly allowed like any other tag.
|
||||
* Deprecate the "tag" constructor argument of the "Twig\Node\Node" class as the tag is now automatically set by the Parser when needed
|
||||
* Fix precedence of two-word tests when the first word is a valid test
|
||||
* Deprecate the `spaceless` filter
|
||||
* Deprecate some internal methods from `Parser`: `getBlockStack()`, `hasBlock()`, `getBlock()`, `hasMacro()`, `hasTraits()`, `getParent()`
|
||||
|
||||
+3
-3
@@ -487,7 +487,7 @@ Now, let's see the actual code of this class::
|
||||
$value = $parser->getExpressionParser()->parseExpression();
|
||||
$stream->expect(\Twig\Token::BLOCK_END_TYPE);
|
||||
|
||||
return new CustomSetNode($name, $value, $token->getLine(), $this->getTag());
|
||||
return new CustomSetNode($name, $value, $token->getLine());
|
||||
}
|
||||
|
||||
public function getTag()
|
||||
@@ -534,9 +534,9 @@ The ``CustomSetNode`` class itself is quite short::
|
||||
|
||||
class CustomSetNode extends \Twig\Node\Node
|
||||
{
|
||||
public function __construct($name, \Twig\Node\Expression\AbstractExpression $value, $line, $tag = null)
|
||||
public function __construct($name, \Twig\Node\Expression\AbstractExpression $value, $line)
|
||||
{
|
||||
parent::__construct(['value' => $value], ['name' => $name], $line, $tag);
|
||||
parent::__construct(['value' => $value], ['name' => $name], $line);
|
||||
}
|
||||
|
||||
public function compile(\Twig\Compiler $compiler)
|
||||
|
||||
+7
-1
@@ -467,7 +467,7 @@ The ``sandbox`` extension can be used to evaluate untrusted code. Access to
|
||||
unsafe attributes and methods is prohibited. The sandbox security is managed
|
||||
by a policy instance. By default, Twig comes with one policy class:
|
||||
``\Twig\Sandbox\SecurityPolicy``. This class allows you to white-list some
|
||||
tags, filters, properties, and methods::
|
||||
tags, filters, functions, properties, and methods::
|
||||
|
||||
$tags = ['if'];
|
||||
$filters = ['upper'];
|
||||
@@ -486,6 +486,12 @@ able to call the ``getTitle()`` and ``getBody()`` methods on ``Article``
|
||||
objects, and the ``title`` and ``body`` public properties. Everything else
|
||||
won't be allowed and will generate a ``\Twig\Sandbox\SecurityError`` exception.
|
||||
|
||||
.. caution::
|
||||
|
||||
The ``extends`` and ``use`` tags are always allowed in a sandboxed
|
||||
template. That behavior will change in 4.0 where these tags will need to be
|
||||
explicitly allowed like any other tag.
|
||||
|
||||
The policy object is the first argument of the sandbox constructor::
|
||||
|
||||
$sandbox = new \Twig\Extension\SandboxExtension($policy);
|
||||
|
||||
+18
-4
@@ -35,6 +35,13 @@ Extensions
|
||||
Nodes
|
||||
-----
|
||||
|
||||
* The "tag" constructor parameter of the ``Twig\Node\Node`` class is deprecated
|
||||
as of Twig 3.12 as the tag is now automatically set by the Parser when
|
||||
needed.
|
||||
|
||||
* Passing a second argument to "ExpressionParser::parseFilterExpressionRaw()"
|
||||
is deprecated as of Twig 3.12.
|
||||
|
||||
* The following ``Twig\Node\Node`` methods will take a string or an integer
|
||||
(instead of just a string) in Twig 4.0 for their "name" argument:
|
||||
``getNode()``, ``hasNode()``, ``setNode()``, ``removeNode()``, and
|
||||
@@ -89,9 +96,9 @@ Nodes
|
||||
|
||||
class NotReadyFilterExpression extends FilterExpression
|
||||
{
|
||||
public function __construct(Node $node, ConstantExpression $filter, Node $arguments, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $node, ConstantExpression $filter, Node $arguments, int $lineno)
|
||||
{
|
||||
parent::__construct($node, $filter, $arguments, $lineno, $tag);
|
||||
parent::__construct($node, $filter, $arguments, $lineno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,9 +124,9 @@ Nodes
|
||||
class ReadyFilterExpression extends FilterExpression
|
||||
{
|
||||
#[FirstClassTwigCallableReady]
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno)
|
||||
{
|
||||
parent::__construct($node, $filter, $arguments, $lineno, $tag);
|
||||
parent::__construct($node, $filter, $arguments, $lineno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,3 +193,10 @@ Filters
|
||||
|
||||
* The ``spaceless`` filter is deprecated as of Twig 3.12 and will be removed in
|
||||
Twig 4.0.
|
||||
|
||||
Sandbox
|
||||
-------
|
||||
|
||||
* Having the ``extends`` and ``use`` tags allowed by default in a sandbox is
|
||||
deprecated as of Twig 3.12. You will need to explicitly allow them if needed
|
||||
in 4.0.
|
||||
|
||||
@@ -18,7 +18,7 @@ use Twig\Node\Node;
|
||||
|
||||
class CacheNode extends AbstractExpression
|
||||
{
|
||||
public function __construct(AbstractExpression $key, ?AbstractExpression $ttl, ?AbstractExpression $tags, Node $body, int $lineno, string $tag)
|
||||
public function __construct(AbstractExpression $key, ?AbstractExpression $ttl, ?AbstractExpression $tags, Node $body, int $lineno)
|
||||
{
|
||||
$body = new CaptureNode($body, $lineno);
|
||||
$body->setAttribute('raw', true);
|
||||
@@ -31,7 +31,7 @@ class CacheNode extends AbstractExpression
|
||||
$nodes['tags'] = $tags;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, [], $lineno, $tag);
|
||||
parent::__construct($nodes, [], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -56,9 +56,9 @@ class CacheTokenParser extends AbstractTokenParser
|
||||
$body = $this->parser->subparse([$this, 'decideCacheEnd'], true);
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
$body = new CacheNode($key, $ttl, $tags, $body, $token->getLine(), $this->getTag());
|
||||
$body = new CacheNode($key, $ttl, $tags, $body, $token->getLine());
|
||||
|
||||
return new PrintNode(new RawFilter($body), $token->getLine(), $this->getTag());
|
||||
return new PrintNode(new RawFilter($body), $token->getLine());
|
||||
}
|
||||
|
||||
public function decideCacheEnd(Token $token): bool
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"require": {
|
||||
"php": ">=8.0.2",
|
||||
"symfony/cache": "^5.4|^6.4|^7.0",
|
||||
"twig/twig": "^3.11"
|
||||
"twig/twig": "^3.12"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "^6.4|^7.0"
|
||||
|
||||
@@ -568,8 +568,12 @@ class ExpressionParser
|
||||
return $this->parseFilterExpressionRaw($node);
|
||||
}
|
||||
|
||||
public function parseFilterExpressionRaw($node, $tag = null)
|
||||
public function parseFilterExpressionRaw($node)
|
||||
{
|
||||
if (func_num_args() > 1) {
|
||||
trigger_deprecation('twig/twig', '3.12', 'Passing a second argument to "%s()" is deprecated.', __METHOD__);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
$token = $this->parser->getStream()->expect(Token::NAME_TYPE);
|
||||
|
||||
@@ -590,7 +594,7 @@ class ExpressionParser
|
||||
trigger_deprecation('twig/twig', '3.12', 'Twig node "%s" is not marked as ready for passing a "TwigFilter" in the constructor instead of its name; please update your code and then add #[FirstClassTwigCallableReady] attribute to the constructor.', $class);
|
||||
}
|
||||
|
||||
$node = new $class($node, $ready ? $filter : new ConstantExpression($filter->getName(), $token->getLine()), $arguments, $token->getLine(), $tag);
|
||||
$node = new $class($node, $ready ? $filter : new ConstantExpression($filter->getName(), $token->getLine()), $arguments, $token->getLine());
|
||||
|
||||
if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '|')) {
|
||||
break;
|
||||
|
||||
@@ -28,9 +28,9 @@ use Twig\Compiler;
|
||||
#[YieldReady]
|
||||
class AutoEscapeNode extends Node
|
||||
{
|
||||
public function __construct($value, Node $body, int $lineno, string $tag = 'autoescape')
|
||||
public function __construct($value, Node $body, int $lineno)
|
||||
{
|
||||
parent::__construct(['body' => $body], ['value' => $value], $lineno, $tag);
|
||||
parent::__construct(['body' => $body], ['value' => $value], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -23,9 +23,9 @@ use Twig\Compiler;
|
||||
#[YieldReady]
|
||||
class BlockNode extends Node
|
||||
{
|
||||
public function __construct(string $name, Node $body, int $lineno, ?string $tag = null)
|
||||
public function __construct(string $name, Node $body, int $lineno)
|
||||
{
|
||||
parent::__construct(['body' => $body], ['name' => $name], $lineno, $tag);
|
||||
parent::__construct(['body' => $body], ['name' => $name], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -23,9 +23,9 @@ use Twig\Compiler;
|
||||
#[YieldReady]
|
||||
class BlockReferenceNode extends Node implements NodeOutputInterface
|
||||
{
|
||||
public function __construct(string $name, int $lineno, ?string $tag = null)
|
||||
public function __construct(string $name, int $lineno)
|
||||
{
|
||||
parent::__construct([], ['name' => $name], $lineno, $tag);
|
||||
parent::__construct([], ['name' => $name], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -22,9 +22,9 @@ use Twig\Compiler;
|
||||
#[YieldReady]
|
||||
class CaptureNode extends Node
|
||||
{
|
||||
public function __construct(Node $body, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $body, int $lineno)
|
||||
{
|
||||
parent::__construct(['body' => $body], ['raw' => false], $lineno, $tag);
|
||||
parent::__construct(['body' => $body], ['raw' => false], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -30,7 +30,7 @@ class CheckToStringNode extends AbstractExpression
|
||||
{
|
||||
public function __construct(AbstractExpression $expr)
|
||||
{
|
||||
parent::__construct(['expr' => $expr], [], $expr->getTemplateLine(), $expr->getNodeTag());
|
||||
parent::__construct(['expr' => $expr], [], $expr->getTemplateLine());
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -24,9 +24,9 @@ use Twig\Node\Expression\ConstantExpression;
|
||||
#[YieldReady]
|
||||
class DeprecatedNode extends Node
|
||||
{
|
||||
public function __construct(AbstractExpression $expr, int $lineno, ?string $tag = null)
|
||||
public function __construct(AbstractExpression $expr, int $lineno)
|
||||
{
|
||||
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
||||
parent::__construct(['expr' => $expr], [], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
+2
-2
@@ -23,9 +23,9 @@ use Twig\Node\Expression\AbstractExpression;
|
||||
#[YieldReady]
|
||||
class DoNode extends Node
|
||||
{
|
||||
public function __construct(AbstractExpression $expr, int $lineno, ?string $tag = null)
|
||||
public function __construct(AbstractExpression $expr, int $lineno)
|
||||
{
|
||||
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
||||
parent::__construct(['expr' => $expr], [], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -25,9 +25,9 @@ use Twig\Node\Expression\ConstantExpression;
|
||||
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(string $name, int $index, ?AbstractExpression $variables, bool $only, bool $ignoreMissing, int $lineno, ?string $tag = null)
|
||||
public function __construct(string $name, int $index, ?AbstractExpression $variables, bool $only, bool $ignoreMissing, int $lineno)
|
||||
{
|
||||
parent::__construct(new ConstantExpression('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
|
||||
parent::__construct(new ConstantExpression('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno);
|
||||
|
||||
$this->setAttribute('name', $name);
|
||||
$this->setAttribute('index', $index);
|
||||
|
||||
@@ -21,9 +21,9 @@ use Twig\Node\Node;
|
||||
*/
|
||||
class ArrowFunctionExpression extends AbstractExpression
|
||||
{
|
||||
public function __construct(AbstractExpression $expr, Node $names, $lineno, $tag = null)
|
||||
public function __construct(AbstractExpression $expr, Node $names, $lineno)
|
||||
{
|
||||
parent::__construct(['expr' => $expr, 'names' => $names], [], $lineno, $tag);
|
||||
parent::__construct(['expr' => $expr, 'names' => $names], [], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -22,14 +22,14 @@ use Twig\Node\Node;
|
||||
*/
|
||||
class BlockReferenceExpression extends AbstractExpression
|
||||
{
|
||||
public function __construct(Node $name, ?Node $template, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $name, ?Node $template, int $lineno)
|
||||
{
|
||||
$nodes = ['name' => $name];
|
||||
if (null !== $template) {
|
||||
$nodes['template'] = $template;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, ['is_defined_test' => false, 'output' => false], $lineno, $tag);
|
||||
parent::__construct($nodes, ['is_defined_test' => false, 'output' => false], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -34,7 +34,7 @@ use Twig\TwigTest;
|
||||
class DefaultFilter extends FilterExpression
|
||||
{
|
||||
#[FirstClassTwigCallableReady]
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno)
|
||||
{
|
||||
if ($filter instanceof TwigFilter) {
|
||||
$name = $filter->getName();
|
||||
@@ -53,7 +53,7 @@ class DefaultFilter extends FilterExpression
|
||||
$node = $default;
|
||||
}
|
||||
|
||||
parent::__construct($node, $filter, $arguments, $lineno, $tag);
|
||||
parent::__construct($node, $filter, $arguments, $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -24,9 +24,9 @@ use Twig\TwigFilter;
|
||||
class RawFilter extends FilterExpression
|
||||
{
|
||||
#[FirstClassTwigCallableReady]
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression|null $filter = null, ?Node $arguments = null, int $lineno = 0, ?string $tag = null)
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression|null $filter = null, ?Node $arguments = null, int $lineno = 0)
|
||||
{
|
||||
parent::__construct($node, $filter ?: new TwigFilter('raw', null, ['is_safe' => ['all']]), $arguments ?: new Node(), $lineno ?: $node->getTemplateLine(), $tag ?: $node->getNodeTag());
|
||||
parent::__construct($node, $filter ?: new TwigFilter('raw', null, ['is_safe' => ['all']]), $arguments ?: new Node(), $lineno ?: $node->getTemplateLine());
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -21,7 +21,7 @@ use Twig\TwigFilter;
|
||||
class FilterExpression extends CallExpression
|
||||
{
|
||||
#[FirstClassTwigCallableReady]
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno)
|
||||
{
|
||||
if ($filter instanceof TwigFilter) {
|
||||
$name = $filter->getName();
|
||||
@@ -32,7 +32,7 @@ class FilterExpression extends CallExpression
|
||||
trigger_deprecation('twig/twig', '3.12', 'Not passing an instance of "TwigFilter" when creating a "%s" filter of type "%s" is deprecated.', $name, static::class);
|
||||
}
|
||||
|
||||
parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], ['name' => $name, 'type' => 'filter'], $lineno, $tag);
|
||||
parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], ['name' => $name, 'type' => 'filter'], $lineno);
|
||||
|
||||
if ($filter instanceof TwigFilter) {
|
||||
$this->setAttribute('twig_callable', $filter);
|
||||
|
||||
@@ -21,9 +21,9 @@ use Twig\Compiler;
|
||||
*/
|
||||
class ParentExpression extends AbstractExpression
|
||||
{
|
||||
public function __construct(string $name, int $lineno, ?string $tag = null)
|
||||
public function __construct(string $name, int $lineno)
|
||||
{
|
||||
parent::__construct([], ['output' => false, 'name' => $name], $lineno, $tag);
|
||||
parent::__construct([], ['output' => false, 'name' => $name], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -22,9 +22,9 @@ use Twig\Compiler;
|
||||
#[YieldReady]
|
||||
class FlushNode extends Node
|
||||
{
|
||||
public function __construct(int $lineno, string $tag)
|
||||
public function __construct(int $lineno)
|
||||
{
|
||||
parent::__construct([], [], $lineno, $tag);
|
||||
parent::__construct([], [], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -22,9 +22,9 @@ use Twig\Compiler;
|
||||
#[YieldReady]
|
||||
class ForLoopNode extends Node
|
||||
{
|
||||
public function __construct(int $lineno, ?string $tag = null)
|
||||
public function __construct(int $lineno)
|
||||
{
|
||||
parent::__construct([], ['with_loop' => false, 'ifexpr' => false, 'else' => false], $lineno, $tag);
|
||||
parent::__construct([], ['with_loop' => false, 'ifexpr' => false, 'else' => false], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -27,16 +27,16 @@ class ForNode extends Node
|
||||
{
|
||||
private $loop;
|
||||
|
||||
public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, ?Node $ifexpr, Node $body, ?Node $else, int $lineno, ?string $tag = null)
|
||||
public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, ?Node $ifexpr, Node $body, ?Node $else, int $lineno)
|
||||
{
|
||||
$body = new Node([$body, $this->loop = new ForLoopNode($lineno, $tag)]);
|
||||
$body = new Node([$body, $this->loop = new ForLoopNode($lineno)]);
|
||||
|
||||
$nodes = ['key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body];
|
||||
if (null !== $else) {
|
||||
$nodes['else'] = $else;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, ['with_loop' => true], $lineno, $tag);
|
||||
parent::__construct($nodes, ['with_loop' => true], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
+2
-2
@@ -23,14 +23,14 @@ use Twig\Compiler;
|
||||
#[YieldReady]
|
||||
class IfNode extends Node
|
||||
{
|
||||
public function __construct(Node $tests, ?Node $else, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $tests, ?Node $else, int $lineno)
|
||||
{
|
||||
$nodes = ['tests' => $tests];
|
||||
if (null !== $else) {
|
||||
$nodes['else'] = $else;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, [], $lineno, $tag);
|
||||
parent::__construct($nodes, [], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -26,7 +26,7 @@ class ImportNode extends Node
|
||||
{
|
||||
public function __construct(AbstractExpression $expr, AbstractExpression $var, int $lineno, ?string $tag = null, bool $global = true)
|
||||
{
|
||||
parent::__construct(['expr' => $expr, 'var' => $var], ['global' => $global], $lineno, $tag);
|
||||
parent::__construct(['expr' => $expr, 'var' => $var], ['global' => $global], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -24,14 +24,14 @@ use Twig\Node\Expression\AbstractExpression;
|
||||
#[YieldReady]
|
||||
class IncludeNode extends Node implements NodeOutputInterface
|
||||
{
|
||||
public function __construct(AbstractExpression $expr, ?AbstractExpression $variables, bool $only, bool $ignoreMissing, int $lineno, ?string $tag = null)
|
||||
public function __construct(AbstractExpression $expr, ?AbstractExpression $variables, bool $only, bool $ignoreMissing, int $lineno)
|
||||
{
|
||||
$nodes = ['expr' => $expr];
|
||||
if (null !== $variables) {
|
||||
$nodes['variables'] = $variables;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, ['only' => $only, 'ignore_missing' => $ignoreMissing], $lineno, $tag);
|
||||
parent::__construct($nodes, ['only' => $only, 'ignore_missing' => $ignoreMissing], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -28,7 +28,7 @@ class MacroNode extends Node
|
||||
/**
|
||||
* @param BodyNode $body
|
||||
*/
|
||||
public function __construct(string $name, Node $body, Node $arguments, int $lineno, ?string $tag = null)
|
||||
public function __construct(string $name, Node $body, Node $arguments, int $lineno)
|
||||
{
|
||||
if (!$body instanceof BodyNode) {
|
||||
trigger_deprecation('twig/twig', '3.12', \sprintf('Not passing a "%s" instance as the "body" argument of the "%s" constructor is deprecated.', BodyNode::class, static::class));
|
||||
@@ -40,7 +40,7 @@ class MacroNode extends Node
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name], $lineno, $tag);
|
||||
parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
+17
-3
@@ -42,9 +42,8 @@ class Node implements \Countable, \IteratorAggregate
|
||||
* @param array<string|int, Node> $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 = [], int $lineno = 0, ?string $tag = null)
|
||||
public function __construct(array $nodes = [], array $attributes = [], int $lineno = 0)
|
||||
{
|
||||
foreach ($nodes as $name => $node) {
|
||||
if (!$node instanceof self) {
|
||||
@@ -54,7 +53,10 @@ class Node implements \Countable, \IteratorAggregate
|
||||
$this->nodes = $nodes;
|
||||
$this->attributes = $attributes;
|
||||
$this->lineno = $lineno;
|
||||
$this->tag = $tag;
|
||||
|
||||
if (func_num_args() > 3) {
|
||||
trigger_deprecation('twig/twig', '3.12', sprintf('The "tag" constructor argument of the "%s" class is deprecated and ignored (check which TokenParser class set it to "%s"), the tag is now automatically set by the Parser when needed.', static::class, func_get_arg(3) ?: 'null'));
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
@@ -117,6 +119,18 @@ class Node implements \Countable, \IteratorAggregate
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function setNodeTag(string $tag): void
|
||||
{
|
||||
if ($this->tag) {
|
||||
throw new \LogicException('The tag of a node can only be set once.');
|
||||
}
|
||||
|
||||
$this->tag = $tag;
|
||||
}
|
||||
|
||||
public function hasAttribute(string $name): bool
|
||||
{
|
||||
return \array_key_exists($name, $this->attributes);
|
||||
|
||||
@@ -24,9 +24,9 @@ use Twig\Node\Expression\AbstractExpression;
|
||||
#[YieldReady]
|
||||
class PrintNode extends Node implements NodeOutputInterface
|
||||
{
|
||||
public function __construct(AbstractExpression $expr, int $lineno, ?string $tag = null)
|
||||
public function __construct(AbstractExpression $expr, int $lineno)
|
||||
{
|
||||
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
||||
parent::__construct(['expr' => $expr], [], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -22,9 +22,9 @@ use Twig\Compiler;
|
||||
#[YieldReady]
|
||||
class SandboxNode extends Node
|
||||
{
|
||||
public function __construct(Node $body, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $body, int $lineno)
|
||||
{
|
||||
parent::__construct(['body' => $body], [], $lineno, $tag);
|
||||
parent::__construct(['body' => $body], [], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -23,7 +23,7 @@ use Twig\Node\Expression\ConstantExpression;
|
||||
#[YieldReady]
|
||||
class SetNode extends Node implements NodeCaptureInterface
|
||||
{
|
||||
public function __construct(bool $capture, Node $names, Node $values, int $lineno, ?string $tag = null)
|
||||
public function __construct(bool $capture, Node $names, Node $values, int $lineno)
|
||||
{
|
||||
/*
|
||||
* Optimizes the node when capture is used for a large block of text.
|
||||
@@ -41,7 +41,7 @@ class SetNode extends Node implements NodeCaptureInterface
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct(['names' => $names, 'values' => $values], ['capture' => $capture, 'safe' => $safe], $lineno, $tag);
|
||||
parent::__construct(['names' => $names, 'values' => $values], ['capture' => $capture, 'safe' => $safe], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -22,14 +22,14 @@ use Twig\Compiler;
|
||||
#[YieldReady]
|
||||
class WithNode extends Node
|
||||
{
|
||||
public function __construct(Node $body, ?Node $variables, bool $only, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $body, ?Node $variables, bool $only, int $lineno)
|
||||
{
|
||||
$nodes = ['body' => $body];
|
||||
if (null !== $variables) {
|
||||
$nodes['variables'] = $variables;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, ['only' => $only], $lineno, $tag);
|
||||
parent::__construct($nodes, ['only' => $only], $lineno);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
|
||||
@@ -46,7 +46,7 @@ final class MacroAutoImportNodeVisitor implements NodeVisitorInterface
|
||||
if ($node instanceof ModuleNode) {
|
||||
$this->inAModule = false;
|
||||
if ($this->hasMacroCalls) {
|
||||
$node->getNode('constructor_end')->setNode('_auto_macro_import', new ImportNode(new NameExpression('_self', 0), new AssignNameExpression('_self', 0), 0, 'import', true));
|
||||
$node->getNode('constructor_end')->setNode('_auto_macro_import', new ImportNode(new NameExpression('_self', 0), new AssignNameExpression('_self', 0), 0, null, true));
|
||||
}
|
||||
} elseif ($this->inAModule) {
|
||||
if (
|
||||
|
||||
@@ -176,6 +176,7 @@ class Parser
|
||||
if (!$node) {
|
||||
trigger_deprecation('twig/twig', '3.12', 'Returning "null" from "%s" is deprecated and forbidden by "TokenParserInterface".', $subparser::class);
|
||||
} else {
|
||||
$node->setNodeTag($subparser->getTag());
|
||||
$rv[] = $node;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -68,7 +68,13 @@ final class SecurityPolicy implements SecurityPolicyInterface
|
||||
{
|
||||
foreach ($tags as $tag) {
|
||||
if (!\in_array($tag, $this->allowedTags)) {
|
||||
throw new SecurityNotAllowedTagError(\sprintf('Tag "%s" is not allowed.', $tag), $tag);
|
||||
if ('extends' === $tag) {
|
||||
trigger_deprecation('twig/twig', '3.12', 'The "extends" tag is always allowed in sandboxes, but won\'t be in 4.0, please enable it explicitely in your sandbox policy if needed.');
|
||||
} elseif ('use' === $tag) {
|
||||
trigger_deprecation('twig/twig', '3.12', 'The "use" tag is always allowed in sandboxes, but won\'t be in 4.0, please enable it explicitely in your sandbox policy if needed.');
|
||||
} else {
|
||||
throw new SecurityNotAllowedTagError(\sprintf('Tag "%s" is not allowed.', $tag), $tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,16 +36,16 @@ final class ApplyTokenParser extends AbstractTokenParser
|
||||
$ref = new TempNameExpression($name, $lineno);
|
||||
$ref->setAttribute('always_defined', true);
|
||||
|
||||
$filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
|
||||
$filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref);
|
||||
|
||||
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
||||
$body = $this->parser->subparse([$this, 'decideApplyEnd'], true);
|
||||
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new Node([
|
||||
new SetNode(true, $ref, $body, $lineno, $this->getTag()),
|
||||
new PrintNode($filter, $lineno, $this->getTag()),
|
||||
]);
|
||||
new SetNode(true, $ref, $body, $lineno),
|
||||
new PrintNode($filter, $lineno),
|
||||
], [], $lineno);
|
||||
}
|
||||
|
||||
public function decideApplyEnd(Token $token): bool
|
||||
|
||||
@@ -43,7 +43,7 @@ final class AutoEscapeTokenParser extends AbstractTokenParser
|
||||
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new AutoEscapeNode($value, $body, $lineno, $this->getTag());
|
||||
return new AutoEscapeNode($value, $body, $lineno);
|
||||
}
|
||||
|
||||
public function decideBlockEnd(Token $token): bool
|
||||
|
||||
@@ -60,7 +60,7 @@ final class BlockTokenParser extends AbstractTokenParser
|
||||
$this->parser->popBlockStack();
|
||||
$this->parser->popLocalScope();
|
||||
|
||||
return new BlockReferenceNode($name, $lineno, $this->getTag());
|
||||
return new BlockReferenceNode($name, $lineno);
|
||||
}
|
||||
|
||||
public function decideBlockEnd(Token $token): bool
|
||||
|
||||
@@ -35,7 +35,7 @@ final class DeprecatedTokenParser extends AbstractTokenParser
|
||||
$stream = $this->parser->getStream();
|
||||
$expressionParser = $this->parser->getExpressionParser();
|
||||
$expr = $expressionParser->parseExpression();
|
||||
$node = new DeprecatedNode($expr, $token->getLine(), $this->getTag());
|
||||
$node = new DeprecatedNode($expr, $token->getLine());
|
||||
|
||||
while ($stream->test(Token::NAME_TYPE)) {
|
||||
$k = $stream->getCurrent()->getValue();
|
||||
|
||||
@@ -28,7 +28,7 @@ final class DoTokenParser extends AbstractTokenParser
|
||||
|
||||
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new DoNode($expr, $token->getLine(), $this->getTag());
|
||||
return new DoNode($expr, $token->getLine());
|
||||
}
|
||||
|
||||
public function getTag(): string
|
||||
|
||||
@@ -58,7 +58,7 @@ final class EmbedTokenParser extends IncludeTokenParser
|
||||
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new EmbedNode($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
|
||||
return new EmbedNode($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine());
|
||||
}
|
||||
|
||||
public function decideBlockEnd(Token $token): bool
|
||||
|
||||
@@ -39,7 +39,7 @@ final class ExtendsTokenParser extends AbstractTokenParser
|
||||
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new Node();
|
||||
return new Node([], [], $token->getLine());
|
||||
}
|
||||
|
||||
public function getTag(): string
|
||||
|
||||
@@ -28,7 +28,7 @@ final class FlushTokenParser extends AbstractTokenParser
|
||||
{
|
||||
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new FlushNode($token->getLine(), $this->getTag());
|
||||
return new FlushNode($token->getLine());
|
||||
}
|
||||
|
||||
public function getTag(): string
|
||||
|
||||
@@ -58,7 +58,7 @@ final class ForTokenParser extends AbstractTokenParser
|
||||
}
|
||||
$valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine());
|
||||
|
||||
return new ForNode($keyTarget, $valueTarget, $seq, null, $body, $else, $lineno, $this->getTag());
|
||||
return new ForNode($keyTarget, $valueTarget, $seq, null, $body, $else, $lineno);
|
||||
}
|
||||
|
||||
public function decideForFork(Token $token): bool
|
||||
|
||||
@@ -50,7 +50,7 @@ final class FromTokenParser extends AbstractTokenParser
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
$var = new AssignNameExpression($this->parser->getVarName(), $token->getLine());
|
||||
$node = new ImportNode($macro, $var, $token->getLine(), $this->getTag(), $this->parser->isMainScope());
|
||||
$node = new ImportNode($macro, $var, $token->getLine(), null, $this->parser->isMainScope());
|
||||
|
||||
foreach ($targets as $name => $alias) {
|
||||
$this->parser->addImportedSymbol('function', $alias, 'macro_'.$name, $var);
|
||||
|
||||
@@ -69,7 +69,7 @@ final class IfTokenParser extends AbstractTokenParser
|
||||
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new IfNode(new Node($tests), $else, $lineno, $this->getTag());
|
||||
return new IfNode(new Node($tests), $else, $lineno);
|
||||
}
|
||||
|
||||
public function decideIfFork(Token $token): bool
|
||||
|
||||
@@ -34,7 +34,7 @@ final class ImportTokenParser extends AbstractTokenParser
|
||||
|
||||
$this->parser->addImportedSymbol('template', $var->getAttribute('name'));
|
||||
|
||||
return new ImportNode($macro, $var, $token->getLine(), $this->getTag(), $this->parser->isMainScope());
|
||||
return new ImportNode($macro, $var, $token->getLine(), null, $this->parser->isMainScope());
|
||||
}
|
||||
|
||||
public function getTag(): string
|
||||
|
||||
@@ -33,7 +33,7 @@ class IncludeTokenParser extends AbstractTokenParser
|
||||
|
||||
[$variables, $only, $ignoreMissing] = $this->parseArguments();
|
||||
|
||||
return new IncludeNode($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
|
||||
return new IncludeNode($expr, $variables, $only, $ignoreMissing, $token->getLine());
|
||||
}
|
||||
|
||||
protected function parseArguments()
|
||||
|
||||
@@ -49,9 +49,9 @@ final class MacroTokenParser extends AbstractTokenParser
|
||||
$this->parser->popLocalScope();
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
$this->parser->setMacro($name, new MacroNode($name, new BodyNode([$body]), $arguments, $lineno, $this->getTag()));
|
||||
$this->parser->setMacro($name, new MacroNode($name, new BodyNode([$body]), $arguments, $lineno));
|
||||
|
||||
return new Node();
|
||||
return new Node([], [], $lineno);
|
||||
}
|
||||
|
||||
public function decideBlockEnd(Token $token): bool
|
||||
|
||||
@@ -51,7 +51,7 @@ final class SandboxTokenParser extends AbstractTokenParser
|
||||
}
|
||||
}
|
||||
|
||||
return new SandboxNode($body, $token->getLine(), $this->getTag());
|
||||
return new SandboxNode($body, $token->getLine());
|
||||
}
|
||||
|
||||
public function decideBlockEnd(Token $token): bool
|
||||
|
||||
@@ -58,7 +58,7 @@ final class SetTokenParser extends AbstractTokenParser
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
}
|
||||
|
||||
return new SetNode($capture, $names, $values, $lineno, $this->getTag());
|
||||
return new SetNode($capture, $names, $values, $lineno);
|
||||
}
|
||||
|
||||
public function decideBlockEnd(Token $token): bool
|
||||
|
||||
@@ -63,7 +63,7 @@ final class UseTokenParser extends AbstractTokenParser
|
||||
|
||||
$this->parser->addTrait(new Node(['template' => $template, 'targets' => new Node($targets)]));
|
||||
|
||||
return new Node();
|
||||
return new Node([], [], $token->getLine());
|
||||
}
|
||||
|
||||
public function getTag(): string
|
||||
|
||||
@@ -41,7 +41,7 @@ final class WithTokenParser extends AbstractTokenParser
|
||||
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new WithNode($body, $variables, $only, $token->getLine(), $this->getTag());
|
||||
return new WithNode($body, $variables, $only, $token->getLine());
|
||||
}
|
||||
|
||||
public function decideWithEnd(Token $token): bool
|
||||
|
||||
@@ -533,7 +533,7 @@ class EnvironmentTest_TokenParser extends AbstractTokenParser
|
||||
{
|
||||
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new EnvironmentTest_LegacyEchoingNode();
|
||||
return new EnvironmentTest_LegacyEchoingNode([], [], 1);
|
||||
}
|
||||
|
||||
public function getTag(): string
|
||||
|
||||
@@ -605,9 +605,9 @@ class NotReadyFunctionExpression extends FunctionExpression
|
||||
|
||||
class NotReadyFilterExpression extends FilterExpression
|
||||
{
|
||||
public function __construct(Node $node, ConstantExpression $filter, Node $arguments, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $node, ConstantExpression $filter, Node $arguments, int $lineno)
|
||||
{
|
||||
parent::__construct($node, $filter, $arguments, $lineno, $tag);
|
||||
parent::__construct($node, $filter, $arguments, $lineno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,9 +643,9 @@ class ReadyFunctionExpression extends FunctionExpression
|
||||
class ReadyFilterExpression extends FilterExpression
|
||||
{
|
||||
#[FirstClassTwigCallableReady]
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno, ?string $tag = null)
|
||||
public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno)
|
||||
{
|
||||
parent::__construct($node, $filter, $arguments, $lineno, $tag);
|
||||
parent::__construct($node, $filter, $arguments, $lineno);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Twig\Tests\Extension;
|
||||
*/
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||
use Twig\Environment;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Extension\SandboxExtension;
|
||||
@@ -28,6 +29,8 @@ use Twig\Source;
|
||||
|
||||
class SandboxTest extends TestCase
|
||||
{
|
||||
use ExpectDeprecationTrait;
|
||||
|
||||
protected static $params;
|
||||
protected static $templates;
|
||||
|
||||
@@ -60,15 +63,71 @@ class SandboxTest extends TestCase
|
||||
'1_syntax_error' => '{% syntax error }}',
|
||||
'1_childobj_parentmethod' => '{{ child_obj.ParentMethod() }}',
|
||||
'1_childobj_childmethod' => '{{ child_obj.ChildMethod() }}',
|
||||
'1_empty' => '',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getSandboxedForCoreTagsTests
|
||||
*/
|
||||
public function testSandboxForCoreTags(string $tag, string $template)
|
||||
{
|
||||
$this->expectException(SecurityError::class);
|
||||
$this->expectExceptionMessageMatches(sprintf('/Tag "%s" is not allowed in "index \(string template .+?\)" at line 1/', $tag));
|
||||
|
||||
$twig = $this->getEnvironment(true, [], self::$templates, []);
|
||||
$twig->createTemplate($template, 'index')->render([]);
|
||||
}
|
||||
|
||||
public function getSandboxedForCoreTagsTests()
|
||||
{
|
||||
yield ['apply', '{% apply upper %}foo{% endapply %}'];
|
||||
yield ['autoescape', '{% autoescape %}foo{% endautoescape %}'];
|
||||
yield ['block', '{% block foo %}foo{% endblock %}'];
|
||||
yield ['deprecated', '{% deprecated "message" %}'];
|
||||
yield ['do', '{% do 1 + 2 %}'];
|
||||
yield ['embed', '{% embed "base.twig" %}{% endembed %}'];
|
||||
// To be uncommented in 4.0
|
||||
//yield ['extends', '{% extends "base.twig" %}'];
|
||||
yield ['flush', '{% flush %}'];
|
||||
yield ['for', '{% for i in 1..2 %}{% endfor %}'];
|
||||
yield ['from', '{% from "macros" import foo %}'];
|
||||
yield ['if', '{% if false %}{% endif %}'];
|
||||
yield ['import', '{% import "macros" as macros %}'];
|
||||
yield ['include', '{% include "macros" %}'];
|
||||
yield ['macro', '{% macro foo() %}{% endmacro %}'];
|
||||
yield ['sandbox', '{% sandbox %}{% endsandbox %}'];
|
||||
yield ['set', '{% set foo = 1 %}'];
|
||||
// To be uncommented in 4.0
|
||||
//yield ['use', '{% use "1_empty" %}'];
|
||||
yield ['with', '{% with foo %}{% endwith %}'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getSandboxedForExtendsAndUseTagsTests
|
||||
*
|
||||
* @group legacy
|
||||
*/
|
||||
public function testSandboxForExtendsAndUseTags(string $tag, string $template)
|
||||
{
|
||||
$this->expectDeprecation(sprintf('Since twig/twig 3.12: The "%s" tag is always allowed in sandboxes, but won\'t be in 4.0, please enable it explicitely in your sandbox policy if needed.', $tag));
|
||||
|
||||
$twig = $this->getEnvironment(true, [], self::$templates, []);
|
||||
$twig->createTemplate($template, 'index')->render([]);
|
||||
}
|
||||
|
||||
public function getSandboxedForExtendsAndUseTagsTests()
|
||||
{
|
||||
yield ['extends', '{% extends "1_empty" %}'];
|
||||
yield ['use', '{% use "1_empty" %}'];
|
||||
}
|
||||
|
||||
public function testSandboxWithInheritance()
|
||||
{
|
||||
$this->expectException(SecurityError::class);
|
||||
$this->expectExceptionMessage('Filter "json_encode" is not allowed in "1_child" at line 3.');
|
||||
|
||||
$twig = $this->getEnvironment(true, [], self::$templates, ['block']);
|
||||
$twig = $this->getEnvironment(true, [], self::$templates, ['extends', 'block']);
|
||||
$twig->load('1_child')->render([]);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class DeprecatedTest extends NodeTestCase
|
||||
$tests = [];
|
||||
|
||||
$expr = new ConstantExpression('This section is deprecated', 1);
|
||||
$node = new DeprecatedNode($expr, 1, 'deprecated');
|
||||
$node = new DeprecatedNode($expr, 1);
|
||||
$node->setSourceContext(new Source('', 'foo.twig'));
|
||||
$node->setNode('package', new ConstantExpression('twig/twig', 1));
|
||||
$node->setNode('version', new ConstantExpression('1.1', 1));
|
||||
@@ -50,7 +50,7 @@ EOF
|
||||
|
||||
$t = new Node([
|
||||
new ConstantExpression(true, 1),
|
||||
$dep = new DeprecatedNode($expr, 2, 'deprecated'),
|
||||
$dep = new DeprecatedNode($expr, 2),
|
||||
], [], 1);
|
||||
$node = new IfNode($t, null, 1);
|
||||
$node->setSourceContext(new Source('', 'foo.twig'));
|
||||
@@ -70,7 +70,7 @@ EOF
|
||||
$environment->addFunction($function = new TwigFunction('foo', 'Twig\Tests\Node\foo', []));
|
||||
|
||||
$expr = new FunctionExpression($function, new Node(), 1);
|
||||
$node = new DeprecatedNode($expr, 1, 'deprecated');
|
||||
$node = new DeprecatedNode($expr, 1);
|
||||
$node->setSourceContext(new Source('', 'foo.twig'));
|
||||
$node->setNode('package', new ConstantExpression('twig/twig', 1));
|
||||
$node->setNode('version', new ConstantExpression('1.1', 1));
|
||||
|
||||
@@ -57,7 +57,8 @@ EOF
|
||||
|
||||
public function testToStringWithTag()
|
||||
{
|
||||
$node = new Node([], [], 1, 'tag');
|
||||
$node = new Node([], [], 1);
|
||||
$node->setNodeTag('tag');
|
||||
|
||||
$this->assertEquals(<<<EOF
|
||||
Twig\Node\Node
|
||||
|
||||
@@ -227,7 +227,7 @@ class TestTokenParser extends AbstractTokenParser
|
||||
|
||||
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new Node([]);
|
||||
return new Node([], [], 1);
|
||||
}
|
||||
|
||||
public function getTag(): string
|
||||
|
||||
Reference in New Issue
Block a user