aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc/Twig/Node
diff options
context:
space:
mode:
authorNicolas LÅ“uillet <nicolas.loeuillet@gmail.com>2013-08-02 22:40:51 +0200
committerNicolas LÅ“uillet <nicolas.loeuillet@gmail.com>2013-08-02 22:40:51 +0200
commita4565e88edbc8e3bd092a475469769c86a4c350c (patch)
treea6a3c935b03a23ff87575c8c315cf8ba78fe68c2 /inc/Twig/Node
parentf6c9baab3efeec1d0efa151e276fc08d5b58f9e9 (diff)
downloadwallabag-a4565e88edbc8e3bd092a475469769c86a4c350c.tar.gz
wallabag-a4565e88edbc8e3bd092a475469769c86a4c350c.tar.zst
wallabag-a4565e88edbc8e3bd092a475469769c86a4c350c.zip
add Twig & refactor poche
Diffstat (limited to 'inc/Twig/Node')
-rw-r--r--inc/Twig/Node/AutoEscape.php39
-rw-r--r--inc/Twig/Node/Block.php44
-rw-r--r--inc/Twig/Node/BlockReference.php37
-rw-r--r--inc/Twig/Node/Body.php19
-rw-r--r--inc/Twig/Node/Do.php38
-rw-r--r--inc/Twig/Node/Embed.php38
-rw-r--r--inc/Twig/Node/Expression.php20
-rw-r--r--inc/Twig/Node/Expression/Array.php86
-rw-r--r--inc/Twig/Node/Expression/AssignName.php28
-rw-r--r--inc/Twig/Node/Expression/Binary.php40
-rw-r--r--inc/Twig/Node/Expression/Binary/Add.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/And.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/BitwiseAnd.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/BitwiseOr.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/BitwiseXor.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/Concat.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/Div.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/Equal.php17
-rw-r--r--inc/Twig/Node/Expression/Binary/FloorDiv.php29
-rw-r--r--inc/Twig/Node/Expression/Binary/Greater.php17
-rw-r--r--inc/Twig/Node/Expression/Binary/GreaterEqual.php17
-rw-r--r--inc/Twig/Node/Expression/Binary/In.php33
-rw-r--r--inc/Twig/Node/Expression/Binary/Less.php17
-rw-r--r--inc/Twig/Node/Expression/Binary/LessEqual.php17
-rw-r--r--inc/Twig/Node/Expression/Binary/Mod.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/Mul.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/NotEqual.php17
-rw-r--r--inc/Twig/Node/Expression/Binary/NotIn.php33
-rw-r--r--inc/Twig/Node/Expression/Binary/Or.php18
-rw-r--r--inc/Twig/Node/Expression/Binary/Power.php33
-rw-r--r--inc/Twig/Node/Expression/Binary/Range.php33
-rw-r--r--inc/Twig/Node/Expression/Binary/Sub.php18
-rw-r--r--inc/Twig/Node/Expression/BlockReference.php51
-rw-r--r--inc/Twig/Node/Expression/Call.php178
-rw-r--r--inc/Twig/Node/Expression/Conditional.php31
-rw-r--r--inc/Twig/Node/Expression/Constant.php23
-rw-r--r--inc/Twig/Node/Expression/ExtensionReference.php33
-rw-r--r--inc/Twig/Node/Expression/Filter.php36
-rw-r--r--inc/Twig/Node/Expression/Filter/Default.php43
-rw-r--r--inc/Twig/Node/Expression/Function.php35
-rw-r--r--inc/Twig/Node/Expression/GetAttr.php53
-rw-r--r--inc/Twig/Node/Expression/MethodCall.php41
-rw-r--r--inc/Twig/Node/Expression/Name.php88
-rw-r--r--inc/Twig/Node/Expression/Parent.php47
-rw-r--r--inc/Twig/Node/Expression/TempName.php26
-rw-r--r--inc/Twig/Node/Expression/Test.php32
-rw-r--r--inc/Twig/Node/Expression/Test/Constant.php46
-rw-r--r--inc/Twig/Node/Expression/Test/Defined.php54
-rw-r--r--inc/Twig/Node/Expression/Test/Divisibleby.php33
-rw-r--r--inc/Twig/Node/Expression/Test/Even.php32
-rw-r--r--inc/Twig/Node/Expression/Test/Null.php31
-rw-r--r--inc/Twig/Node/Expression/Test/Odd.php32
-rw-r--r--inc/Twig/Node/Expression/Test/Sameas.php29
-rw-r--r--inc/Twig/Node/Expression/Unary.php30
-rw-r--r--inc/Twig/Node/Expression/Unary/Neg.php18
-rw-r--r--inc/Twig/Node/Expression/Unary/Not.php18
-rw-r--r--inc/Twig/Node/Expression/Unary/Pos.php18
-rw-r--r--inc/Twig/Node/Flush.php36
-rw-r--r--inc/Twig/Node/For.php112
-rw-r--r--inc/Twig/Node/ForLoop.php55
-rw-r--r--inc/Twig/Node/If.php66
-rw-r--r--inc/Twig/Node/Import.php50
-rw-r--r--inc/Twig/Node/Include.php99
-rw-r--r--inc/Twig/Node/Macro.php96
-rw-r--r--inc/Twig/Node/Module.php371
-rw-r--r--inc/Twig/Node/Print.php39
-rw-r--r--inc/Twig/Node/Sandbox.php47
-rw-r--r--inc/Twig/Node/SandboxedModule.php60
-rw-r--r--inc/Twig/Node/SandboxedPrint.php59
-rw-r--r--inc/Twig/Node/Set.php101
-rw-r--r--inc/Twig/Node/SetTemp.php35
-rw-r--r--inc/Twig/Node/Spaceless.php40
-rw-r--r--inc/Twig/Node/Text.php39
73 files changed, 3213 insertions, 0 deletions
diff --git a/inc/Twig/Node/AutoEscape.php b/inc/Twig/Node/AutoEscape.php
new file mode 100644
index 00000000..8f190e0b
--- /dev/null
+++ b/inc/Twig/Node/AutoEscape.php
@@ -0,0 +1,39 @@
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 * Represents an autoescape node.
14 *
15 * The value is the escaping strategy (can be html, js, ...)
16 *
17 * The true value is equivalent to html.
18 *
19 * If autoescaping is disabled, then the value is false.
20 *
21 * @author Fabien Potencier <fabien@symfony.com>
22 */
23class Twig_Node_AutoEscape extends Twig_Node
24{
25 public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape')
26 {
27 parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag);
28 }
29
30 /**
31 * Compiles the node to PHP.
32 *
33 * @param Twig_Compiler A Twig_Compiler instance
34 */
35 public function compile(Twig_Compiler $compiler)
36 {
37 $compiler->subcompile($this->getNode('body'));
38 }
39}
diff --git a/inc/Twig/Node/Block.php b/inc/Twig/Node/Block.php
new file mode 100644
index 00000000..50eb67ed
--- /dev/null
+++ b/inc/Twig/Node/Block.php
@@ -0,0 +1,44 @@
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 * Represents a block node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_Block extends Twig_Node
19{
20 public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null)
21 {
22 parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag);
23 }
24
25 /**
26 * Compiles the node to PHP.
27 *
28 * @param Twig_Compiler A Twig_Compiler instance
29 */
30 public function compile(Twig_Compiler $compiler)
31 {
32 $compiler
33 ->addDebugInfo($this)
34 ->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n")
35 ->indent()
36 ;
37
38 $compiler
39 ->subcompile($this->getNode('body'))
40 ->outdent()
41 ->write("}\n\n")
42 ;
43 }
44}
diff --git a/inc/Twig/Node/BlockReference.php b/inc/Twig/Node/BlockReference.php
new file mode 100644
index 00000000..013e369e
--- /dev/null
+++ b/inc/Twig/Node/BlockReference.php
@@ -0,0 +1,37 @@
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 * Represents a block call node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface
19{
20 public function __construct($name, $lineno, $tag = null)
21 {
22 parent::__construct(array(), array('name' => $name), $lineno, $tag);
23 }
24
25 /**
26 * Compiles the node to PHP.
27 *
28 * @param Twig_Compiler A Twig_Compiler instance
29 */
30 public function compile(Twig_Compiler $compiler)
31 {
32 $compiler
33 ->addDebugInfo($this)
34 ->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name')))
35 ;
36 }
37}
diff --git a/inc/Twig/Node/Body.php b/inc/Twig/Node/Body.php
new file mode 100644
index 00000000..3ffb1342
--- /dev/null
+++ b/inc/Twig/Node/Body.php
@@ -0,0 +1,19 @@
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 * Represents a body node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Body extends Twig_Node
18{
19}
diff --git a/inc/Twig/Node/Do.php b/inc/Twig/Node/Do.php
new file mode 100644
index 00000000..c528066b
--- /dev/null
+++ b/inc/Twig/Node/Do.php
@@ -0,0 +1,38 @@
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 * Represents a do node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Do extends Twig_Node
18{
19 public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
20 {
21 parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param Twig_Compiler A Twig_Compiler instance
28 */
29 public function compile(Twig_Compiler $compiler)
30 {
31 $compiler
32 ->addDebugInfo($this)
33 ->write('')
34 ->subcompile($this->getNode('expr'))
35 ->raw(";\n")
36 ;
37 }
38}
diff --git a/inc/Twig/Node/Embed.php b/inc/Twig/Node/Embed.php
new file mode 100644
index 00000000..4c9456dc
--- /dev/null
+++ b/inc/Twig/Node/Embed.php
@@ -0,0 +1,38 @@
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 * Represents an embed node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Embed extends Twig_Node_Include
18{
19 // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module)
20 public function __construct($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
21 {
22 parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
23
24 $this->setAttribute('filename', $filename);
25 $this->setAttribute('index', $index);
26 }
27
28 protected function addGetTemplate(Twig_Compiler $compiler)
29 {
30 $compiler
31 ->write("\$this->env->loadTemplate(")
32 ->string($this->getAttribute('filename'))
33 ->raw(', ')
34 ->string($this->getAttribute('index'))
35 ->raw(")")
36 ;
37 }
38}
diff --git a/inc/Twig/Node/Expression.php b/inc/Twig/Node/Expression.php
new file mode 100644
index 00000000..a7382e7d
--- /dev/null
+++ b/inc/Twig/Node/Expression.php
@@ -0,0 +1,20 @@
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 * Abstract class for all nodes that represents an expression.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18abstract class Twig_Node_Expression extends Twig_Node
19{
20}
diff --git a/inc/Twig/Node/Expression/Array.php b/inc/Twig/Node/Expression/Array.php
new file mode 100644
index 00000000..1da785fe
--- /dev/null
+++ b/inc/Twig/Node/Expression/Array.php
@@ -0,0 +1,86 @@
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 */
11class Twig_Node_Expression_Array extends Twig_Node_Expression
12{
13 protected $index;
14
15 public function __construct(array $elements, $lineno)
16 {
17 parent::__construct($elements, array(), $lineno);
18
19 $this->index = -1;
20 foreach ($this->getKeyValuePairs() as $pair) {
21 if ($pair['key'] instanceof Twig_Node_Expression_Constant && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) {
22 $this->index = $pair['key']->getAttribute('value');
23 }
24 }
25 }
26
27 public function getKeyValuePairs()
28 {
29 $pairs = array();
30
31 foreach (array_chunk($this->nodes, 2) as $pair) {
32 $pairs[] = array(
33 'key' => $pair[0],
34 'value' => $pair[1],
35 );
36 }
37
38 return $pairs;
39 }
40
41 public function hasElement(Twig_Node_Expression $key)
42 {
43 foreach ($this->getKeyValuePairs() as $pair) {
44 // we compare the string representation of the keys
45 // to avoid comparing the line numbers which are not relevant here.
46 if ((string) $key == (string) $pair['key']) {
47 return true;
48 }
49 }
50
51 return false;
52 }
53
54 public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null)
55 {
56 if (null === $key) {
57 $key = new Twig_Node_Expression_Constant(++$this->index, $value->getLine());
58 }
59
60 array_push($this->nodes, $key, $value);
61 }
62
63 /**
64 * Compiles the node to PHP.
65 *
66 * @param Twig_Compiler A Twig_Compiler instance
67 */
68 public function compile(Twig_Compiler $compiler)
69 {
70 $compiler->raw('array(');
71 $first = true;
72 foreach ($this->getKeyValuePairs() as $pair) {
73 if (!$first) {
74 $compiler->raw(', ');
75 }
76 $first = false;
77
78 $compiler
79 ->subcompile($pair['key'])
80 ->raw(' => ')
81 ->subcompile($pair['value'])
82 ;
83 }
84 $compiler->raw(')');
85 }
86}
diff --git a/inc/Twig/Node/Expression/AssignName.php b/inc/Twig/Node/Expression/AssignName.php
new file mode 100644
index 00000000..2ddea78c
--- /dev/null
+++ b/inc/Twig/Node/Expression/AssignName.php
@@ -0,0 +1,28 @@
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
13class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
14{
15 /**
16 * Compiles the node to PHP.
17 *
18 * @param Twig_Compiler A Twig_Compiler instance
19 */
20 public function compile(Twig_Compiler $compiler)
21 {
22 $compiler
23 ->raw('$context[')
24 ->string($this->getAttribute('name'))
25 ->raw(']')
26 ;
27 }
28}
diff --git a/inc/Twig/Node/Expression/Binary.php b/inc/Twig/Node/Expression/Binary.php
new file mode 100644
index 00000000..9dd5de2c
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary.php
@@ -0,0 +1,40 @@
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 */
12abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
13{
14 public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
15 {
16 parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno);
17 }
18
19 /**
20 * Compiles the node to PHP.
21 *
22 * @param Twig_Compiler A Twig_Compiler instance
23 */
24 public function compile(Twig_Compiler $compiler)
25 {
26 $compiler
27 ->raw('(')
28 ->subcompile($this->getNode('left'))
29 ->raw(' ')
30 ;
31 $this->operator($compiler);
32 $compiler
33 ->raw(' ')
34 ->subcompile($this->getNode('right'))
35 ->raw(')')
36 ;
37 }
38
39 abstract public function operator(Twig_Compiler $compiler);
40}
diff --git a/inc/Twig/Node/Expression/Binary/Add.php b/inc/Twig/Node/Expression/Binary/Add.php
new file mode 100644
index 00000000..0ef8e117
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Add.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('+');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/And.php b/inc/Twig/Node/Expression/Binary/And.php
new file mode 100644
index 00000000..d5752ebb
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/And.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('&&');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/BitwiseAnd.php b/inc/Twig/Node/Expression/Binary/BitwiseAnd.php
new file mode 100644
index 00000000..9a46d845
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/BitwiseAnd.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('&');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/BitwiseOr.php b/inc/Twig/Node/Expression/Binary/BitwiseOr.php
new file mode 100644
index 00000000..058a20bf
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/BitwiseOr.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('|');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/BitwiseXor.php b/inc/Twig/Node/Expression/Binary/BitwiseXor.php
new file mode 100644
index 00000000..f4da73d4
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/BitwiseXor.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('^');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/Concat.php b/inc/Twig/Node/Expression/Binary/Concat.php
new file mode 100644
index 00000000..f9a64627
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Concat.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('.');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/Div.php b/inc/Twig/Node/Expression/Binary/Div.php
new file mode 100644
index 00000000..e0797a61
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Div.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('/');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/Equal.php b/inc/Twig/Node/Expression/Binary/Equal.php
new file mode 100644
index 00000000..7b1236d0
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Equal.php
@@ -0,0 +1,17 @@
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 */
11class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary
12{
13 public function operator(Twig_Compiler $compiler)
14 {
15 return $compiler->raw('==');
16 }
17}
diff --git a/inc/Twig/Node/Expression/Binary/FloorDiv.php b/inc/Twig/Node/Expression/Binary/FloorDiv.php
new file mode 100644
index 00000000..7fbd0556
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/FloorDiv.php
@@ -0,0 +1,29 @@
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 */
11class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary
12{
13 /**
14 * Compiles the node to PHP.
15 *
16 * @param Twig_Compiler A Twig_Compiler instance
17 */
18 public function compile(Twig_Compiler $compiler)
19 {
20 $compiler->raw('intval(floor(');
21 parent::compile($compiler);
22 $compiler->raw('))');
23 }
24
25 public function operator(Twig_Compiler $compiler)
26 {
27 return $compiler->raw('/');
28 }
29}
diff --git a/inc/Twig/Node/Expression/Binary/Greater.php b/inc/Twig/Node/Expression/Binary/Greater.php
new file mode 100644
index 00000000..a110bd92
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Greater.php
@@ -0,0 +1,17 @@
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 */
11class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary
12{
13 public function operator(Twig_Compiler $compiler)
14 {
15 return $compiler->raw('>');
16 }
17}
diff --git a/inc/Twig/Node/Expression/Binary/GreaterEqual.php b/inc/Twig/Node/Expression/Binary/GreaterEqual.php
new file mode 100644
index 00000000..3754fed2
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/GreaterEqual.php
@@ -0,0 +1,17 @@
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 */
11class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Binary
12{
13 public function operator(Twig_Compiler $compiler)
14 {
15 return $compiler->raw('>=');
16 }
17}
diff --git a/inc/Twig/Node/Expression/Binary/In.php b/inc/Twig/Node/Expression/Binary/In.php
new file mode 100644
index 00000000..788f9377
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/In.php
@@ -0,0 +1,33 @@
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 */
11class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary
12{
13 /**
14 * Compiles the node to PHP.
15 *
16 * @param Twig_Compiler A Twig_Compiler instance
17 */
18 public function compile(Twig_Compiler $compiler)
19 {
20 $compiler
21 ->raw('twig_in_filter(')
22 ->subcompile($this->getNode('left'))
23 ->raw(', ')
24 ->subcompile($this->getNode('right'))
25 ->raw(')')
26 ;
27 }
28
29 public function operator(Twig_Compiler $compiler)
30 {
31 return $compiler->raw('in');
32 }
33}
diff --git a/inc/Twig/Node/Expression/Binary/Less.php b/inc/Twig/Node/Expression/Binary/Less.php
new file mode 100644
index 00000000..45fd3004
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Less.php
@@ -0,0 +1,17 @@
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 */
11class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary
12{
13 public function operator(Twig_Compiler $compiler)
14 {
15 return $compiler->raw('<');
16 }
17}
diff --git a/inc/Twig/Node/Expression/Binary/LessEqual.php b/inc/Twig/Node/Expression/Binary/LessEqual.php
new file mode 100644
index 00000000..e38e257c
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/LessEqual.php
@@ -0,0 +1,17 @@
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 */
11class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary
12{
13 public function operator(Twig_Compiler $compiler)
14 {
15 return $compiler->raw('<=');
16 }
17}
diff --git a/inc/Twig/Node/Expression/Binary/Mod.php b/inc/Twig/Node/Expression/Binary/Mod.php
new file mode 100644
index 00000000..9924114f
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Mod.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('%');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/Mul.php b/inc/Twig/Node/Expression/Binary/Mul.php
new file mode 100644
index 00000000..c91529ca
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Mul.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('*');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/NotEqual.php b/inc/Twig/Node/Expression/Binary/NotEqual.php
new file mode 100644
index 00000000..26867ba2
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/NotEqual.php
@@ -0,0 +1,17 @@
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 */
11class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary
12{
13 public function operator(Twig_Compiler $compiler)
14 {
15 return $compiler->raw('!=');
16 }
17}
diff --git a/inc/Twig/Node/Expression/Binary/NotIn.php b/inc/Twig/Node/Expression/Binary/NotIn.php
new file mode 100644
index 00000000..f347b7b6
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/NotIn.php
@@ -0,0 +1,33 @@
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 */
11class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary
12{
13 /**
14 * Compiles the node to PHP.
15 *
16 * @param Twig_Compiler A Twig_Compiler instance
17 */
18 public function compile(Twig_Compiler $compiler)
19 {
20 $compiler
21 ->raw('!twig_in_filter(')
22 ->subcompile($this->getNode('left'))
23 ->raw(', ')
24 ->subcompile($this->getNode('right'))
25 ->raw(')')
26 ;
27 }
28
29 public function operator(Twig_Compiler $compiler)
30 {
31 return $compiler->raw('not in');
32 }
33}
diff --git a/inc/Twig/Node/Expression/Binary/Or.php b/inc/Twig/Node/Expression/Binary/Or.php
new file mode 100644
index 00000000..adba49c6
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Or.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('||');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Binary/Power.php b/inc/Twig/Node/Expression/Binary/Power.php
new file mode 100644
index 00000000..b2c59040
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Power.php
@@ -0,0 +1,33 @@
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 */
11class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
12{
13 /**
14 * Compiles the node to PHP.
15 *
16 * @param Twig_Compiler A Twig_Compiler instance
17 */
18 public function compile(Twig_Compiler $compiler)
19 {
20 $compiler
21 ->raw('pow(')
22 ->subcompile($this->getNode('left'))
23 ->raw(', ')
24 ->subcompile($this->getNode('right'))
25 ->raw(')')
26 ;
27 }
28
29 public function operator(Twig_Compiler $compiler)
30 {
31 return $compiler->raw('**');
32 }
33}
diff --git a/inc/Twig/Node/Expression/Binary/Range.php b/inc/Twig/Node/Expression/Binary/Range.php
new file mode 100644
index 00000000..bea4f2a6
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Range.php
@@ -0,0 +1,33 @@
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 */
11class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary
12{
13 /**
14 * Compiles the node to PHP.
15 *
16 * @param Twig_Compiler A Twig_Compiler instance
17 */
18 public function compile(Twig_Compiler $compiler)
19 {
20 $compiler
21 ->raw('range(')
22 ->subcompile($this->getNode('left'))
23 ->raw(', ')
24 ->subcompile($this->getNode('right'))
25 ->raw(')')
26 ;
27 }
28
29 public function operator(Twig_Compiler $compiler)
30 {
31 return $compiler->raw('..');
32 }
33}
diff --git a/inc/Twig/Node/Expression/Binary/Sub.php b/inc/Twig/Node/Expression/Binary/Sub.php
new file mode 100644
index 00000000..d4463991
--- /dev/null
+++ b/inc/Twig/Node/Expression/Binary/Sub.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 return $compiler->raw('-');
17 }
18}
diff --git a/inc/Twig/Node/Expression/BlockReference.php b/inc/Twig/Node/Expression/BlockReference.php
new file mode 100644
index 00000000..647196eb
--- /dev/null
+++ b/inc/Twig/Node/Expression/BlockReference.php
@@ -0,0 +1,51 @@
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 * Represents a block call node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
19{
20 public function __construct(Twig_NodeInterface $name, $asString = false, $lineno, $tag = null)
21 {
22 parent::__construct(array('name' => $name), array('as_string' => $asString, 'output' => false), $lineno, $tag);
23 }
24
25 /**
26 * Compiles the node to PHP.
27 *
28 * @param Twig_Compiler A Twig_Compiler instance
29 */
30 public function compile(Twig_Compiler $compiler)
31 {
32 if ($this->getAttribute('as_string')) {
33 $compiler->raw('(string) ');
34 }
35
36 if ($this->getAttribute('output')) {
37 $compiler
38 ->addDebugInfo($this)
39 ->write("\$this->displayBlock(")
40 ->subcompile($this->getNode('name'))
41 ->raw(", \$context, \$blocks);\n")
42 ;
43 } else {
44 $compiler
45 ->raw("\$this->renderBlock(")
46 ->subcompile($this->getNode('name'))
47 ->raw(", \$context, \$blocks)")
48 ;
49 }
50 }
51}
diff --git a/inc/Twig/Node/Expression/Call.php b/inc/Twig/Node/Expression/Call.php
new file mode 100644
index 00000000..87b62deb
--- /dev/null
+++ b/inc/Twig/Node/Expression/Call.php
@@ -0,0 +1,178 @@
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 */
11abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
12{
13 protected function compileCallable(Twig_Compiler $compiler)
14 {
15 $callable = $this->getAttribute('callable');
16
17 $closingParenthesis = false;
18 if ($callable) {
19 if (is_string($callable)) {
20 $compiler->raw($callable);
21 } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
22 $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1]));
23 } else {
24 $type = ucfirst($this->getAttribute('type'));
25 $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
26 $closingParenthesis = true;
27 }
28 } else {
29 $compiler->raw($this->getAttribute('thing')->compile());
30 }
31
32 $this->compileArguments($compiler);
33
34 if ($closingParenthesis) {
35 $compiler->raw(')');
36 }
37 }
38
39 protected function compileArguments(Twig_Compiler $compiler)
40 {
41 $compiler->raw('(');
42
43 $first = true;
44
45 if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
46 $compiler->raw('$this->env');
47 $first = false;
48 }
49
50 if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
51 if (!$first) {
52 $compiler->raw(', ');
53 }
54 $compiler->raw('$context');
55 $first = false;
56 }
57
58 if ($this->hasAttribute('arguments')) {
59 foreach ($this->getAttribute('arguments') as $argument) {
60 if (!$first) {
61 $compiler->raw(', ');
62 }
63 $compiler->string($argument);
64 $first = false;
65 }
66 }
67
68 if ($this->hasNode('node')) {
69 if (!$first) {
70 $compiler->raw(', ');
71 }
72 $compiler->subcompile($this->getNode('node'));
73 $first = false;
74 }
75
76 if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) {
77 $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null;
78
79 $arguments = $this->getArguments($callable, $this->getNode('arguments'));
80
81 foreach ($arguments as $node) {
82 if (!$first) {
83 $compiler->raw(', ');
84 }
85 $compiler->subcompile($node);
86 $first = false;
87 }
88 }
89
90 $compiler->raw(')');
91 }
92
93 protected function getArguments($callable, $arguments)
94 {
95 $parameters = array();
96 $named = false;
97 foreach ($arguments as $name => $node) {
98 if (!is_int($name)) {
99 $named = true;
100 $name = $this->normalizeName($name);
101 } elseif ($named) {
102 throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
103 }
104
105 $parameters[$name] = $node;
106 }
107
108 if (!$named) {
109 return $parameters;
110 }
111
112 if (!$callable) {
113 throw new LogicException(sprintf('Named arguments are not supported for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
114 }
115
116 // manage named arguments
117 if (is_array($callable)) {
118 $r = new ReflectionMethod($callable[0], $callable[1]);
119 } elseif (is_object($callable) && !$callable instanceof Closure) {
120 $r = new ReflectionObject($callable);
121 $r = $r->getMethod('__invoke');
122 } else {
123 $r = new ReflectionFunction($callable);
124 }
125
126 $definition = $r->getParameters();
127 if ($this->hasNode('node')) {
128 array_shift($definition);
129 }
130 if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
131 array_shift($definition);
132 }
133 if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
134 array_shift($definition);
135 }
136 if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
137 foreach ($this->getAttribute('arguments') as $argument) {
138 array_shift($definition);
139 }
140 }
141
142 $arguments = array();
143 $pos = 0;
144 foreach ($definition as $param) {
145 $name = $this->normalizeName($param->name);
146
147 if (array_key_exists($name, $parameters)) {
148 if (array_key_exists($pos, $parameters)) {
149 throw new Twig_Error_Syntax(sprintf('Arguments "%s" is defined twice for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
150 }
151
152 $arguments[] = $parameters[$name];
153 unset($parameters[$name]);
154 } elseif (array_key_exists($pos, $parameters)) {
155 $arguments[] = $parameters[$pos];
156 unset($parameters[$pos]);
157 ++$pos;
158 } elseif ($param->isDefaultValueAvailable()) {
159 $arguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1);
160 } elseif ($param->isOptional()) {
161 break;
162 } else {
163 throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
164 }
165 }
166
167 foreach (array_keys($parameters) as $name) {
168 throw new Twig_Error_Syntax(sprintf('Unknown argument "%s" for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
169 }
170
171 return $arguments;
172 }
173
174 protected function normalizeName($name)
175 {
176 return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
177 }
178}
diff --git a/inc/Twig/Node/Expression/Conditional.php b/inc/Twig/Node/Expression/Conditional.php
new file mode 100644
index 00000000..edcb1e2d
--- /dev/null
+++ b/inc/Twig/Node/Expression/Conditional.php
@@ -0,0 +1,31 @@
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 */
12class Twig_Node_Expression_Conditional extends Twig_Node_Expression
13{
14 public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno)
15 {
16 parent::__construct(array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno);
17 }
18
19 public function compile(Twig_Compiler $compiler)
20 {
21 $compiler
22 ->raw('((')
23 ->subcompile($this->getNode('expr1'))
24 ->raw(') ? (')
25 ->subcompile($this->getNode('expr2'))
26 ->raw(') : (')
27 ->subcompile($this->getNode('expr3'))
28 ->raw('))')
29 ;
30 }
31}
diff --git a/inc/Twig/Node/Expression/Constant.php b/inc/Twig/Node/Expression/Constant.php
new file mode 100644
index 00000000..a91dc698
--- /dev/null
+++ b/inc/Twig/Node/Expression/Constant.php
@@ -0,0 +1,23 @@
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 */
12class Twig_Node_Expression_Constant extends Twig_Node_Expression
13{
14 public function __construct($value, $lineno)
15 {
16 parent::__construct(array(), array('value' => $value), $lineno);
17 }
18
19 public function compile(Twig_Compiler $compiler)
20 {
21 $compiler->repr($this->getAttribute('value'));
22 }
23}
diff --git a/inc/Twig/Node/Expression/ExtensionReference.php b/inc/Twig/Node/Expression/ExtensionReference.php
new file mode 100644
index 00000000..00ac6701
--- /dev/null
+++ b/inc/Twig/Node/Expression/ExtensionReference.php
@@ -0,0 +1,33 @@
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 * Represents an extension call node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
18{
19 public function __construct($name, $lineno, $tag = null)
20 {
21 parent::__construct(array(), array('name' => $name), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param Twig_Compiler A Twig_Compiler instance
28 */
29 public function compile(Twig_Compiler $compiler)
30 {
31 $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name')));
32 }
33}
diff --git a/inc/Twig/Node/Expression/Filter.php b/inc/Twig/Node/Expression/Filter.php
new file mode 100644
index 00000000..207b062a
--- /dev/null
+++ b/inc/Twig/Node/Expression/Filter.php
@@ -0,0 +1,36 @@
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 */
12class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
13{
14 public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
15 {
16 parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag);
17 }
18
19 public function compile(Twig_Compiler $compiler)
20 {
21 $name = $this->getNode('filter')->getAttribute('value');
22 $filter = $compiler->getEnvironment()->getFilter($name);
23
24 $this->setAttribute('name', $name);
25 $this->setAttribute('type', 'filter');
26 $this->setAttribute('thing', $filter);
27 $this->setAttribute('needs_environment', $filter->needsEnvironment());
28 $this->setAttribute('needs_context', $filter->needsContext());
29 $this->setAttribute('arguments', $filter->getArguments());
30 if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
31 $this->setAttribute('callable', $filter->getCallable());
32 }
33
34 $this->compileCallable($compiler);
35 }
36}
diff --git a/inc/Twig/Node/Expression/Filter/Default.php b/inc/Twig/Node/Expression/Filter/Default.php
new file mode 100644
index 00000000..1827c888
--- /dev/null
+++ b/inc/Twig/Node/Expression/Filter/Default.php
@@ -0,0 +1,43 @@
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 * Returns the value or the default value when it is undefined or empty.
14 *
15 * <pre>
16 * {{ var.foo|default('foo item on var is not defined') }}
17 * </pre>
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
22{
23 public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
24 {
25 $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getLine()), $arguments, $node->getLine());
26
27 if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) {
28 $test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getLine());
29 $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getLine());
30
31 $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getLine());
32 } else {
33 $node = $default;
34 }
35
36 parent::__construct($node, $filterName, $arguments, $lineno, $tag);
37 }
38
39 public function compile(Twig_Compiler $compiler)
40 {
41 $compiler->subcompile($this->getNode('node'));
42 }
43}
diff --git a/inc/Twig/Node/Expression/Function.php b/inc/Twig/Node/Expression/Function.php
new file mode 100644
index 00000000..3e1f6b55
--- /dev/null
+++ b/inc/Twig/Node/Expression/Function.php
@@ -0,0 +1,35 @@
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 */
11class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
12{
13 public function __construct($name, Twig_NodeInterface $arguments, $lineno)
14 {
15 parent::__construct(array('arguments' => $arguments), array('name' => $name), $lineno);
16 }
17
18 public function compile(Twig_Compiler $compiler)
19 {
20 $name = $this->getAttribute('name');
21 $function = $compiler->getEnvironment()->getFunction($name);
22
23 $this->setAttribute('name', $name);
24 $this->setAttribute('type', 'function');
25 $this->setAttribute('thing', $function);
26 $this->setAttribute('needs_environment', $function->needsEnvironment());
27 $this->setAttribute('needs_context', $function->needsContext());
28 $this->setAttribute('arguments', $function->getArguments());
29 if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
30 $this->setAttribute('callable', $function->getCallable());
31 }
32
33 $this->compileCallable($compiler);
34 }
35}
diff --git a/inc/Twig/Node/Expression/GetAttr.php b/inc/Twig/Node/Expression/GetAttr.php
new file mode 100644
index 00000000..81a9b137
--- /dev/null
+++ b/inc/Twig/Node/Expression/GetAttr.php
@@ -0,0 +1,53 @@
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 */
12class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
13{
14 public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno)
15 {
16 parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno);
17 }
18
19 public function compile(Twig_Compiler $compiler)
20 {
21 if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) {
22 $compiler->raw('twig_template_get_attributes($this, ');
23 } else {
24 $compiler->raw('$this->getAttribute(');
25 }
26
27 if ($this->getAttribute('ignore_strict_check')) {
28 $this->getNode('node')->setAttribute('ignore_strict_check', true);
29 }
30
31 $compiler->subcompile($this->getNode('node'));
32
33 $compiler->raw(', ')->subcompile($this->getNode('attribute'));
34
35 if (count($this->getNode('arguments')) || Twig_TemplateInterface::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
36 $compiler->raw(', ')->subcompile($this->getNode('arguments'));
37
38 if (Twig_TemplateInterface::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
39 $compiler->raw(', ')->repr($this->getAttribute('type'));
40 }
41
42 if ($this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
43 $compiler->raw(', '.($this->getAttribute('is_defined_test') ? 'true' : 'false'));
44 }
45
46 if ($this->getAttribute('ignore_strict_check')) {
47 $compiler->raw(', '.($this->getAttribute('ignore_strict_check') ? 'true' : 'false'));
48 }
49 }
50
51 $compiler->raw(')');
52 }
53}
diff --git a/inc/Twig/Node/Expression/MethodCall.php b/inc/Twig/Node/Expression/MethodCall.php
new file mode 100644
index 00000000..620b02bf
--- /dev/null
+++ b/inc/Twig/Node/Expression/MethodCall.php
@@ -0,0 +1,41 @@
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 */
11class Twig_Node_Expression_MethodCall extends Twig_Node_Expression
12{
13 public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno)
14 {
15 parent::__construct(array('node' => $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno);
16
17 if ($node instanceof Twig_Node_Expression_Name) {
18 $node->setAttribute('always_defined', true);
19 }
20 }
21
22 public function compile(Twig_Compiler $compiler)
23 {
24 $compiler
25 ->subcompile($this->getNode('node'))
26 ->raw('->')
27 ->raw($this->getAttribute('method'))
28 ->raw('(')
29 ;
30 $first = true;
31 foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) {
32 if (!$first) {
33 $compiler->raw(', ');
34 }
35 $first = false;
36
37 $compiler->subcompile($pair['value']);
38 }
39 $compiler->raw(')');
40 }
41}
diff --git a/inc/Twig/Node/Expression/Name.php b/inc/Twig/Node/Expression/Name.php
new file mode 100644
index 00000000..3b8fae01
--- /dev/null
+++ b/inc/Twig/Node/Expression/Name.php
@@ -0,0 +1,88 @@
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 */
12class Twig_Node_Expression_Name extends Twig_Node_Expression
13{
14 protected $specialVars = array(
15 '_self' => '$this',
16 '_context' => '$context',
17 '_charset' => '$this->env->getCharset()',
18 );
19
20 public function __construct($name, $lineno)
21 {
22 parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false), $lineno);
23 }
24
25 public function compile(Twig_Compiler $compiler)
26 {
27 $name = $this->getAttribute('name');
28
29 if ($this->getAttribute('is_defined_test')) {
30 if ($this->isSpecial()) {
31 $compiler->repr(true);
32 } else {
33 $compiler->raw('array_key_exists(')->repr($name)->raw(', $context)');
34 }
35 } elseif ($this->isSpecial()) {
36 $compiler->raw($this->specialVars[$name]);
37 } elseif ($this->getAttribute('always_defined')) {
38 $compiler
39 ->raw('$context[')
40 ->string($name)
41 ->raw(']')
42 ;
43 } else {
44 // remove the non-PHP 5.4 version when PHP 5.3 support is dropped
45 // as the non-optimized version is just a workaround for slow ternary operator
46 // when the context has a lot of variables
47 if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
48 // PHP 5.4 ternary operator performance was optimized
49 $compiler
50 ->raw('(isset($context[')
51 ->string($name)
52 ->raw(']) ? $context[')
53 ->string($name)
54 ->raw('] : ')
55 ;
56
57 if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) {
58 $compiler->raw('null)');
59 } else {
60 $compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
61 }
62 } else {
63 $compiler
64 ->raw('$this->getContext($context, ')
65 ->string($name)
66 ;
67
68 if ($this->getAttribute('ignore_strict_check')) {
69 $compiler->raw(', true');
70 }
71
72 $compiler
73 ->raw(')')
74 ;
75 }
76 }
77 }
78
79 public function isSpecial()
80 {
81 return isset($this->specialVars[$this->getAttribute('name')]);
82 }
83
84 public function isSimple()
85 {
86 return !$this->isSpecial() && !$this->getAttribute('is_defined_test');
87 }
88}
diff --git a/inc/Twig/Node/Expression/Parent.php b/inc/Twig/Node/Expression/Parent.php
new file mode 100644
index 00000000..dcf618c0
--- /dev/null
+++ b/inc/Twig/Node/Expression/Parent.php
@@ -0,0 +1,47 @@
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 * Represents a parent node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_Expression_Parent extends Twig_Node_Expression
19{
20 public function __construct($name, $lineno, $tag = null)
21 {
22 parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag);
23 }
24
25 /**
26 * Compiles the node to PHP.
27 *
28 * @param Twig_Compiler A Twig_Compiler instance
29 */
30 public function compile(Twig_Compiler $compiler)
31 {
32 if ($this->getAttribute('output')) {
33 $compiler
34 ->addDebugInfo($this)
35 ->write("\$this->displayParentBlock(")
36 ->string($this->getAttribute('name'))
37 ->raw(", \$context, \$blocks);\n")
38 ;
39 } else {
40 $compiler
41 ->raw("\$this->renderParentBlock(")
42 ->string($this->getAttribute('name'))
43 ->raw(", \$context, \$blocks)")
44 ;
45 }
46 }
47}
diff --git a/inc/Twig/Node/Expression/TempName.php b/inc/Twig/Node/Expression/TempName.php
new file mode 100644
index 00000000..e6b058e8
--- /dev/null
+++ b/inc/Twig/Node/Expression/TempName.php
@@ -0,0 +1,26 @@
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 */
11class Twig_Node_Expression_TempName extends Twig_Node_Expression
12{
13 public function __construct($name, $lineno)
14 {
15 parent::__construct(array(), array('name' => $name), $lineno);
16 }
17
18 public function compile(Twig_Compiler $compiler)
19 {
20 $compiler
21 ->raw('$_')
22 ->raw($this->getAttribute('name'))
23 ->raw('_')
24 ;
25 }
26}
diff --git a/inc/Twig/Node/Expression/Test.php b/inc/Twig/Node/Expression/Test.php
new file mode 100644
index 00000000..639f501a
--- /dev/null
+++ b/inc/Twig/Node/Expression/Test.php
@@ -0,0 +1,32 @@
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 */
11class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
12{
13 public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
14 {
15 parent::__construct(array('node' => $node, 'arguments' => $arguments), array('name' => $name), $lineno);
16 }
17
18 public function compile(Twig_Compiler $compiler)
19 {
20 $name = $this->getAttribute('name');
21 $test = $compiler->getEnvironment()->getTest($name);
22
23 $this->setAttribute('name', $name);
24 $this->setAttribute('type', 'test');
25 $this->setAttribute('thing', $test);
26 if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
27 $this->setAttribute('callable', $test->getCallable());
28 }
29
30 $this->compileCallable($compiler);
31 }
32}
diff --git a/inc/Twig/Node/Expression/Test/Constant.php b/inc/Twig/Node/Expression/Test/Constant.php
new file mode 100644
index 00000000..de55f5f5
--- /dev/null
+++ b/inc/Twig/Node/Expression/Test/Constant.php
@@ -0,0 +1,46 @@
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 * Checks if a variable is the exact same value as a constant.
14 *
15 * <pre>
16 * {% if post.status is constant('Post::PUBLISHED') %}
17 * the status attribute is exactly the same as Post::PUBLISHED
18 * {% endif %}
19 * </pre>
20 *
21 * @author Fabien Potencier <fabien@symfony.com>
22 */
23class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
24{
25 public function compile(Twig_Compiler $compiler)
26 {
27 $compiler
28 ->raw('(')
29 ->subcompile($this->getNode('node'))
30 ->raw(' === constant(')
31 ;
32
33 if ($this->getNode('arguments')->hasNode(1)) {
34 $compiler
35 ->raw('get_class(')
36 ->subcompile($this->getNode('arguments')->getNode(1))
37 ->raw(')."::".')
38 ;
39 }
40
41 $compiler
42 ->subcompile($this->getNode('arguments')->getNode(0))
43 ->raw('))')
44 ;
45 }
46}
diff --git a/inc/Twig/Node/Expression/Test/Defined.php b/inc/Twig/Node/Expression/Test/Defined.php
new file mode 100644
index 00000000..247b2e23
--- /dev/null
+++ b/inc/Twig/Node/Expression/Test/Defined.php
@@ -0,0 +1,54 @@
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 * Checks if a variable is defined in the current context.
14 *
15 * <pre>
16 * {# defined works with variable names and variable attributes #}
17 * {% if foo is defined %}
18 * {# ... #}
19 * {% endif %}
20 * </pre>
21 *
22 * @author Fabien Potencier <fabien@symfony.com>
23 */
24class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
25{
26 public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
27 {
28 parent::__construct($node, $name, $arguments, $lineno);
29
30 if ($node instanceof Twig_Node_Expression_Name) {
31 $node->setAttribute('is_defined_test', true);
32 } elseif ($node instanceof Twig_Node_Expression_GetAttr) {
33 $node->setAttribute('is_defined_test', true);
34
35 $this->changeIgnoreStrictCheck($node);
36 } else {
37 throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine());
38 }
39 }
40
41 protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node)
42 {
43 $node->setAttribute('ignore_strict_check', true);
44
45 if ($node->getNode('node') instanceof Twig_Node_Expression_GetAttr) {
46 $this->changeIgnoreStrictCheck($node->getNode('node'));
47 }
48 }
49
50 public function compile(Twig_Compiler $compiler)
51 {
52 $compiler->subcompile($this->getNode('node'));
53 }
54}
diff --git a/inc/Twig/Node/Expression/Test/Divisibleby.php b/inc/Twig/Node/Expression/Test/Divisibleby.php
new file mode 100644
index 00000000..0aceb530
--- /dev/null
+++ b/inc/Twig/Node/Expression/Test/Divisibleby.php
@@ -0,0 +1,33 @@
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 * Checks if a variable is divisible by a number.
14 *
15 * <pre>
16 * {% if loop.index is divisibleby(3) %}
17 * </pre>
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test
22{
23 public function compile(Twig_Compiler $compiler)
24 {
25 $compiler
26 ->raw('(0 == ')
27 ->subcompile($this->getNode('node'))
28 ->raw(' % ')
29 ->subcompile($this->getNode('arguments')->getNode(0))
30 ->raw(')')
31 ;
32 }
33}
diff --git a/inc/Twig/Node/Expression/Test/Even.php b/inc/Twig/Node/Expression/Test/Even.php
new file mode 100644
index 00000000..d7853e89
--- /dev/null
+++ b/inc/Twig/Node/Expression/Test/Even.php
@@ -0,0 +1,32 @@
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 * Checks if a number is even.
14 *
15 * <pre>
16 * {{ var is even }}
17 * </pre>
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
22{
23 public function compile(Twig_Compiler $compiler)
24 {
25 $compiler
26 ->raw('(')
27 ->subcompile($this->getNode('node'))
28 ->raw(' % 2 == 0')
29 ->raw(')')
30 ;
31 }
32}
diff --git a/inc/Twig/Node/Expression/Test/Null.php b/inc/Twig/Node/Expression/Test/Null.php
new file mode 100644
index 00000000..1c83825a
--- /dev/null
+++ b/inc/Twig/Node/Expression/Test/Null.php
@@ -0,0 +1,31 @@
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 * Checks that a variable is null.
14 *
15 * <pre>
16 * {{ var is none }}
17 * </pre>
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
22{
23 public function compile(Twig_Compiler $compiler)
24 {
25 $compiler
26 ->raw('(null === ')
27 ->subcompile($this->getNode('node'))
28 ->raw(')')
29 ;
30 }
31}
diff --git a/inc/Twig/Node/Expression/Test/Odd.php b/inc/Twig/Node/Expression/Test/Odd.php
new file mode 100644
index 00000000..421c19e8
--- /dev/null
+++ b/inc/Twig/Node/Expression/Test/Odd.php
@@ -0,0 +1,32 @@
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 * Checks if a number is odd.
14 *
15 * <pre>
16 * {{ var is odd }}
17 * </pre>
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
22{
23 public function compile(Twig_Compiler $compiler)
24 {
25 $compiler
26 ->raw('(')
27 ->subcompile($this->getNode('node'))
28 ->raw(' % 2 == 1')
29 ->raw(')')
30 ;
31 }
32}
diff --git a/inc/Twig/Node/Expression/Test/Sameas.php b/inc/Twig/Node/Expression/Test/Sameas.php
new file mode 100644
index 00000000..b48905ee
--- /dev/null
+++ b/inc/Twig/Node/Expression/Test/Sameas.php
@@ -0,0 +1,29 @@
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 * Checks if a variable is the same as another one (=== in PHP).
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test
18{
19 public function compile(Twig_Compiler $compiler)
20 {
21 $compiler
22 ->raw('(')
23 ->subcompile($this->getNode('node'))
24 ->raw(' === ')
25 ->subcompile($this->getNode('arguments')->getNode(0))
26 ->raw(')')
27 ;
28 }
29}
diff --git a/inc/Twig/Node/Expression/Unary.php b/inc/Twig/Node/Expression/Unary.php
new file mode 100644
index 00000000..c514388e
--- /dev/null
+++ b/inc/Twig/Node/Expression/Unary.php
@@ -0,0 +1,30 @@
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 */
12abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression
13{
14 public function __construct(Twig_NodeInterface $node, $lineno)
15 {
16 parent::__construct(array('node' => $node), array(), $lineno);
17 }
18
19 public function compile(Twig_Compiler $compiler)
20 {
21 $compiler->raw('(');
22 $this->operator($compiler);
23 $compiler
24 ->subcompile($this->getNode('node'))
25 ->raw(')')
26 ;
27 }
28
29 abstract public function operator(Twig_Compiler $compiler);
30}
diff --git a/inc/Twig/Node/Expression/Unary/Neg.php b/inc/Twig/Node/Expression/Unary/Neg.php
new file mode 100644
index 00000000..2a3937ec
--- /dev/null
+++ b/inc/Twig/Node/Expression/Unary/Neg.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 $compiler->raw('-');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Unary/Not.php b/inc/Twig/Node/Expression/Unary/Not.php
new file mode 100644
index 00000000..f94073cf
--- /dev/null
+++ b/inc/Twig/Node/Expression/Unary/Not.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 $compiler->raw('!');
17 }
18}
diff --git a/inc/Twig/Node/Expression/Unary/Pos.php b/inc/Twig/Node/Expression/Unary/Pos.php
new file mode 100644
index 00000000..04edb52a
--- /dev/null
+++ b/inc/Twig/Node/Expression/Unary/Pos.php
@@ -0,0 +1,18 @@
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 */
12class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary
13{
14 public function operator(Twig_Compiler $compiler)
15 {
16 $compiler->raw('+');
17 }
18}
diff --git a/inc/Twig/Node/Flush.php b/inc/Twig/Node/Flush.php
new file mode 100644
index 00000000..0467ddce
--- /dev/null
+++ b/inc/Twig/Node/Flush.php
@@ -0,0 +1,36 @@
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 * Represents a flush node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Flush extends Twig_Node
18{
19 public function __construct($lineno, $tag)
20 {
21 parent::__construct(array(), array(), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param Twig_Compiler A Twig_Compiler instance
28 */
29 public function compile(Twig_Compiler $compiler)
30 {
31 $compiler
32 ->addDebugInfo($this)
33 ->write("flush();\n")
34 ;
35 }
36}
diff --git a/inc/Twig/Node/For.php b/inc/Twig/Node/For.php
new file mode 100644
index 00000000..d1ff371d
--- /dev/null
+++ b/inc/Twig/Node/For.php
@@ -0,0 +1,112 @@
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 * Represents a for node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_For extends Twig_Node
19{
20 protected $loop;
21
22 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)
23 {
24 $body = new Twig_Node(array($body, $this->loop = new Twig_Node_ForLoop($lineno, $tag)));
25
26 if (null !== $ifexpr) {
27 $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag);
28 }
29
30 parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag);
31 }
32
33 /**
34 * Compiles the node to PHP.
35 *
36 * @param Twig_Compiler A Twig_Compiler instance
37 */
38 public function compile(Twig_Compiler $compiler)
39 {
40 $compiler
41 ->addDebugInfo($this)
42 // the (array) cast bypasses a PHP 5.2.6 bug
43 ->write("\$context['_parent'] = (array) \$context;\n")
44 ->write("\$context['_seq'] = twig_ensure_traversable(")
45 ->subcompile($this->getNode('seq'))
46 ->raw(");\n")
47 ;
48
49 if (null !== $this->getNode('else')) {
50 $compiler->write("\$context['_iterated'] = false;\n");
51 }
52
53 if ($this->getAttribute('with_loop')) {
54 $compiler
55 ->write("\$context['loop'] = array(\n")
56 ->write(" 'parent' => \$context['_parent'],\n")
57 ->write(" 'index0' => 0,\n")
58 ->write(" 'index' => 1,\n")
59 ->write(" 'first' => true,\n")
60 ->write(");\n")
61 ;
62
63 if (!$this->getAttribute('ifexpr')) {
64 $compiler
65 ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n")
66 ->indent()
67 ->write("\$length = count(\$context['_seq']);\n")
68 ->write("\$context['loop']['revindex0'] = \$length - 1;\n")
69 ->write("\$context['loop']['revindex'] = \$length;\n")
70 ->write("\$context['loop']['length'] = \$length;\n")
71 ->write("\$context['loop']['last'] = 1 === \$length;\n")
72 ->outdent()
73 ->write("}\n")
74 ;
75 }
76 }
77
78 $this->loop->setAttribute('else', null !== $this->getNode('else'));
79 $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop'));
80 $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr'));
81
82 $compiler
83 ->write("foreach (\$context['_seq'] as ")
84 ->subcompile($this->getNode('key_target'))
85 ->raw(" => ")
86 ->subcompile($this->getNode('value_target'))
87 ->raw(") {\n")
88 ->indent()
89 ->subcompile($this->getNode('body'))
90 ->outdent()
91 ->write("}\n")
92 ;
93
94 if (null !== $this->getNode('else')) {
95 $compiler
96 ->write("if (!\$context['_iterated']) {\n")
97 ->indent()
98 ->subcompile($this->getNode('else'))
99 ->outdent()
100 ->write("}\n")
101 ;
102 }
103
104 $compiler->write("\$_parent = \$context['_parent'];\n");
105
106 // remove some "private" loop variables (needed for nested loops)
107 $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
108
109 // keep the values set in the inner context for variables defined in the outer context
110 $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n");
111 }
112}
diff --git a/inc/Twig/Node/ForLoop.php b/inc/Twig/Node/ForLoop.php
new file mode 100644
index 00000000..b8841583
--- /dev/null
+++ b/inc/Twig/Node/ForLoop.php
@@ -0,0 +1,55 @@
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 * Internal node used by the for node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_ForLoop extends Twig_Node
18{
19 public function __construct($lineno, $tag = null)
20 {
21 parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param Twig_Compiler A Twig_Compiler instance
28 */
29 public function compile(Twig_Compiler $compiler)
30 {
31 if ($this->getAttribute('else')) {
32 $compiler->write("\$context['_iterated'] = true;\n");
33 }
34
35 if ($this->getAttribute('with_loop')) {
36 $compiler
37 ->write("++\$context['loop']['index0'];\n")
38 ->write("++\$context['loop']['index'];\n")
39 ->write("\$context['loop']['first'] = false;\n")
40 ;
41
42 if (!$this->getAttribute('ifexpr')) {
43 $compiler
44 ->write("if (isset(\$context['loop']['length'])) {\n")
45 ->indent()
46 ->write("--\$context['loop']['revindex0'];\n")
47 ->write("--\$context['loop']['revindex'];\n")
48 ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
49 ->outdent()
50 ->write("}\n")
51 ;
52 }
53 }
54 }
55}
diff --git a/inc/Twig/Node/If.php b/inc/Twig/Node/If.php
new file mode 100644
index 00000000..4296a8d6
--- /dev/null
+++ b/inc/Twig/Node/If.php
@@ -0,0 +1,66 @@
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 * Represents an if node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_If extends Twig_Node
19{
20 public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null)
21 {
22 parent::__construct(array('tests' => $tests, 'else' => $else), array(), $lineno, $tag);
23 }
24
25 /**
26 * Compiles the node to PHP.
27 *
28 * @param Twig_Compiler A Twig_Compiler instance
29 */
30 public function compile(Twig_Compiler $compiler)
31 {
32 $compiler->addDebugInfo($this);
33 for ($i = 0; $i < count($this->getNode('tests')); $i += 2) {
34 if ($i > 0) {
35 $compiler
36 ->outdent()
37 ->write("} elseif (")
38 ;
39 } else {
40 $compiler
41 ->write('if (')
42 ;
43 }
44
45 $compiler
46 ->subcompile($this->getNode('tests')->getNode($i))
47 ->raw(") {\n")
48 ->indent()
49 ->subcompile($this->getNode('tests')->getNode($i + 1))
50 ;
51 }
52
53 if ($this->hasNode('else') && null !== $this->getNode('else')) {
54 $compiler
55 ->outdent()
56 ->write("} else {\n")
57 ->indent()
58 ->subcompile($this->getNode('else'))
59 ;
60 }
61
62 $compiler
63 ->outdent()
64 ->write("}\n");
65 }
66}
diff --git a/inc/Twig/Node/Import.php b/inc/Twig/Node/Import.php
new file mode 100644
index 00000000..99efc091
--- /dev/null
+++ b/inc/Twig/Node/Import.php
@@ -0,0 +1,50 @@
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 * Represents an import node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Import extends Twig_Node
18{
19 public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null)
20 {
21 parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param Twig_Compiler A Twig_Compiler instance
28 */
29 public function compile(Twig_Compiler $compiler)
30 {
31 $compiler
32 ->addDebugInfo($this)
33 ->write('')
34 ->subcompile($this->getNode('var'))
35 ->raw(' = ')
36 ;
37
38 if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
39 $compiler->raw("\$this");
40 } else {
41 $compiler
42 ->raw('$this->env->loadTemplate(')
43 ->subcompile($this->getNode('expr'))
44 ->raw(")")
45 ;
46 }
47
48 $compiler->raw(";\n");
49 }
50}
diff --git a/inc/Twig/Node/Include.php b/inc/Twig/Node/Include.php
new file mode 100644
index 00000000..ed4a3751
--- /dev/null
+++ b/inc/Twig/Node/Include.php
@@ -0,0 +1,99 @@
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 * Represents an include node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
19{
20 public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
21 {
22 parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (Boolean) $only, 'ignore_missing' => (Boolean) $ignoreMissing), $lineno, $tag);
23 }
24
25 /**
26 * Compiles the node to PHP.
27 *
28 * @param Twig_Compiler A Twig_Compiler instance
29 */
30 public function compile(Twig_Compiler $compiler)
31 {
32 $compiler->addDebugInfo($this);
33
34 if ($this->getAttribute('ignore_missing')) {
35 $compiler
36 ->write("try {\n")
37 ->indent()
38 ;
39 }
40
41 $this->addGetTemplate($compiler);
42
43 $compiler->raw('->display(');
44
45 $this->addTemplateArguments($compiler);
46
47 $compiler->raw(");\n");
48
49 if ($this->getAttribute('ignore_missing')) {
50 $compiler
51 ->outdent()
52 ->write("} catch (Twig_Error_Loader \$e) {\n")
53 ->indent()
54 ->write("// ignore missing template\n")
55 ->outdent()
56 ->write("}\n\n")
57 ;
58 }
59 }
60
61 protected function addGetTemplate(Twig_Compiler $compiler)
62 {
63 if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) {
64 $compiler
65 ->write("\$this->env->loadTemplate(")
66 ->subcompile($this->getNode('expr'))
67 ->raw(")")
68 ;
69 } else {
70 $compiler
71 ->write("\$template = \$this->env->resolveTemplate(")
72 ->subcompile($this->getNode('expr'))
73 ->raw(");\n")
74 ->write('$template')
75 ;
76 }
77 }
78
79 protected function addTemplateArguments(Twig_Compiler $compiler)
80 {
81 if (false === $this->getAttribute('only')) {
82 if (null === $this->getNode('variables')) {
83 $compiler->raw('$context');
84 } else {
85 $compiler
86 ->raw('array_merge($context, ')
87 ->subcompile($this->getNode('variables'))
88 ->raw(')')
89 ;
90 }
91 } else {
92 if (null === $this->getNode('variables')) {
93 $compiler->raw('array()');
94 } else {
95 $compiler->subcompile($this->getNode('variables'));
96 }
97 }
98 }
99}
diff --git a/inc/Twig/Node/Macro.php b/inc/Twig/Node/Macro.php
new file mode 100644
index 00000000..89910618
--- /dev/null
+++ b/inc/Twig/Node/Macro.php
@@ -0,0 +1,96 @@
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 * Represents a macro node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Macro extends Twig_Node
18{
19 public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
20 {
21 parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param Twig_Compiler A Twig_Compiler instance
28 */
29 public function compile(Twig_Compiler $compiler)
30 {
31 $compiler
32 ->addDebugInfo($this)
33 ->write(sprintf("public function get%s(", $this->getAttribute('name')))
34 ;
35
36 $count = count($this->getNode('arguments'));
37 $pos = 0;
38 foreach ($this->getNode('arguments') as $name => $default) {
39 $compiler
40 ->raw('$_'.$name.' = ')
41 ->subcompile($default)
42 ;
43
44 if (++$pos < $count) {
45 $compiler->raw(', ');
46 }
47 }
48
49 $compiler
50 ->raw(")\n")
51 ->write("{\n")
52 ->indent()
53 ;
54
55 if (!count($this->getNode('arguments'))) {
56 $compiler->write("\$context = \$this->env->getGlobals();\n\n");
57 } else {
58 $compiler
59 ->write("\$context = \$this->env->mergeGlobals(array(\n")
60 ->indent()
61 ;
62
63 foreach ($this->getNode('arguments') as $name => $default) {
64 $compiler
65 ->write('')
66 ->string($name)
67 ->raw(' => $_'.$name)
68 ->raw(",\n")
69 ;
70 }
71
72 $compiler
73 ->outdent()
74 ->write("));\n\n")
75 ;
76 }
77
78 $compiler
79 ->write("\$blocks = array();\n\n")
80 ->write("ob_start();\n")
81 ->write("try {\n")
82 ->indent()
83 ->subcompile($this->getNode('body'))
84 ->outdent()
85 ->write("} catch (Exception \$e) {\n")
86 ->indent()
87 ->write("ob_end_clean();\n\n")
88 ->write("throw \$e;\n")
89 ->outdent()
90 ->write("}\n\n")
91 ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n")
92 ->outdent()
93 ->write("}\n\n")
94 ;
95 }
96}
diff --git a/inc/Twig/Node/Module.php b/inc/Twig/Node/Module.php
new file mode 100644
index 00000000..585048b8
--- /dev/null
+++ b/inc/Twig/Node/Module.php
@@ -0,0 +1,371 @@
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 * Represents a module node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_Module extends Twig_Node
19{
20 public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename)
21 {
22 // embedded templates are set as attributes so that they are only visited once by the visitors
23 parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits), array('filename' => $filename, 'index' => null, 'embedded_templates' => $embeddedTemplates), 1);
24 }
25
26 public function setIndex($index)
27 {
28 $this->setAttribute('index', $index);
29 }
30
31 /**
32 * Compiles the node to PHP.
33 *
34 * @param Twig_Compiler A Twig_Compiler instance
35 */
36 public function compile(Twig_Compiler $compiler)
37 {
38 $this->compileTemplate($compiler);
39
40 foreach ($this->getAttribute('embedded_templates') as $template) {
41 $compiler->subcompile($template);
42 }
43 }
44
45 protected function compileTemplate(Twig_Compiler $compiler)
46 {
47 if (!$this->getAttribute('index')) {
48 $compiler->write('<?php');
49 }
50
51 $this->compileClassHeader($compiler);
52
53 if (count($this->getNode('blocks')) || count($this->getNode('traits')) || null === $this->getNode('parent') || $this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
54 $this->compileConstructor($compiler);
55 }
56
57 $this->compileGetParent($compiler);
58
59 $this->compileDisplayHeader($compiler);
60
61 $this->compileDisplayBody($compiler);
62
63 $this->compileDisplayFooter($compiler);
64
65 $compiler->subcompile($this->getNode('blocks'));
66
67 $this->compileMacros($compiler);
68
69 $this->compileGetTemplateName($compiler);
70
71 $this->compileIsTraitable($compiler);
72
73 $this->compileDebugInfo($compiler);
74
75 $this->compileClassFooter($compiler);
76 }
77
78 protected function compileGetParent(Twig_Compiler $compiler)
79 {
80 if (null === $this->getNode('parent')) {
81 return;
82 }
83
84 $compiler
85 ->write("protected function doGetParent(array \$context)\n", "{\n")
86 ->indent()
87 ->write("return ")
88 ;
89
90 if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
91 $compiler->subcompile($this->getNode('parent'));
92 } else {
93 $compiler
94 ->raw("\$this->env->resolveTemplate(")
95 ->subcompile($this->getNode('parent'))
96 ->raw(")")
97 ;
98 }
99
100 $compiler
101 ->raw(";\n")
102 ->outdent()
103 ->write("}\n\n")
104 ;
105 }
106
107 protected function compileDisplayBody(Twig_Compiler $compiler)
108 {
109 $compiler->subcompile($this->getNode('body'));
110
111 if (null !== $this->getNode('parent')) {
112 if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
113 $compiler->write("\$this->parent");
114 } else {
115 $compiler->write("\$this->getParent(\$context)");
116 }
117 $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
118 }
119 }
120
121 protected function compileClassHeader(Twig_Compiler $compiler)
122 {
123 $compiler
124 ->write("\n\n")
125 // if the filename contains */, add a blank to avoid a PHP parse error
126 ->write("/* ".str_replace('*/', '* /', $this->getAttribute('filename'))." */\n")
127 ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index')))
128 ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
129 ->write("{\n")
130 ->indent()
131 ;
132 }
133
134 protected function compileConstructor(Twig_Compiler $compiler)
135 {
136 $compiler
137 ->write("public function __construct(Twig_Environment \$env)\n", "{\n")
138 ->indent()
139 ->write("parent::__construct(\$env);\n\n")
140 ;
141
142 // parent
143 if (null === $this->getNode('parent')) {
144 $compiler->write("\$this->parent = false;\n\n");
145 } elseif ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
146 $compiler
147 ->write("\$this->parent = \$this->env->loadTemplate(")
148 ->subcompile($this->getNode('parent'))
149 ->raw(");\n\n")
150 ;
151 }
152
153 $countTraits = count($this->getNode('traits'));
154 if ($countTraits) {
155 // traits
156 foreach ($this->getNode('traits') as $i => $trait) {
157 $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i));
158
159 $compiler
160 ->addDebugInfo($trait->getNode('template'))
161 ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
162 ->indent()
163 ->write("throw new Twig_Error_Runtime('Template \"'.")
164 ->subcompile($trait->getNode('template'))
165 ->raw(".'\" cannot be used as a trait.');\n")
166 ->outdent()
167 ->write("}\n")
168 ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
169 ;
170
171 foreach ($trait->getNode('targets') as $key => $value) {
172 $compiler
173 ->write(sprintf("\$_trait_%s_blocks[", $i))
174 ->subcompile($value)
175 ->raw(sprintf("] = \$_trait_%s_blocks[", $i))
176 ->string($key)
177 ->raw(sprintf("]; unset(\$_trait_%s_blocks[", $i))
178 ->string($key)
179 ->raw("]);\n\n")
180 ;
181 }
182 }
183
184 if ($countTraits > 1) {
185 $compiler
186 ->write("\$this->traits = array_merge(\n")
187 ->indent()
188 ;
189
190 for ($i = 0; $i < $countTraits; $i++) {
191 $compiler
192 ->write(sprintf("\$_trait_%s_blocks".($i == $countTraits - 1 ? '' : ',')."\n", $i))
193 ;
194 }
195
196 $compiler
197 ->outdent()
198 ->write(");\n\n")
199 ;
200 } else {
201 $compiler
202 ->write("\$this->traits = \$_trait_0_blocks;\n\n")
203 ;
204 }
205
206 $compiler
207 ->write("\$this->blocks = array_merge(\n")
208 ->indent()
209 ->write("\$this->traits,\n")
210 ->write("array(\n")
211 ;
212 } else {
213 $compiler
214 ->write("\$this->blocks = array(\n")
215 ;
216 }
217
218 // blocks
219 $compiler
220 ->indent()
221 ;
222
223 foreach ($this->getNode('blocks') as $name => $node) {
224 $compiler
225 ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name))
226 ;
227 }
228
229 if ($countTraits) {
230 $compiler
231 ->outdent()
232 ->write(")\n")
233 ;
234 }
235
236 $compiler
237 ->outdent()
238 ->write(");\n")
239 ->outdent()
240 ->write("}\n\n");
241 ;
242 }
243
244 protected function compileDisplayHeader(Twig_Compiler $compiler)
245 {
246 $compiler
247 ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n")
248 ->indent()
249 ;
250 }
251
252 protected function compileDisplayFooter(Twig_Compiler $compiler)
253 {
254 $compiler
255 ->outdent()
256 ->write("}\n\n")
257 ;
258 }
259
260 protected function compileClassFooter(Twig_Compiler $compiler)
261 {
262 $compiler
263 ->outdent()
264 ->write("}\n")
265 ;
266 }
267
268 protected function compileMacros(Twig_Compiler $compiler)
269 {
270 $compiler->subcompile($this->getNode('macros'));
271 }
272
273 protected function compileGetTemplateName(Twig_Compiler $compiler)
274 {
275 $compiler
276 ->write("public function getTemplateName()\n", "{\n")
277 ->indent()
278 ->write('return ')
279 ->repr($this->getAttribute('filename'))
280 ->raw(";\n")
281 ->outdent()
282 ->write("}\n\n")
283 ;
284 }
285
286 protected function compileIsTraitable(Twig_Compiler $compiler)
287 {
288 // A template can be used as a trait if:
289 // * it has no parent
290 // * it has no macros
291 // * it has no body
292 //
293 // Put another way, a template can be used as a trait if it
294 // only contains blocks and use statements.
295 $traitable = null === $this->getNode('parent') && 0 === count($this->getNode('macros'));
296 if ($traitable) {
297 if ($this->getNode('body') instanceof Twig_Node_Body) {
298 $nodes = $this->getNode('body')->getNode(0);
299 } else {
300 $nodes = $this->getNode('body');
301 }
302
303 if (!count($nodes)) {
304 $nodes = new Twig_Node(array($nodes));
305 }
306
307 foreach ($nodes as $node) {
308 if (!count($node)) {
309 continue;
310 }
311
312 if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
313 continue;
314 }
315
316 if ($node instanceof Twig_Node_BlockReference) {
317 continue;
318 }
319
320 $traitable = false;
321 break;
322 }
323 }
324
325 if ($traitable) {
326 return;
327 }
328
329 $compiler
330 ->write("public function isTraitable()\n", "{\n")
331 ->indent()
332 ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false'))
333 ->outdent()
334 ->write("}\n\n")
335 ;
336 }
337
338 protected function compileDebugInfo(Twig_Compiler $compiler)
339 {
340 $compiler
341 ->write("public function getDebugInfo()\n", "{\n")
342 ->indent()
343 ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true))))
344 ->outdent()
345 ->write("}\n")
346 ;
347 }
348
349 protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var)
350 {
351 if ($node instanceof Twig_Node_Expression_Constant) {
352 $compiler
353 ->write(sprintf("%s = \$this->env->loadTemplate(", $var))
354 ->subcompile($node)
355 ->raw(");\n")
356 ;
357 } else {
358 $compiler
359 ->write(sprintf("%s = ", $var))
360 ->subcompile($node)
361 ->raw(";\n")
362 ->write(sprintf("if (!%s", $var))
363 ->raw(" instanceof Twig_Template) {\n")
364 ->indent()
365 ->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var))
366 ->outdent()
367 ->write("}\n")
368 ;
369 }
370 }
371}
diff --git a/inc/Twig/Node/Print.php b/inc/Twig/Node/Print.php
new file mode 100644
index 00000000..b0c41d1d
--- /dev/null
+++ b/inc/Twig/Node/Print.php
@@ -0,0 +1,39 @@
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 * Represents a node that outputs an expression.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
19{
20 public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
21 {
22 parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
23 }
24
25 /**
26 * Compiles the node to PHP.
27 *
28 * @param Twig_Compiler A Twig_Compiler instance
29 */
30 public function compile(Twig_Compiler $compiler)
31 {
32 $compiler
33 ->addDebugInfo($this)
34 ->write('echo ')
35 ->subcompile($this->getNode('expr'))
36 ->raw(";\n")
37 ;
38 }
39}
diff --git a/inc/Twig/Node/Sandbox.php b/inc/Twig/Node/Sandbox.php
new file mode 100644
index 00000000..8cf3ed44
--- /dev/null
+++ b/inc/Twig/Node/Sandbox.php
@@ -0,0 +1,47 @@
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 * Represents a sandbox node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Sandbox extends Twig_Node
18{
19 public function __construct(Twig_NodeInterface $body, $lineno, $tag = null)
20 {
21 parent::__construct(array('body' => $body), array(), $lineno, $tag);
22 }
23
24 /**
25 * Compiles the node to PHP.
26 *
27 * @param Twig_Compiler A Twig_Compiler instance
28 */
29 public function compile(Twig_Compiler $compiler)
30 {
31 $compiler
32 ->addDebugInfo($this)
33 ->write("\$sandbox = \$this->env->getExtension('sandbox');\n")
34 ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
35 ->indent()
36 ->write("\$sandbox->enableSandbox();\n")
37 ->outdent()
38 ->write("}\n")
39 ->subcompile($this->getNode('body'))
40 ->write("if (!\$alreadySandboxed) {\n")
41 ->indent()
42 ->write("\$sandbox->disableSandbox();\n")
43 ->outdent()
44 ->write("}\n")
45 ;
46 }
47}
diff --git a/inc/Twig/Node/SandboxedModule.php b/inc/Twig/Node/SandboxedModule.php
new file mode 100644
index 00000000..be1f5daa
--- /dev/null
+++ b/inc/Twig/Node/SandboxedModule.php
@@ -0,0 +1,60 @@
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 * Represents a module node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_SandboxedModule extends Twig_Node_Module
19{
20 protected $usedFilters;
21 protected $usedTags;
22 protected $usedFunctions;
23
24 public function __construct(Twig_Node_Module $node, array $usedFilters, array $usedTags, array $usedFunctions)
25 {
26 parent::__construct($node->getNode('body'), $node->getNode('parent'), $node->getNode('blocks'), $node->getNode('macros'), $node->getNode('traits'), $node->getAttribute('embedded_templates'), $node->getAttribute('filename'), $node->getLine(), $node->getNodeTag());
27
28 $this->setAttribute('index', $node->getAttribute('index'));
29
30 $this->usedFilters = $usedFilters;
31 $this->usedTags = $usedTags;
32 $this->usedFunctions = $usedFunctions;
33 }
34
35 protected function compileDisplayBody(Twig_Compiler $compiler)
36 {
37 $compiler->write("\$this->checkSecurity();\n");
38
39 parent::compileDisplayBody($compiler);
40 }
41
42 protected function compileDisplayFooter(Twig_Compiler $compiler)
43 {
44 parent::compileDisplayFooter($compiler);
45
46 $compiler
47 ->write("protected function checkSecurity()\n", "{\n")
48 ->indent()
49 ->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
50 ->indent()
51 ->write(!$this->usedTags ? "array(),\n" : "array('".implode('\', \'', $this->usedTags)."'),\n")
52 ->write(!$this->usedFilters ? "array(),\n" : "array('".implode('\', \'', $this->usedFilters)."'),\n")
53 ->write(!$this->usedFunctions ? "array()\n" : "array('".implode('\', \'', $this->usedFunctions)."')\n")
54 ->outdent()
55 ->write(");\n")
56 ->outdent()
57 ->write("}\n\n")
58 ;
59 }
60}
diff --git a/inc/Twig/Node/SandboxedPrint.php b/inc/Twig/Node/SandboxedPrint.php
new file mode 100644
index 00000000..73dfaa96
--- /dev/null
+++ b/inc/Twig/Node/SandboxedPrint.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 * Twig_Node_SandboxedPrint adds a check for the __toString() method
14 * when the variable is an object and the sandbox is activated.
15 *
16 * When there is a simple Print statement, like {{ article }},
17 * and if the sandbox is enabled, we need to check that the __toString()
18 * method is allowed if 'article' is an object.
19 *
20 * @author Fabien Potencier <fabien@symfony.com>
21 */
22class Twig_Node_SandboxedPrint extends Twig_Node_Print
23{
24 public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
25 {
26 parent::__construct($expr, $lineno, $tag);
27 }
28
29 /**
30 * Compiles the node to PHP.
31 *
32 * @param Twig_Compiler A Twig_Compiler instance
33 */
34 public function compile(Twig_Compiler $compiler)
35 {
36 $compiler
37 ->addDebugInfo($this)
38 ->write('echo $this->env->getExtension(\'sandbox\')->ensureToStringAllowed(')
39 ->subcompile($this->getNode('expr'))
40 ->raw(");\n")
41 ;
42 }
43
44 /**
45 * Removes node filters.
46 *
47 * This is mostly needed when another visitor adds filters (like the escaper one).
48 *
49 * @param Twig_Node $node A Node
50 */
51 protected function removeNodeFilter($node)
52 {
53 if ($node instanceof Twig_Node_Expression_Filter) {
54 return $this->removeNodeFilter($node->getNode('node'));
55 }
56
57 return $node;
58 }
59}
diff --git a/inc/Twig/Node/Set.php b/inc/Twig/Node/Set.php
new file mode 100644
index 00000000..4c9c16ce
--- /dev/null
+++ b/inc/Twig/Node/Set.php
@@ -0,0 +1,101 @@
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 * Represents a set node.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Node_Set extends Twig_Node
18{
19 public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null)
20 {
21 parent::__construct(array('names' => $names, 'values' => $values), array('capture' => $capture, 'safe' => false), $lineno, $tag);
22
23 /*
24 * Optimizes the node when capture is used for a large block of text.
25 *
26 * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig_Markup("foo");
27 */
28 if ($this->getAttribute('capture')) {
29 $this->setAttribute('safe', true);
30
31 $values = $this->getNode('values');
32 if ($values instanceof Twig_Node_Text) {
33 $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getLine()));
34 $this->setAttribute('capture', false);
35 }
36 }
37 }
38
39 /**
40 * Compiles the node to PHP.
41 *
42 * @param Twig_Compiler A Twig_Compiler instance
43 */
44 public function compile(Twig_Compiler $compiler)
45 {
46 $compiler->addDebugInfo($this);
47
48 if (count($this->getNode('names')) > 1) {
49 $compiler->write('list(');
50 foreach ($this->getNode('names') as $idx => $node) {
51 if ($idx) {
52 $compiler->raw(', ');
53 }
54
55 $compiler->subcompile($node);
56 }
57 $compiler->raw(')');
58 } else {
59 if ($this->getAttribute('capture')) {
60 $compiler
61 ->write("ob_start();\n")
62 ->subcompile($this->getNode('values'))
63 ;
64 }
65
66 $compiler->subcompile($this->getNode('names'), false);
67
68 if ($this->getAttribute('capture')) {
69 $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())");
70 }
71 }
72
73 if (!$this->getAttribute('capture')) {
74 $compiler->raw(' = ');
75
76 if (count($this->getNode('names')) > 1) {
77 $compiler->write('array(');
78 foreach ($this->getNode('values') as $idx => $value) {
79 if ($idx) {
80 $compiler->raw(', ');
81 }
82
83 $compiler->subcompile($value);
84 }
85 $compiler->raw(')');
86 } else {
87 if ($this->getAttribute('safe')) {
88 $compiler
89 ->raw("('' === \$tmp = ")
90 ->subcompile($this->getNode('values'))
91 ->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())")
92 ;
93 } else {
94 $compiler->subcompile($this->getNode('values'));
95 }
96 }
97 }
98
99 $compiler->raw(";\n");
100 }
101}
diff --git a/inc/Twig/Node/SetTemp.php b/inc/Twig/Node/SetTemp.php
new file mode 100644
index 00000000..3bdd1cb7
--- /dev/null
+++ b/inc/Twig/Node/SetTemp.php
@@ -0,0 +1,35 @@
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
12class Twig_Node_SetTemp extends Twig_Node
13{
14 public function __construct($name, $lineno)
15 {
16 parent::__construct(array(), array('name' => $name), $lineno);
17 }
18
19 public function compile(Twig_Compiler $compiler)
20 {
21 $name = $this->getAttribute('name');
22 $compiler
23 ->addDebugInfo($this)
24 ->write('if (isset($context[')
25 ->string($name)
26 ->raw('])) { $_')
27 ->raw($name)
28 ->raw('_ = $context[')
29 ->repr($name)
30 ->raw(']; } else { $_')
31 ->raw($name)
32 ->raw("_ = null; }\n")
33 ;
34 }
35}
diff --git a/inc/Twig/Node/Spaceless.php b/inc/Twig/Node/Spaceless.php
new file mode 100644
index 00000000..7555fa0f
--- /dev/null
+++ b/inc/Twig/Node/Spaceless.php
@@ -0,0 +1,40 @@
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 * Represents a spaceless node.
14 *
15 * It removes spaces between HTML tags.
16 *
17 * @author Fabien Potencier <fabien@symfony.com>
18 */
19class Twig_Node_Spaceless extends Twig_Node
20{
21 public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
22 {
23 parent::__construct(array('body' => $body), array(), $lineno, $tag);
24 }
25
26 /**
27 * Compiles the node to PHP.
28 *
29 * @param Twig_Compiler A Twig_Compiler instance
30 */
31 public function compile(Twig_Compiler $compiler)
32 {
33 $compiler
34 ->addDebugInfo($this)
35 ->write("ob_start();\n")
36 ->subcompile($this->getNode('body'))
37 ->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n")
38 ;
39 }
40}
diff --git a/inc/Twig/Node/Text.php b/inc/Twig/Node/Text.php
new file mode 100644
index 00000000..21bdcea1
--- /dev/null
+++ b/inc/Twig/Node/Text.php
@@ -0,0 +1,39 @@
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 * Represents a text node.
15 *
16 * @author Fabien Potencier <fabien@symfony.com>
17 */
18class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
19{
20 public function __construct($data, $lineno)
21 {
22 parent::__construct(array(), array('data' => $data), $lineno);
23 }
24
25 /**
26 * Compiles the node to PHP.
27 *
28 * @param Twig_Compiler A Twig_Compiler instance
29 */
30 public function compile(Twig_Compiler $compiler)
31 {
32 $compiler
33 ->addDebugInfo($this)
34 ->write('echo ')
35 ->string($this->getAttribute('data'))
36 ->raw(";\n")
37 ;
38 }
39}