diff options
Diffstat (limited to 'inc/Twig/Node')
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 | */ | ||
23 | class 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 | */ | ||
18 | class 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 | */ | ||
18 | class 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 | */ | ||
17 | class 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 | */ | ||
17 | class 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 | */ | ||
17 | class 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 | */ | ||
18 | abstract 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 | */ | ||
11 | class 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 | |||
13 | class 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 | */ | ||
12 | abstract 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
11 | class 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 | */ | ||
11 | class 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 | */ | ||
11 | class 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 | */ | ||
11 | class 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 | */ | ||
11 | class 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 | */ | ||
11 | class 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 | */ | ||
11 | class 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
11 | class 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 | */ | ||
11 | class 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 | */ | ||
12 | class 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 | */ | ||
11 | class 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 | */ | ||
11 | class 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 | */ | ||
12 | class 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 | */ | ||
18 | class 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 | */ | ||
11 | abstract 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
17 | class 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 | */ | ||
12 | class 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 | */ | ||
21 | class 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 | */ | ||
11 | class 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 | */ | ||
12 | class 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 | */ | ||
11 | class 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 | */ | ||
12 | class 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 | */ | ||
18 | class 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 | */ | ||
11 | class 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 | */ | ||
11 | class 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 | */ | ||
23 | class 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 | */ | ||
24 | class 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 | */ | ||
21 | class 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 | */ | ||
21 | class 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 | */ | ||
21 | class 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 | */ | ||
21 | class 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 | */ | ||
17 | class 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 | */ | ||
12 | abstract 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
12 | class 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 | */ | ||
17 | class 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 | */ | ||
18 | class 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 | */ | ||
17 | class 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 | */ | ||
18 | class 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 | */ | ||
17 | class 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 | */ | ||
18 | class 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 | */ | ||
17 | class 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 | */ | ||
18 | class 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 | */ | ||
18 | class 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 | */ | ||
17 | class 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 | */ | ||
18 | class 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 | */ | ||
22 | class 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 | */ | ||
17 | class 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 | |||
12 | class 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 | */ | ||
19 | class 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 | */ | ||
18 | class 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 | } | ||