diff --git a/CHANGELOG b/CHANGELOG index 6a0b56ee7..496115fda 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,6 @@ * 2.8.2 (2019-XX-XX) - * n/a + * added template line number to twig_get_attribute() * 2.8.1 (2019-04-16) diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index 227c576e2..fde808946 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -1511,6 +1511,7 @@ function twig_array_batch($items, $size, $fill = null, $preserveKeys = true) * @param string $type The type of attribute (@see \Twig\Template constants) * @param bool $isDefinedTest Whether this is only a defined check * @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not + * @param int $lineno The template line where the attribute was called * * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true * @@ -1518,7 +1519,7 @@ function twig_array_batch($items, $size, $fill = null, $preserveKeys = true) * * @internal */ -function twig_get_attribute(Environment $env, Source $source, $object, $item, array $arguments = [], $type = /* Template::ANY_CALL */ 'any', $isDefinedTest = false, $ignoreStrictCheck = false, $sandboxed = false) +function twig_get_attribute(Environment $env, Source $source, $object, $item, array $arguments = [], $type = /* Template::ANY_CALL */ 'any', $isDefinedTest = false, $ignoreStrictCheck = false, $sandboxed = false, int $lineno = -1) { // array if (/* Template::METHOD_CALL */ 'method' !== $type) { @@ -1565,7 +1566,7 @@ function twig_get_attribute(Environment $env, Source $source, $object, $item, ar $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); } - throw new RuntimeError($message, -1, $source); + throw new RuntimeError($message, $lineno, $source); } } @@ -1586,11 +1587,11 @@ function twig_get_attribute(Environment $env, Source $source, $object, $item, ar $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); } - throw new RuntimeError($message, -1, $source); + throw new RuntimeError($message, $lineno, $source); } if ($object instanceof Template) { - throw new RuntimeError('Accessing \Twig\Template attributes is forbidden.'); + throw new RuntimeError('Accessing \Twig\Template attributes is forbidden.', $lineno, $source); } // object property @@ -1670,7 +1671,7 @@ function twig_get_attribute(Environment $env, Source $source, $object, $item, ar return; } - throw new RuntimeError(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()"/"has%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), -1, $source); + throw new RuntimeError(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()"/"has%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), $lineno, $source); } if ($isDefinedTest) { diff --git a/src/Node/Expression/GetAttrExpression.php b/src/Node/Expression/GetAttrExpression.php index b3ac77a10..7b066170e 100644 --- a/src/Node/Expression/GetAttrExpression.php +++ b/src/Node/Expression/GetAttrExpression.php @@ -63,42 +63,26 @@ class GetAttrExpression extends AbstractExpression $this->getNode('node')->setAttribute('ignore_strict_check', true); } - $compiler->subcompile($this->getNode('node')); + $compiler + ->subcompile($this->getNode('node')) + ->raw(', ') + ->subcompile($this->getNode('attribute')) + ; - $compiler->raw(', ')->subcompile($this->getNode('attribute')); - - // only generate optional arguments when needed (to make generated code more readable) - $needFifth = $env->hasExtension(SandboxExtension::class); - $needFourth = $needFifth || $this->getAttribute('ignore_strict_check'); - $needThird = $needFourth || $this->getAttribute('is_defined_test'); - $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(', []'); - } + if ($this->hasNode('arguments')) { + $compiler->raw(', ')->subcompile($this->getNode('arguments')); + } else { + $compiler->raw(', []'); } - if ($needSecond) { - $compiler->raw(', ')->repr($this->getAttribute('type')); - } - - if ($needThird) { - $compiler->raw(', ')->repr($this->getAttribute('is_defined_test')); - } - - if ($needFourth) { - $compiler->raw(', ')->repr($this->getAttribute('ignore_strict_check')); - } - - if ($needFifth) { - $compiler->raw(', ')->repr($env->hasExtension(SandboxExtension::class)); - } - - $compiler->raw(')'); + $compiler->raw(', ') + ->repr($this->getAttribute('type')) + ->raw(', ')->repr($this->getAttribute('is_defined_test')) + ->raw(', ')->repr($this->getAttribute('ignore_strict_check')) + ->raw(', ')->repr($env->hasExtension(SandboxExtension::class)) + ->raw(', ')->repr($this->getNode('node')->getTemplateLine()) + ->raw(')') + ; } } diff --git a/test/Twig/Tests/Node/Expression/GetAttrTest.php b/test/Twig/Tests/Node/Expression/GetAttrTest.php index be30770e9..e02d25b47 100644 --- a/test/Twig/Tests/Node/Expression/GetAttrTest.php +++ b/test/Twig/Tests/Node/Expression/GetAttrTest.php @@ -41,7 +41,7 @@ class Twig_Tests_Node_Expression_GetAttrTest extends NodeTestCase $attr = new ConstantExpression('bar', 1); $args = new ArrayExpression([], 1); $node = new GetAttrExpression($expr, $attr, $args, Template::ANY_CALL, 1); - $tests[] = [$node, sprintf('%s%s, "bar", [])', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1))]; + $tests[] = [$node, sprintf('%s%s, "bar", [], "any", false, false, false, 1)', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1))]; $node = new GetAttrExpression($expr, $attr, $args, Template::ARRAY_CALL, 1); $tests[] = [$node, '(($__internal_%s = // line 1'."\n". @@ -51,7 +51,7 @@ class Twig_Tests_Node_Expression_GetAttrTest extends NodeTestCase $args->addElement(new NameExpression('foo', 1)); $args->addElement(new ConstantExpression('bar', 1)); $node = new GetAttrExpression($expr, $attr, $args, Template::METHOD_CALL, 1); - $tests[] = [$node, sprintf('%s%s, "bar", [0 => %s, 1 => "bar"], "method")', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1), $this->getVariableGetter('foo'))]; + $tests[] = [$node, sprintf('%s%s, "bar", [0 => %s, 1 => "bar"], "method", false, false, false, 1)', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1), $this->getVariableGetter('foo'))]; return $tests; }