summaryrefslogtreecommitdiff
path: root/inc/lib/Twig/TokenParser/For.php
diff options
context:
space:
mode:
authorczaks <marcin@6irc.net>2013-08-05 06:03:40 -0400
committerczaks <marcin@6irc.net>2013-08-05 06:03:40 -0400
commita84c4510fccfdc0cfb6f187633daea10dc70f326 (patch)
tree6077f5211196ae40cac0184bb7cc67b81d320b0b /inc/lib/Twig/TokenParser/For.php
parent33c7abf11f3a9b5c0964a2d7a25533c2849dbc78 (diff)
parenta8327c3a37fd22d2aa5d63061c9d3eaa30ae425a (diff)
Merge branch 'master' of github.com:vichan-devel/Tinyboard
Conflicts: js/post-hider.js
Diffstat (limited to 'inc/lib/Twig/TokenParser/For.php')
-rw-r--r--inc/lib/Twig/TokenParser/For.php66
1 files changed, 58 insertions, 8 deletions
diff --git a/inc/lib/Twig/TokenParser/For.php b/inc/lib/Twig/TokenParser/For.php
index 5ce82979..98a6d079 100644
--- a/inc/lib/Twig/TokenParser/For.php
+++ b/inc/lib/Twig/TokenParser/For.php
@@ -33,32 +33,41 @@ class Twig_TokenParser_For extends Twig_TokenParser
public function parse(Twig_Token $token)
{
$lineno = $token->getLine();
+ $stream = $this->parser->getStream();
$targets = $this->parser->getExpressionParser()->parseAssignmentExpression();
- $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, 'in');
+ $stream->expect(Twig_Token::OPERATOR_TYPE, 'in');
$seq = $this->parser->getExpressionParser()->parseExpression();
$ifexpr = null;
- if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'if')) {
- $this->parser->getStream()->next();
+ if ($stream->test(Twig_Token::NAME_TYPE, 'if')) {
+ $stream->next();
$ifexpr = $this->parser->getExpressionParser()->parseExpression();
}
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
$body = $this->parser->subparse(array($this, 'decideForFork'));
- if ($this->parser->getStream()->next()->getValue() == 'else') {
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+ if ($stream->next()->getValue() == 'else') {
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
$else = $this->parser->subparse(array($this, 'decideForEnd'), true);
} else {
$else = null;
}
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
if (count($targets) > 1) {
$keyTarget = $targets->getNode(0);
+ $keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getLine());
$valueTarget = $targets->getNode(1);
+ $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine());
} else {
$keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno);
$valueTarget = $targets->getNode(0);
+ $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine());
+ }
+
+ if ($ifexpr) {
+ $this->checkLoopUsageCondition($stream, $ifexpr);
+ $this->checkLoopUsageBody($stream, $body);
}
return new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag());
@@ -74,10 +83,51 @@ class Twig_TokenParser_For extends Twig_TokenParser
return $token->test('endfor');
}
+ // the loop variable cannot be used in the condition
+ protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node)
+ {
+ if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
+ throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition', $node->getLine(), $stream->getFilename());
+ }
+
+ foreach ($node as $n) {
+ if (!$n) {
+ continue;
+ }
+
+ $this->checkLoopUsageCondition($stream, $n);
+ }
+ }
+
+ // check usage of non-defined loop-items
+ // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include)
+ protected function checkLoopUsageBody(Twig_TokenStream $stream, Twig_NodeInterface $node)
+ {
+ if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
+ $attribute = $node->getNode('attribute');
+ if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) {
+ throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition', $attribute->getAttribute('value')), $node->getLine(), $stream->getFilename());
+ }
+ }
+
+ // should check for parent.loop.XXX usage
+ if ($node instanceof Twig_Node_For) {
+ return;
+ }
+
+ foreach ($node as $n) {
+ if (!$n) {
+ continue;
+ }
+
+ $this->checkLoopUsageBody($stream, $n);
+ }
+ }
+
/**
* Gets the tag name associated with this token parser.
*
- * @param string The tag name
+ * @return string The tag name
*/
public function getTag()
{