aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc/Twig/TokenParser
diff options
context:
space:
mode:
Diffstat (limited to 'inc/Twig/TokenParser')
-rw-r--r--inc/Twig/TokenParser/AutoEscape.php89
-rw-r--r--inc/Twig/TokenParser/Block.php83
-rw-r--r--inc/Twig/TokenParser/Do.php42
-rw-r--r--inc/Twig/TokenParser/Embed.php66
-rw-r--r--inc/Twig/TokenParser/Extends.php52
-rw-r--r--inc/Twig/TokenParser/Filter.php61
-rw-r--r--inc/Twig/TokenParser/Flush.php42
-rw-r--r--inc/Twig/TokenParser/For.php136
-rw-r--r--inc/Twig/TokenParser/From.php74
-rw-r--r--inc/Twig/TokenParser/If.php94
-rw-r--r--inc/Twig/TokenParser/Import.php49
-rw-r--r--inc/Twig/TokenParser/Include.php80
-rw-r--r--inc/Twig/TokenParser/Macro.php68
-rw-r--r--inc/Twig/TokenParser/Sandbox.php68
-rw-r--r--inc/Twig/TokenParser/Set.php84
-rw-r--r--inc/Twig/TokenParser/Spaceless.php59
-rw-r--r--inc/Twig/TokenParser/Use.php82
17 files changed, 1229 insertions, 0 deletions
diff --git a/inc/Twig/TokenParser/AutoEscape.php b/inc/Twig/TokenParser/AutoEscape.php
new file mode 100644
index 00000000..27560288
--- /dev/null
+++ b/inc/Twig/TokenParser/AutoEscape.php
@@ -0,0 +1,89 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Marks a section of a template to be escaped or not.
14 *
15 * <pre>
16 * {% autoescape true %}
17 * Everything will be automatically escaped in this block
18 * {% endautoescape %}
19 *
20 * {% autoescape false %}
21 * Everything will be outputed as is in this block
22 * {% endautoescape %}
23 *
24 * {% autoescape true js %}
25 * Everything will be automatically escaped in this block
26 * using the js escaping strategy
27 * {% endautoescape %}
28 * </pre>
29 */
30class Twig_TokenParser_AutoEscape extends Twig_TokenParser
31{
32 /**
33 * Parses a token and returns a node.
34 *
35 * @param Twig_Token $token A Twig_Token instance
36 *
37 * @return Twig_NodeInterface A Twig_NodeInterface instance
38 */
39 public function parse(Twig_Token $token)
40 {
41 $lineno = $token->getLine();
42 $stream = $this->parser->getStream();
43
44 if ($stream->test(Twig_Token::BLOCK_END_TYPE)) {
45 $value = 'html';
46 } else {
47 $expr = $this->parser->getExpressionParser()->parseExpression();
48 if (!$expr instanceof Twig_Node_Expression_Constant) {
49 throw new Twig_Error_Syntax('An escaping strategy must be a string or a Boolean.', $stream->getCurrent()->getLine(), $stream->getFilename());
50 }
51 $value = $expr->getAttribute('value');
52
53 $compat = true === $value || false === $value;
54
55 if (true === $value) {
56 $value = 'html';
57 }
58
59 if ($compat && $stream->test(Twig_Token::NAME_TYPE)) {
60 if (false === $value) {
61 throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getFilename());
62 }
63
64 $value = $stream->next()->getValue();
65 }
66 }
67
68 $stream->expect(Twig_Token::BLOCK_END_TYPE);
69 $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
70 $stream->expect(Twig_Token::BLOCK_END_TYPE);
71
72 return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag());
73 }
74
75 public function decideBlockEnd(Twig_Token $token)
76 {
77 return $token->test('endautoescape');
78 }
79
80 /**
81 * Gets the tag name associated with this token parser.
82 *
83 * @return string The tag name
84 */
85 public function getTag()
86 {
87 return 'autoescape';
88 }
89}
diff --git a/inc/Twig/TokenParser/Block.php b/inc/Twig/TokenParser/Block.php
new file mode 100644
index 00000000..a2e017f3
--- /dev/null
+++ b/inc/Twig/TokenParser/Block.php
@@ -0,0 +1,83 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 * (c) 2009 Armin Ronacher
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13/**
14 * Marks a section of a template as being reusable.
15 *
16 * <pre>
17 * {% block head %}
18 * <link rel="stylesheet" href="style.css" />
19 * <title>{% block title %}{% endblock %} - My Webpage</title>
20 * {% endblock %}
21 * </pre>
22 */
23class Twig_TokenParser_Block extends Twig_TokenParser
24{
25 /**
26 * Parses a token and returns a node.
27 *
28 * @param Twig_Token $token A Twig_Token instance
29 *
30 * @return Twig_NodeInterface A Twig_NodeInterface instance
31 */
32 public function parse(Twig_Token $token)
33 {
34 $lineno = $token->getLine();
35 $stream = $this->parser->getStream();
36 $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
37 if ($this->parser->hasBlock($name)) {
38 throw new Twig_Error_Syntax(sprintf("The block '$name' has already been defined line %d", $this->parser->getBlock($name)->getLine()), $stream->getCurrent()->getLine(), $stream->getFilename());
39 }
40 $this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node(array()), $lineno));
41 $this->parser->pushLocalScope();
42 $this->parser->pushBlockStack($name);
43
44 if ($stream->test(Twig_Token::BLOCK_END_TYPE)) {
45 $stream->next();
46
47 $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
48 if ($stream->test(Twig_Token::NAME_TYPE)) {
49 $value = $stream->next()->getValue();
50
51 if ($value != $name) {
52 throw new Twig_Error_Syntax(sprintf("Expected endblock for block '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
53 }
54 }
55 } else {
56 $body = new Twig_Node(array(
57 new Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno),
58 ));
59 }
60 $stream->expect(Twig_Token::BLOCK_END_TYPE);
61
62 $block->setNode('body', $body);
63 $this->parser->popBlockStack();
64 $this->parser->popLocalScope();
65
66 return new Twig_Node_BlockReference($name, $lineno, $this->getTag());
67 }
68
69 public function decideBlockEnd(Twig_Token $token)
70 {
71 return $token->test('endblock');
72 }
73
74 /**
75 * Gets the tag name associated with this token parser.
76 *
77 * @return string The tag name
78 */
79 public function getTag()
80 {
81 return 'block';
82 }
83}
diff --git a/inc/Twig/TokenParser/Do.php b/inc/Twig/TokenParser/Do.php
new file mode 100644
index 00000000..f50939dd
--- /dev/null
+++ b/inc/Twig/TokenParser/Do.php
@@ -0,0 +1,42 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2011 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Evaluates an expression, discarding the returned value.
14 */
15class Twig_TokenParser_Do extends Twig_TokenParser
16{
17 /**
18 * Parses a token and returns a node.
19 *
20 * @param Twig_Token $token A Twig_Token instance
21 *
22 * @return Twig_NodeInterface A Twig_NodeInterface instance
23 */
24 public function parse(Twig_Token $token)
25 {
26 $expr = $this->parser->getExpressionParser()->parseExpression();
27
28 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
29
30 return new Twig_Node_Do($expr, $token->getLine(), $this->getTag());
31 }
32
33 /**
34 * Gets the tag name associated with this token parser.
35 *
36 * @return string The tag name
37 */
38 public function getTag()
39 {
40 return 'do';
41 }
42}
diff --git a/inc/Twig/TokenParser/Embed.php b/inc/Twig/TokenParser/Embed.php
new file mode 100644
index 00000000..69cb5f35
--- /dev/null
+++ b/inc/Twig/TokenParser/Embed.php
@@ -0,0 +1,66 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2012 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Embeds a template.
14 */
15class Twig_TokenParser_Embed extends Twig_TokenParser_Include
16{
17 /**
18 * Parses a token and returns a node.
19 *
20 * @param Twig_Token $token A Twig_Token instance
21 *
22 * @return Twig_NodeInterface A Twig_NodeInterface instance
23 */
24 public function parse(Twig_Token $token)
25 {
26 $stream = $this->parser->getStream();
27
28 $parent = $this->parser->getExpressionParser()->parseExpression();
29
30 list($variables, $only, $ignoreMissing) = $this->parseArguments();
31
32 // inject a fake parent to make the parent() function work
33 $stream->injectTokens(array(
34 new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $token->getLine()),
35 new Twig_Token(Twig_Token::NAME_TYPE, 'extends', $token->getLine()),
36 new Twig_Token(Twig_Token::STRING_TYPE, '__parent__', $token->getLine()),
37 new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $token->getLine()),
38 ));
39
40 $module = $this->parser->parse($stream, array($this, 'decideBlockEnd'), true);
41
42 // override the parent with the correct one
43 $module->setNode('parent', $parent);
44
45 $this->parser->embedTemplate($module);
46
47 $stream->expect(Twig_Token::BLOCK_END_TYPE);
48
49 return new Twig_Node_Embed($module->getAttribute('filename'), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
50 }
51
52 public function decideBlockEnd(Twig_Token $token)
53 {
54 return $token->test('endembed');
55 }
56
57 /**
58 * Gets the tag name associated with this token parser.
59 *
60 * @return string The tag name
61 */
62 public function getTag()
63 {
64 return 'embed';
65 }
66}
diff --git a/inc/Twig/TokenParser/Extends.php b/inc/Twig/TokenParser/Extends.php
new file mode 100644
index 00000000..f5ecee21
--- /dev/null
+++ b/inc/Twig/TokenParser/Extends.php
@@ -0,0 +1,52 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 * (c) 2009 Armin Ronacher
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13/**
14 * Extends a template by another one.
15 *
16 * <pre>
17 * {% extends "base.html" %}
18 * </pre>
19 */
20class Twig_TokenParser_Extends extends Twig_TokenParser
21{
22 /**
23 * Parses a token and returns a node.
24 *
25 * @param Twig_Token $token A Twig_Token instance
26 *
27 * @return Twig_NodeInterface A Twig_NodeInterface instance
28 */
29 public function parse(Twig_Token $token)
30 {
31 if (!$this->parser->isMainScope()) {
32 throw new Twig_Error_Syntax('Cannot extend from a block', $token->getLine(), $this->parser->getFilename());
33 }
34
35 if (null !== $this->parser->getParent()) {
36 throw new Twig_Error_Syntax('Multiple extends tags are forbidden', $token->getLine(), $this->parser->getFilename());
37 }
38 $this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
39
40 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
41 }
42
43 /**
44 * Gets the tag name associated with this token parser.
45 *
46 * @return string The tag name
47 */
48 public function getTag()
49 {
50 return 'extends';
51 }
52}
diff --git a/inc/Twig/TokenParser/Filter.php b/inc/Twig/TokenParser/Filter.php
new file mode 100644
index 00000000..2b97475a
--- /dev/null
+++ b/inc/Twig/TokenParser/Filter.php
@@ -0,0 +1,61 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Filters a section of a template by applying filters.
14 *
15 * <pre>
16 * {% filter upper %}
17 * This text becomes uppercase
18 * {% endfilter %}
19 * </pre>
20 */
21class Twig_TokenParser_Filter extends Twig_TokenParser
22{
23 /**
24 * Parses a token and returns a node.
25 *
26 * @param Twig_Token $token A Twig_Token instance
27 *
28 * @return Twig_NodeInterface A Twig_NodeInterface instance
29 */
30 public function parse(Twig_Token $token)
31 {
32 $name = $this->parser->getVarName();
33 $ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), true, $token->getLine(), $this->getTag());
34
35 $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
36 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
37
38 $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
39 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
40
41 $block = new Twig_Node_Block($name, $body, $token->getLine());
42 $this->parser->setBlock($name, $block);
43
44 return new Twig_Node_Print($filter, $token->getLine(), $this->getTag());
45 }
46
47 public function decideBlockEnd(Twig_Token $token)
48 {
49 return $token->test('endfilter');
50 }
51
52 /**
53 * Gets the tag name associated with this token parser.
54 *
55 * @return string The tag name
56 */
57 public function getTag()
58 {
59 return 'filter';
60 }
61}
diff --git a/inc/Twig/TokenParser/Flush.php b/inc/Twig/TokenParser/Flush.php
new file mode 100644
index 00000000..4e15e785
--- /dev/null
+++ b/inc/Twig/TokenParser/Flush.php
@@ -0,0 +1,42 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2011 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Flushes the output to the client.
14 *
15 * @see flush()
16 */
17class Twig_TokenParser_Flush extends Twig_TokenParser
18{
19 /**
20 * Parses a token and returns a node.
21 *
22 * @param Twig_Token $token A Twig_Token instance
23 *
24 * @return Twig_NodeInterface A Twig_NodeInterface instance
25 */
26 public function parse(Twig_Token $token)
27 {
28 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
29
30 return new Twig_Node_Flush($token->getLine(), $this->getTag());
31 }
32
33 /**
34 * Gets the tag name associated with this token parser.
35 *
36 * @return string The tag name
37 */
38 public function getTag()
39 {
40 return 'flush';
41 }
42}
diff --git a/inc/Twig/TokenParser/For.php b/inc/Twig/TokenParser/For.php
new file mode 100644
index 00000000..98a6d079
--- /dev/null
+++ b/inc/Twig/TokenParser/For.php
@@ -0,0 +1,136 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 * (c) 2009 Armin Ronacher
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13/**
14 * Loops over each item of a sequence.
15 *
16 * <pre>
17 * <ul>
18 * {% for user in users %}
19 * <li>{{ user.username|e }}</li>
20 * {% endfor %}
21 * </ul>
22 * </pre>
23 */
24class Twig_TokenParser_For extends Twig_TokenParser
25{
26 /**
27 * Parses a token and returns a node.
28 *
29 * @param Twig_Token $token A Twig_Token instance
30 *
31 * @return Twig_NodeInterface A Twig_NodeInterface instance
32 */
33 public function parse(Twig_Token $token)
34 {
35 $lineno = $token->getLine();
36 $stream = $this->parser->getStream();
37 $targets = $this->parser->getExpressionParser()->parseAssignmentExpression();
38 $stream->expect(Twig_Token::OPERATOR_TYPE, 'in');
39 $seq = $this->parser->getExpressionParser()->parseExpression();
40
41 $ifexpr = null;
42 if ($stream->test(Twig_Token::NAME_TYPE, 'if')) {
43 $stream->next();
44 $ifexpr = $this->parser->getExpressionParser()->parseExpression();
45 }
46
47 $stream->expect(Twig_Token::BLOCK_END_TYPE);
48 $body = $this->parser->subparse(array($this, 'decideForFork'));
49 if ($stream->next()->getValue() == 'else') {
50 $stream->expect(Twig_Token::BLOCK_END_TYPE);
51 $else = $this->parser->subparse(array($this, 'decideForEnd'), true);
52 } else {
53 $else = null;
54 }
55 $stream->expect(Twig_Token::BLOCK_END_TYPE);
56
57 if (count($targets) > 1) {
58 $keyTarget = $targets->getNode(0);
59 $keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getLine());
60 $valueTarget = $targets->getNode(1);
61 $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine());
62 } else {
63 $keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno);
64 $valueTarget = $targets->getNode(0);
65 $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine());
66 }
67
68 if ($ifexpr) {
69 $this->checkLoopUsageCondition($stream, $ifexpr);
70 $this->checkLoopUsageBody($stream, $body);
71 }
72
73 return new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag());
74 }
75
76 public function decideForFork(Twig_Token $token)
77 {
78 return $token->test(array('else', 'endfor'));
79 }
80
81 public function decideForEnd(Twig_Token $token)
82 {
83 return $token->test('endfor');
84 }
85
86 // the loop variable cannot be used in the condition
87 protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node)
88 {
89 if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
90 throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition', $node->getLine(), $stream->getFilename());
91 }
92
93 foreach ($node as $n) {
94 if (!$n) {
95 continue;
96 }
97
98 $this->checkLoopUsageCondition($stream, $n);
99 }
100 }
101
102 // check usage of non-defined loop-items
103 // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include)
104 protected function checkLoopUsageBody(Twig_TokenStream $stream, Twig_NodeInterface $node)
105 {
106 if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
107 $attribute = $node->getNode('attribute');
108 if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) {
109 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());
110 }
111 }
112
113 // should check for parent.loop.XXX usage
114 if ($node instanceof Twig_Node_For) {
115 return;
116 }
117
118 foreach ($node as $n) {
119 if (!$n) {
120 continue;
121 }
122
123 $this->checkLoopUsageBody($stream, $n);
124 }
125 }
126
127 /**
128 * Gets the tag name associated with this token parser.
129 *
130 * @return string The tag name
131 */
132 public function getTag()
133 {
134 return 'for';
135 }
136}
diff --git a/inc/Twig/TokenParser/From.php b/inc/Twig/TokenParser/From.php
new file mode 100644
index 00000000..a54054db
--- /dev/null
+++ b/inc/Twig/TokenParser/From.php
@@ -0,0 +1,74 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2010 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Imports macros.
14 *
15 * <pre>
16 * {% from 'forms.html' import forms %}
17 * </pre>
18 */
19class Twig_TokenParser_From extends Twig_TokenParser
20{
21 /**
22 * Parses a token and returns a node.
23 *
24 * @param Twig_Token $token A Twig_Token instance
25 *
26 * @return Twig_NodeInterface A Twig_NodeInterface instance
27 */
28 public function parse(Twig_Token $token)
29 {
30 $macro = $this->parser->getExpressionParser()->parseExpression();
31 $stream = $this->parser->getStream();
32 $stream->expect('import');
33
34 $targets = array();
35 do {
36 $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
37
38 $alias = $name;
39 if ($stream->test('as')) {
40 $stream->next();
41
42 $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
43 }
44
45 $targets[$name] = $alias;
46
47 if (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
48 break;
49 }
50
51 $stream->next();
52 } while (true);
53
54 $stream->expect(Twig_Token::BLOCK_END_TYPE);
55
56 $node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag());
57
58 foreach ($targets as $name => $alias) {
59 $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
60 }
61
62 return $node;
63 }
64
65 /**
66 * Gets the tag name associated with this token parser.
67 *
68 * @return string The tag name
69 */
70 public function getTag()
71 {
72 return 'from';
73 }
74}
diff --git a/inc/Twig/TokenParser/If.php b/inc/Twig/TokenParser/If.php
new file mode 100644
index 00000000..3d7d1f51
--- /dev/null
+++ b/inc/Twig/TokenParser/If.php
@@ -0,0 +1,94 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 * (c) 2009 Armin Ronacher
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13/**
14 * Tests a condition.
15 *
16 * <pre>
17 * {% if users %}
18 * <ul>
19 * {% for user in users %}
20 * <li>{{ user.username|e }}</li>
21 * {% endfor %}
22 * </ul>
23 * {% endif %}
24 * </pre>
25 */
26class Twig_TokenParser_If extends Twig_TokenParser
27{
28 /**
29 * Parses a token and returns a node.
30 *
31 * @param Twig_Token $token A Twig_Token instance
32 *
33 * @return Twig_NodeInterface A Twig_NodeInterface instance
34 */
35 public function parse(Twig_Token $token)
36 {
37 $lineno = $token->getLine();
38 $expr = $this->parser->getExpressionParser()->parseExpression();
39 $stream = $this->parser->getStream();
40 $stream->expect(Twig_Token::BLOCK_END_TYPE);
41 $body = $this->parser->subparse(array($this, 'decideIfFork'));
42 $tests = array($expr, $body);
43 $else = null;
44
45 $end = false;
46 while (!$end) {
47 switch ($stream->next()->getValue()) {
48 case 'else':
49 $stream->expect(Twig_Token::BLOCK_END_TYPE);
50 $else = $this->parser->subparse(array($this, 'decideIfEnd'));
51 break;
52
53 case 'elseif':
54 $expr = $this->parser->getExpressionParser()->parseExpression();
55 $stream->expect(Twig_Token::BLOCK_END_TYPE);
56 $body = $this->parser->subparse(array($this, 'decideIfFork'));
57 $tests[] = $expr;
58 $tests[] = $body;
59 break;
60
61 case 'endif':
62 $end = true;
63 break;
64
65 default:
66 throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d)', $lineno), $stream->getCurrent()->getLine(), $stream->getFilename());
67 }
68 }
69
70 $stream->expect(Twig_Token::BLOCK_END_TYPE);
71
72 return new Twig_Node_If(new Twig_Node($tests), $else, $lineno, $this->getTag());
73 }
74
75 public function decideIfFork(Twig_Token $token)
76 {
77 return $token->test(array('elseif', 'else', 'endif'));
78 }
79
80 public function decideIfEnd(Twig_Token $token)
81 {
82 return $token->test(array('endif'));
83 }
84
85 /**
86 * Gets the tag name associated with this token parser.
87 *
88 * @return string The tag name
89 */
90 public function getTag()
91 {
92 return 'if';
93 }
94}
diff --git a/inc/Twig/TokenParser/Import.php b/inc/Twig/TokenParser/Import.php
new file mode 100644
index 00000000..e7050c70
--- /dev/null
+++ b/inc/Twig/TokenParser/Import.php
@@ -0,0 +1,49 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Imports macros.
14 *
15 * <pre>
16 * {% import 'forms.html' as forms %}
17 * </pre>
18 */
19class Twig_TokenParser_Import extends Twig_TokenParser
20{
21 /**
22 * Parses a token and returns a node.
23 *
24 * @param Twig_Token $token A Twig_Token instance
25 *
26 * @return Twig_NodeInterface A Twig_NodeInterface instance
27 */
28 public function parse(Twig_Token $token)
29 {
30 $macro = $this->parser->getExpressionParser()->parseExpression();
31 $this->parser->getStream()->expect('as');
32 $var = new Twig_Node_Expression_AssignName($this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(), $token->getLine());
33 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
34
35 $this->parser->addImportedSymbol('template', $var->getAttribute('name'));
36
37 return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag());
38 }
39
40 /**
41 * Gets the tag name associated with this token parser.
42 *
43 * @return string The tag name
44 */
45 public function getTag()
46 {
47 return 'import';
48 }
49}
diff --git a/inc/Twig/TokenParser/Include.php b/inc/Twig/TokenParser/Include.php
new file mode 100644
index 00000000..4a317868
--- /dev/null
+++ b/inc/Twig/TokenParser/Include.php
@@ -0,0 +1,80 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 * (c) 2009 Armin Ronacher
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13/**
14 * Includes a template.
15 *
16 * <pre>
17 * {% include 'header.html' %}
18 * Body
19 * {% include 'footer.html' %}
20 * </pre>
21 */
22class Twig_TokenParser_Include extends Twig_TokenParser
23{
24 /**
25 * Parses a token and returns a node.
26 *
27 * @param Twig_Token $token A Twig_Token instance
28 *
29 * @return Twig_NodeInterface A Twig_NodeInterface instance
30 */
31 public function parse(Twig_Token $token)
32 {
33 $expr = $this->parser->getExpressionParser()->parseExpression();
34
35 list($variables, $only, $ignoreMissing) = $this->parseArguments();
36
37 return new Twig_Node_Include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
38 }
39
40 protected function parseArguments()
41 {
42 $stream = $this->parser->getStream();
43
44 $ignoreMissing = false;
45 if ($stream->test(Twig_Token::NAME_TYPE, 'ignore')) {
46 $stream->next();
47 $stream->expect(Twig_Token::NAME_TYPE, 'missing');
48
49 $ignoreMissing = true;
50 }
51
52 $variables = null;
53 if ($stream->test(Twig_Token::NAME_TYPE, 'with')) {
54 $stream->next();
55
56 $variables = $this->parser->getExpressionParser()->parseExpression();
57 }
58
59 $only = false;
60 if ($stream->test(Twig_Token::NAME_TYPE, 'only')) {
61 $stream->next();
62
63 $only = true;
64 }
65
66 $stream->expect(Twig_Token::BLOCK_END_TYPE);
67
68 return array($variables, $only, $ignoreMissing);
69 }
70
71 /**
72 * Gets the tag name associated with this token parser.
73 *
74 * @return string The tag name
75 */
76 public function getTag()
77 {
78 return 'include';
79 }
80}
diff --git a/inc/Twig/TokenParser/Macro.php b/inc/Twig/TokenParser/Macro.php
new file mode 100644
index 00000000..82b4fa6d
--- /dev/null
+++ b/inc/Twig/TokenParser/Macro.php
@@ -0,0 +1,68 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Defines a macro.
14 *
15 * <pre>
16 * {% macro input(name, value, type, size) %}
17 * <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
18 * {% endmacro %}
19 * </pre>
20 */
21class Twig_TokenParser_Macro extends Twig_TokenParser
22{
23 /**
24 * Parses a token and returns a node.
25 *
26 * @param Twig_Token $token A Twig_Token instance
27 *
28 * @return Twig_NodeInterface A Twig_NodeInterface instance
29 */
30 public function parse(Twig_Token $token)
31 {
32 $lineno = $token->getLine();
33 $stream = $this->parser->getStream();
34 $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
35
36 $arguments = $this->parser->getExpressionParser()->parseArguments(true, true);
37
38 $stream->expect(Twig_Token::BLOCK_END_TYPE);
39 $this->parser->pushLocalScope();
40 $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
41 if ($stream->test(Twig_Token::NAME_TYPE)) {
42 $value = $stream->next()->getValue();
43
44 if ($value != $name) {
45 throw new Twig_Error_Syntax(sprintf("Expected endmacro for macro '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
46 }
47 }
48 $this->parser->popLocalScope();
49 $stream->expect(Twig_Token::BLOCK_END_TYPE);
50
51 $this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body(array($body)), $arguments, $lineno, $this->getTag()));
52 }
53
54 public function decideBlockEnd(Twig_Token $token)
55 {
56 return $token->test('endmacro');
57 }
58
59 /**
60 * Gets the tag name associated with this token parser.
61 *
62 * @return string The tag name
63 */
64 public function getTag()
65 {
66 return 'macro';
67 }
68}
diff --git a/inc/Twig/TokenParser/Sandbox.php b/inc/Twig/TokenParser/Sandbox.php
new file mode 100644
index 00000000..9457325a
--- /dev/null
+++ b/inc/Twig/TokenParser/Sandbox.php
@@ -0,0 +1,68 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2010 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Marks a section of a template as untrusted code that must be evaluated in the sandbox mode.
14 *
15 * <pre>
16 * {% sandbox %}
17 * {% include 'user.html' %}
18 * {% endsandbox %}
19 * </pre>
20 *
21 * @see http://www.twig-project.org/doc/api.html#sandbox-extension for details
22 */
23class Twig_TokenParser_Sandbox extends Twig_TokenParser
24{
25 /**
26 * Parses a token and returns a node.
27 *
28 * @param Twig_Token $token A Twig_Token instance
29 *
30 * @return Twig_NodeInterface A Twig_NodeInterface instance
31 */
32 public function parse(Twig_Token $token)
33 {
34 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
35 $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
36 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
37
38 // in a sandbox tag, only include tags are allowed
39 if (!$body instanceof Twig_Node_Include) {
40 foreach ($body as $node) {
41 if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
42 continue;
43 }
44
45 if (!$node instanceof Twig_Node_Include) {
46 throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section', $node->getLine(), $this->parser->getFilename());
47 }
48 }
49 }
50
51 return new Twig_Node_Sandbox($body, $token->getLine(), $this->getTag());
52 }
53
54 public function decideBlockEnd(Twig_Token $token)
55 {
56 return $token->test('endsandbox');
57 }
58
59 /**
60 * Gets the tag name associated with this token parser.
61 *
62 * @return string The tag name
63 */
64 public function getTag()
65 {
66 return 'sandbox';
67 }
68}
diff --git a/inc/Twig/TokenParser/Set.php b/inc/Twig/TokenParser/Set.php
new file mode 100644
index 00000000..70e0b41b
--- /dev/null
+++ b/inc/Twig/TokenParser/Set.php
@@ -0,0 +1,84 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Defines a variable.
14 *
15 * <pre>
16 * {% set foo = 'foo' %}
17 *
18 * {% set foo = [1, 2] %}
19 *
20 * {% set foo = {'foo': 'bar'} %}
21 *
22 * {% set foo = 'foo' ~ 'bar' %}
23 *
24 * {% set foo, bar = 'foo', 'bar' %}
25 *
26 * {% set foo %}Some content{% endset %}
27 * </pre>
28 */
29class Twig_TokenParser_Set extends Twig_TokenParser
30{
31 /**
32 * Parses a token and returns a node.
33 *
34 * @param Twig_Token $token A Twig_Token instance
35 *
36 * @return Twig_NodeInterface A Twig_NodeInterface instance
37 */
38 public function parse(Twig_Token $token)
39 {
40 $lineno = $token->getLine();
41 $stream = $this->parser->getStream();
42 $names = $this->parser->getExpressionParser()->parseAssignmentExpression();
43
44 $capture = false;
45 if ($stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
46 $stream->next();
47 $values = $this->parser->getExpressionParser()->parseMultitargetExpression();
48
49 $stream->expect(Twig_Token::BLOCK_END_TYPE);
50
51 if (count($names) !== count($values)) {
52 throw new Twig_Error_Syntax("When using set, you must have the same number of variables and assignments.", $stream->getCurrent()->getLine(), $stream->getFilename());
53 }
54 } else {
55 $capture = true;
56
57 if (count($names) > 1) {
58 throw new Twig_Error_Syntax("When using set with a block, you cannot have a multi-target.", $stream->getCurrent()->getLine(), $stream->getFilename());
59 }
60
61 $stream->expect(Twig_Token::BLOCK_END_TYPE);
62
63 $values = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
64 $stream->expect(Twig_Token::BLOCK_END_TYPE);
65 }
66
67 return new Twig_Node_Set($capture, $names, $values, $lineno, $this->getTag());
68 }
69
70 public function decideBlockEnd(Twig_Token $token)
71 {
72 return $token->test('endset');
73 }
74
75 /**
76 * Gets the tag name associated with this token parser.
77 *
78 * @return string The tag name
79 */
80 public function getTag()
81 {
82 return 'set';
83 }
84}
diff --git a/inc/Twig/TokenParser/Spaceless.php b/inc/Twig/TokenParser/Spaceless.php
new file mode 100644
index 00000000..1e3fa8f3
--- /dev/null
+++ b/inc/Twig/TokenParser/Spaceless.php
@@ -0,0 +1,59 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2010 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Remove whitespaces between HTML tags.
14 *
15 * <pre>
16 * {% spaceless %}
17 * <div>
18 * <strong>foo</strong>
19 * </div>
20 * {% endspaceless %}
21 *
22 * {# output will be <div><strong>foo</strong></div> #}
23 * </pre>
24 */
25class Twig_TokenParser_Spaceless extends Twig_TokenParser
26{
27 /**
28 * Parses a token and returns a node.
29 *
30 * @param Twig_Token $token A Twig_Token instance
31 *
32 * @return Twig_NodeInterface A Twig_NodeInterface instance
33 */
34 public function parse(Twig_Token $token)
35 {
36 $lineno = $token->getLine();
37
38 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
39 $body = $this->parser->subparse(array($this, 'decideSpacelessEnd'), true);
40 $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
41
42 return new Twig_Node_Spaceless($body, $lineno, $this->getTag());
43 }
44
45 public function decideSpacelessEnd(Twig_Token $token)
46 {
47 return $token->test('endspaceless');
48 }
49
50 /**
51 * Gets the tag name associated with this token parser.
52 *
53 * @return string The tag name
54 */
55 public function getTag()
56 {
57 return 'spaceless';
58 }
59}
diff --git a/inc/Twig/TokenParser/Use.php b/inc/Twig/TokenParser/Use.php
new file mode 100644
index 00000000..bc0e09ef
--- /dev/null
+++ b/inc/Twig/TokenParser/Use.php
@@ -0,0 +1,82 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2011 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Imports blocks defined in another template into the current template.
14 *
15 * <pre>
16 * {% extends "base.html" %}
17 *
18 * {% use "blocks.html" %}
19 *
20 * {% block title %}{% endblock %}
21 * {% block content %}{% endblock %}
22 * </pre>
23 *
24 * @see http://www.twig-project.org/doc/templates.html#horizontal-reuse for details.
25 */
26class Twig_TokenParser_Use extends Twig_TokenParser
27{
28 /**
29 * Parses a token and returns a node.
30 *
31 * @param Twig_Token $token A Twig_Token instance
32 *
33 * @return Twig_NodeInterface A Twig_NodeInterface instance
34 */
35 public function parse(Twig_Token $token)
36 {
37 $template = $this->parser->getExpressionParser()->parseExpression();
38 $stream = $this->parser->getStream();
39
40 if (!$template instanceof Twig_Node_Expression_Constant) {
41 throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getFilename());
42 }
43
44 $targets = array();
45 if ($stream->test('with')) {
46 $stream->next();
47
48 do {
49 $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
50
51 $alias = $name;
52 if ($stream->test('as')) {
53 $stream->next();
54
55 $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
56 }
57
58 $targets[$name] = new Twig_Node_Expression_Constant($alias, -1);
59
60 if (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
61 break;
62 }
63
64 $stream->next();
65 } while (true);
66 }
67
68 $stream->expect(Twig_Token::BLOCK_END_TYPE);
69
70 $this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets))));
71 }
72
73 /**
74 * Gets the tag name associated with this token parser.
75 *
76 * @return string The tag name
77 */
78 public function getTag()
79 {
80 return 'use';
81 }
82}