You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ih...@apache.org on 2012/05/22 16:42:31 UTC

svn commit: r1341499 [5/7] - in /logging/site/branches/experimental-twig-textile: ./ libs/Twig/ libs/Twig/lib/ libs/Twig/lib/Twig/ libs/Twig/lib/Twig/Error/ libs/Twig/lib/Twig/Extension/ libs/Twig/lib/Twig/Filter/ libs/Twig/lib/Twig/Function/ libs/Twig...

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Even.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Even.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Even.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Even.php Tue May 22 14:42:25 2012
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Checks if a number is even.
+ *
+ * <pre>
+ *  {{ var is even }}
+ * </pre>
+ *
+ * @package twig
+ * @author  Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
+{
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->raw('(')
+            ->subcompile($this->getNode('node'))
+            ->raw(' % 2 == 0')
+            ->raw(')')
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Null.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Null.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Null.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Null.php Tue May 22 14:42:25 2012
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Checks that a variable is null.
+ *
+ * <pre>
+ *  {{ var is none }}
+ * </pre>
+ *
+ * @package twig
+ * @author  Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
+{
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->raw('(null === ')
+            ->subcompile($this->getNode('node'))
+            ->raw(')')
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Odd.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Odd.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Odd.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Odd.php Tue May 22 14:42:25 2012
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Checks if a number is odd.
+ *
+ * <pre>
+ *  {{ var is odd }}
+ * </pre>
+ *
+ * @package twig
+ * @author  Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
+{
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->raw('(')
+            ->subcompile($this->getNode('node'))
+            ->raw(' % 2 == 1')
+            ->raw(')')
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Sameas.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Sameas.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Sameas.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Test/Sameas.php Tue May 22 14:42:25 2012
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Checks if a variable is the same as another one (=== in PHP).
+ *
+ * @package twig
+ * @author  Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test
+{
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->raw('(')
+            ->subcompile($this->getNode('node'))
+            ->raw(' === ')
+            ->subcompile($this->getNode('arguments')->getNode(0))
+            ->raw(')')
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary.php Tue May 22 14:42:25 2012
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression
+{
+    public function __construct(Twig_NodeInterface $node, $lineno)
+    {
+        parent::__construct(array('node' => $node), array(), $lineno);
+    }
+
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler->raw('(');
+        $this->operator($compiler);
+        $compiler
+            ->subcompile($this->getNode('node'))
+            ->raw(')')
+        ;
+    }
+
+    abstract public function operator(Twig_Compiler $compiler);
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Neg.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Neg.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Neg.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Neg.php Tue May 22 14:42:25 2012
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary
+{
+    public function operator(Twig_Compiler $compiler)
+    {
+        $compiler->raw('-');
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Not.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Not.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Not.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Not.php Tue May 22 14:42:25 2012
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary
+{
+    public function operator(Twig_Compiler $compiler)
+    {
+        $compiler->raw('!');
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Pos.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Pos.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Pos.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Expression/Unary/Pos.php Tue May 22 14:42:25 2012
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary
+{
+    public function operator(Twig_Compiler $compiler)
+    {
+        $compiler->raw('+');
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Flush.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Flush.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Flush.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Flush.php Tue May 22 14:42:25 2012
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a flush node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Flush extends Twig_Node
+{
+    public function __construct($lineno, $tag)
+    {
+        parent::__construct(array(), array(), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->addDebugInfo($this)
+            ->write("flush();\n")
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/For.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/For.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/For.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/For.php Tue May 22 14:42:25 2012
@@ -0,0 +1,113 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a for node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_For extends Twig_Node
+{
+    protected $loop;
+
+    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)
+    {
+        $body = new Twig_Node(array($body, $this->loop = new Twig_Node_ForLoop($lineno, $tag)));
+
+        if (null !== $ifexpr) {
+            $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag);
+        }
+
+        parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->addDebugInfo($this)
+            // the (array) cast bypasses a PHP 5.2.6 bug
+            ->write("\$context['_parent'] = (array) \$context;\n")
+            ->write("\$context['_seq'] = twig_ensure_traversable(")
+            ->subcompile($this->getNode('seq'))
+            ->raw(");\n")
+        ;
+
+        if (null !== $this->getNode('else')) {
+            $compiler->write("\$context['_iterated'] = false;\n");
+        }
+
+        if ($this->getAttribute('with_loop')) {
+            $compiler
+                ->write("\$context['loop'] = array(\n")
+                ->write("  'parent' => \$context['_parent'],\n")
+                ->write("  'index0' => 0,\n")
+                ->write("  'index'  => 1,\n")
+                ->write("  'first'  => true,\n")
+                ->write(");\n")
+            ;
+
+            if (!$this->getAttribute('ifexpr')) {
+                $compiler
+                    ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n")
+                    ->indent()
+                    ->write("\$length = count(\$context['_seq']);\n")
+                    ->write("\$context['loop']['revindex0'] = \$length - 1;\n")
+                    ->write("\$context['loop']['revindex'] = \$length;\n")
+                    ->write("\$context['loop']['length'] = \$length;\n")
+                    ->write("\$context['loop']['last'] = 1 === \$length;\n")
+                    ->outdent()
+                    ->write("}\n")
+                ;
+            }
+        }
+
+        $this->loop->setAttribute('else', null !== $this->getNode('else'));
+        $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop'));
+        $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr'));
+
+        $compiler
+            ->write("foreach (\$context['_seq'] as ")
+            ->subcompile($this->getNode('key_target'))
+            ->raw(" => ")
+            ->subcompile($this->getNode('value_target'))
+            ->raw(") {\n")
+            ->indent()
+            ->subcompile($this->getNode('body'))
+            ->outdent()
+            ->write("}\n")
+        ;
+
+        if (null !== $this->getNode('else')) {
+            $compiler
+                ->write("if (!\$context['_iterated']) {\n")
+                ->indent()
+                ->subcompile($this->getNode('else'))
+                ->outdent()
+                ->write("}\n")
+            ;
+        }
+
+        $compiler->write("\$_parent = \$context['_parent'];\n");
+
+        // remove some "private" loop variables (needed for nested loops)
+        $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");
+
+        // keep the values set in the inner context for variables defined in the outer context
+        $compiler->write("\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));\n");
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/ForLoop.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/ForLoop.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/ForLoop.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/ForLoop.php Tue May 22 14:42:25 2012
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Internal node used by the for node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_ForLoop extends Twig_Node
+{
+    public function __construct($lineno, $tag = null)
+    {
+        parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        if ($this->getAttribute('else')) {
+            $compiler->write("\$context['_iterated'] = true;\n");
+        }
+
+        if ($this->getAttribute('with_loop')) {
+            $compiler
+                ->write("++\$context['loop']['index0'];\n")
+                ->write("++\$context['loop']['index'];\n")
+                ->write("\$context['loop']['first'] = false;\n")
+            ;
+
+            if (!$this->getAttribute('ifexpr')) {
+                $compiler
+                    ->write("if (isset(\$context['loop']['length'])) {\n")
+                    ->indent()
+                    ->write("--\$context['loop']['revindex0'];\n")
+                    ->write("--\$context['loop']['revindex'];\n")
+                    ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
+                    ->outdent()
+                    ->write("}\n")
+                ;
+            }
+        }
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/If.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/If.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/If.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/If.php Tue May 22 14:42:25 2012
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents an if node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_If extends Twig_Node
+{
+    public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null)
+    {
+        parent::__construct(array('tests' => $tests, 'else' => $else), array(), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler->addDebugInfo($this);
+        for ($i = 0; $i < count($this->getNode('tests')); $i += 2) {
+            if ($i > 0) {
+                $compiler
+                    ->outdent()
+                    ->write("} elseif (")
+                ;
+            } else {
+                $compiler
+                    ->write('if (')
+                ;
+            }
+
+            $compiler
+                ->subcompile($this->getNode('tests')->getNode($i))
+                ->raw(") {\n")
+                ->indent()
+                ->subcompile($this->getNode('tests')->getNode($i + 1))
+            ;
+        }
+
+        if ($this->hasNode('else') && null !== $this->getNode('else')) {
+            $compiler
+                ->outdent()
+                ->write("} else {\n")
+                ->indent()
+                ->subcompile($this->getNode('else'))
+            ;
+        }
+
+        $compiler
+            ->outdent()
+            ->write("}\n");
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Import.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Import.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Import.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Import.php Tue May 22 14:42:25 2012
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents an import node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Import extends Twig_Node
+{
+    public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null)
+    {
+        parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->addDebugInfo($this)
+            ->write('')
+            ->subcompile($this->getNode('var'))
+            ->raw(' = ')
+        ;
+
+        if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
+            $compiler->raw("\$this");
+        } else {
+            $compiler
+                ->raw('$this->env->loadTemplate(')
+                ->subcompile($this->getNode('expr'))
+                ->raw(")")
+            ;
+        }
+
+        $compiler->raw(";\n");
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Include.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Include.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Include.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Include.php Tue May 22 14:42:25 2012
@@ -0,0 +1,100 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents an include node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
+{
+    public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
+    {
+        parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (Boolean) $only, 'ignore_missing' => (Boolean) $ignoreMissing), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler->addDebugInfo($this);
+
+        if ($this->getAttribute('ignore_missing')) {
+            $compiler
+                ->write("try {\n")
+                ->indent()
+            ;
+        }
+
+        $this->addGetTemplate($compiler);
+
+        $compiler->raw('->display(');
+
+        $this->addTemplateArguments($compiler);
+
+        $compiler->raw(");\n");
+
+        if ($this->getAttribute('ignore_missing')) {
+            $compiler
+                ->outdent()
+                ->write("} catch (Twig_Error_Loader \$e) {\n")
+                ->indent()
+                ->write("// ignore missing template\n")
+                ->outdent()
+                ->write("}\n\n")
+            ;
+        }
+    }
+
+    protected function addGetTemplate(Twig_Compiler $compiler)
+    {
+        if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) {
+            $compiler
+                ->write("\$this->env->loadTemplate(")
+                ->subcompile($this->getNode('expr'))
+                ->raw(")")
+            ;
+        } else {
+            $compiler
+                ->write("\$template = \$this->env->resolveTemplate(")
+                ->subcompile($this->getNode('expr'))
+                ->raw(");\n")
+                ->write('$template')
+            ;
+        }
+    }
+
+    protected function addTemplateArguments(Twig_Compiler $compiler)
+    {
+        if (false === $this->getAttribute('only')) {
+            if (null === $this->getNode('variables')) {
+                $compiler->raw('$context');
+            } else {
+                $compiler
+                    ->raw('array_merge($context, ')
+                    ->subcompile($this->getNode('variables'))
+                    ->raw(')')
+                ;
+            }
+        } else {
+            if (null === $this->getNode('variables')) {
+                $compiler->raw('array()');
+            } else {
+                $compiler->subcompile($this->getNode('variables'));
+            }
+        }
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Macro.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Macro.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Macro.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Macro.php Tue May 22 14:42:25 2012
@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a macro node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Macro extends Twig_Node
+{
+    public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
+    {
+        parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $arguments = array();
+        foreach ($this->getNode('arguments') as $argument) {
+            $arguments[] = '$'.$argument->getAttribute('name').' = null';
+        }
+
+        $compiler
+            ->addDebugInfo($this)
+            ->write(sprintf("public function get%s(%s)\n", $this->getAttribute('name'), implode(', ', $arguments)), "{\n")
+            ->indent()
+        ;
+
+        if (!count($this->getNode('arguments'))) {
+            $compiler->write("\$context = \$this->env->getGlobals();\n\n");
+        } else {
+            $compiler
+                ->write("\$context = \$this->env->mergeGlobals(array(\n")
+                ->indent()
+            ;
+
+            foreach ($this->getNode('arguments') as $argument) {
+                $compiler
+                    ->write('')
+                    ->string($argument->getAttribute('name'))
+                    ->raw(' => $'.$argument->getAttribute('name'))
+                    ->raw(",\n")
+                ;
+            }
+
+            $compiler
+                ->outdent()
+                ->write("));\n\n")
+            ;
+        }
+
+        $compiler
+            ->write("\$blocks = array();\n\n")
+            ->write("ob_start();\n")
+            ->write("try {\n")
+            ->indent()
+            ->subcompile($this->getNode('body'))
+            ->outdent()
+            ->write("} catch(Exception \$e) {\n")
+            ->indent()
+            ->write("ob_end_clean();\n\n")
+            ->write("throw \$e;\n")
+            ->outdent()
+            ->write("}\n\n")
+            ->write("return ob_get_clean();\n")
+            ->outdent()
+            ->write("}\n\n")
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Module.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Module.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Module.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Module.php Tue May 22 14:42:25 2012
@@ -0,0 +1,372 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a module node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Module extends Twig_Node
+{
+    public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename)
+    {
+        // embedded templates are set as attributes so that they are only visited once by the visitors
+        parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits), array('filename' => $filename, 'index' => null, 'embedded_templates' => $embeddedTemplates), 1);
+    }
+
+    public function setIndex($index)
+    {
+        $this->setAttribute('index', $index);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $this->compileTemplate($compiler);
+
+        foreach ($this->getAttribute('embedded_templates') as $template) {
+            $compiler->subcompile($template);
+        }
+    }
+
+    protected function compileTemplate(Twig_Compiler $compiler)
+    {
+        if (!$this->getAttribute('index')) {
+            $compiler->write('<?php');
+        }
+
+        $this->compileClassHeader($compiler);
+
+        if (count($this->getNode('blocks')) || count($this->getNode('traits')) || null === $this->getNode('parent') || $this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
+            $this->compileConstructor($compiler);
+        }
+
+        $this->compileGetParent($compiler);
+
+        $this->compileDisplayHeader($compiler);
+
+        $this->compileDisplayBody($compiler);
+
+        $this->compileDisplayFooter($compiler);
+
+        $compiler->subcompile($this->getNode('blocks'));
+
+        $this->compileMacros($compiler);
+
+        $this->compileGetTemplateName($compiler);
+
+        $this->compileIsTraitable($compiler);
+
+        $this->compileDebugInfo($compiler);
+
+        $this->compileClassFooter($compiler);
+    }
+
+    protected function compileGetParent(Twig_Compiler $compiler)
+    {
+        if (null === $this->getNode('parent')) {
+            return;
+        }
+
+        $compiler
+            ->write("protected function doGetParent(array \$context)\n", "{\n")
+            ->indent()
+            ->write("return ")
+        ;
+
+        if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
+            $compiler->subcompile($this->getNode('parent'));
+        } else {
+            $compiler
+                ->raw("\$this->env->resolveTemplate(")
+                ->subcompile($this->getNode('parent'))
+                ->raw(")")
+            ;
+        }
+
+        $compiler
+            ->raw(";\n")
+            ->outdent()
+            ->write("}\n\n")
+        ;
+    }
+
+    protected function compileDisplayBody(Twig_Compiler $compiler)
+    {
+        $compiler->subcompile($this->getNode('body'));
+
+        if (null !== $this->getNode('parent')) {
+            if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
+                $compiler->write("\$this->parent");
+            } else {
+                $compiler->write("\$this->getParent(\$context)");
+            }
+            $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
+        }
+    }
+
+    protected function compileClassHeader(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->write("\n\n")
+            // if the filename contains */, add a blank to avoid a PHP parse error
+            ->write("/* ".str_replace('*/', '* /', $this->getAttribute('filename'))." */\n")
+            ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index')))
+            ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
+            ->write("{\n")
+            ->indent()
+        ;
+    }
+
+    protected function compileConstructor(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->write("public function __construct(Twig_Environment \$env)\n", "{\n")
+            ->indent()
+            ->write("parent::__construct(\$env);\n\n")
+        ;
+
+        // parent
+        if (null === $this->getNode('parent')) {
+            $compiler->write("\$this->parent = false;\n\n");
+        } elseif ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
+            $compiler
+                ->write("\$this->parent = \$this->env->loadTemplate(")
+                ->subcompile($this->getNode('parent'))
+                ->raw(");\n\n")
+            ;
+        }
+
+        $countTraits = count($this->getNode('traits'));
+        if ($countTraits) {
+            // traits
+            foreach ($this->getNode('traits') as $i => $trait) {
+                $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i));
+
+                $compiler
+                    ->addDebugInfo($trait->getNode('template'))
+                    ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
+                    ->indent()
+                    ->write("throw new Twig_Error_Runtime('Template \"'.")
+                    ->subcompile($trait->getNode('template'))
+                    ->raw(".'\" cannot be used as a trait.');\n")
+                    ->outdent()
+                    ->write("}\n")
+                    ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
+                ;
+
+                foreach ($trait->getNode('targets') as $key => $value) {
+                    $compiler
+                        ->write(sprintf("\$_trait_%s_blocks[", $i))
+                        ->subcompile($value)
+                        ->raw(sprintf("] = \$_trait_%s_blocks[", $i))
+                        ->string($key)
+                        ->raw(sprintf("]; unset(\$_trait_%s_blocks[", $i))
+                        ->string($key)
+                        ->raw("]);\n\n")
+                    ;
+                }
+            }
+
+            if ($countTraits > 1) {
+                $compiler
+                    ->write("\$this->traits = array_merge(\n")
+                    ->indent()
+                ;
+
+                for ($i = 0; $i < $countTraits; $i++) {
+                    $compiler
+                        ->write(sprintf("\$_trait_%s_blocks".($i == $countTraits - 1 ? '' : ',')."\n", $i))
+                    ;
+                }
+
+                $compiler
+                    ->outdent()
+                    ->write(");\n\n")
+                ;
+            } else {
+                $compiler
+                    ->write("\$this->traits = \$_trait_0_blocks;\n\n")
+                ;
+            }
+
+            $compiler
+                ->write("\$this->blocks = array_merge(\n")
+                ->indent()
+                ->write("\$this->traits,\n")
+                ->write("array(\n")
+            ;
+        } else {
+            $compiler
+                ->write("\$this->blocks = array(\n")
+            ;
+        }
+
+        // blocks
+        $compiler
+            ->indent()
+        ;
+
+        foreach ($this->getNode('blocks') as $name => $node) {
+            $compiler
+                ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name))
+            ;
+        }
+
+        if ($countTraits) {
+            $compiler
+                ->outdent()
+                ->write(")\n")
+            ;
+        }
+
+        $compiler
+            ->outdent()
+            ->write(");\n")
+            ->outdent()
+            ->write("}\n\n");
+        ;
+    }
+
+    protected function compileDisplayHeader(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n")
+            ->indent()
+        ;
+    }
+
+    protected function compileDisplayFooter(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->outdent()
+            ->write("}\n\n")
+        ;
+    }
+
+    protected function compileClassFooter(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->outdent()
+            ->write("}\n")
+        ;
+    }
+
+    protected function compileMacros(Twig_Compiler $compiler)
+    {
+        $compiler->subcompile($this->getNode('macros'));
+    }
+
+    protected function compileGetTemplateName(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->write("public function getTemplateName()\n", "{\n")
+            ->indent()
+            ->write('return ')
+            ->repr($this->getAttribute('filename'))
+            ->raw(";\n")
+            ->outdent()
+            ->write("}\n\n")
+        ;
+    }
+
+    protected function compileIsTraitable(Twig_Compiler $compiler)
+    {
+        // A template can be used as a trait if:
+        //   * it has no parent
+        //   * it has no macros
+        //   * it has no body
+        //
+        // Put another way, a template can be used as a trait if it
+        // only contains blocks and use statements.
+        $traitable = null === $this->getNode('parent') && 0 === count($this->getNode('macros'));
+        if ($traitable) {
+            if ($this->getNode('body') instanceof Twig_Node_Body) {
+                $nodes = $this->getNode('body')->getNode(0);
+            } else {
+                $nodes = $this->getNode('body');
+            }
+
+            if (!count($nodes)) {
+                $nodes = new Twig_Node(array($nodes));
+            }
+
+            foreach ($nodes as $node) {
+                if (!count($node)) {
+                    continue;
+                }
+
+                if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
+                    continue;
+                }
+
+                if ($node instanceof Twig_Node_BlockReference) {
+                    continue;
+                }
+
+                $traitable = false;
+                break;
+            }
+        }
+
+        if ($traitable) {
+            return;
+        }
+
+        $compiler
+            ->write("public function isTraitable()\n", "{\n")
+            ->indent()
+            ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false'))
+            ->outdent()
+            ->write("}\n\n")
+        ;
+    }
+
+    protected function compileDebugInfo(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->write("public function getDebugInfo()\n", "{\n")
+            ->indent()
+            ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true))))
+            ->outdent()
+            ->write("}\n")
+        ;
+    }
+
+    protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var)
+    {
+        if ($node instanceof Twig_Node_Expression_Constant) {
+            $compiler
+                ->write(sprintf("%s = \$this->env->loadTemplate(", $var))
+                ->subcompile($node)
+                ->raw(");\n")
+            ;
+        } else {
+            $compiler
+                ->write(sprintf("%s = ", $var))
+                ->subcompile($node)
+                ->raw(";\n")
+                ->write(sprintf("if (!%s", $var))
+                ->raw(" instanceof Twig_Template) {\n")
+                ->indent()
+                ->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var))
+                ->outdent()
+                ->write("}\n")
+            ;
+        }
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Print.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Print.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Print.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Print.php Tue May 22 14:42:25 2012
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a node that outputs an expression.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
+{
+    public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
+    {
+        parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->addDebugInfo($this)
+            ->write('echo ')
+            ->subcompile($this->getNode('expr'))
+            ->raw(";\n")
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Sandbox.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Sandbox.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Sandbox.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Sandbox.php Tue May 22 14:42:25 2012
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a sandbox node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Sandbox extends Twig_Node
+{
+    public function __construct(Twig_NodeInterface $body, $lineno, $tag = null)
+    {
+        parent::__construct(array('body' => $body), array(), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->addDebugInfo($this)
+            ->write("\$sandbox = \$this->env->getExtension('sandbox');\n")
+            ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
+            ->indent()
+            ->write("\$sandbox->enableSandbox();\n")
+            ->outdent()
+            ->write("}\n")
+            ->subcompile($this->getNode('body'))
+            ->write("if (!\$alreadySandboxed) {\n")
+            ->indent()
+            ->write("\$sandbox->disableSandbox();\n")
+            ->outdent()
+            ->write("}\n")
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SandboxedModule.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SandboxedModule.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SandboxedModule.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SandboxedModule.php Tue May 22 14:42:25 2012
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a module node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_SandboxedModule extends Twig_Node_Module
+{
+    protected $usedFilters;
+    protected $usedTags;
+    protected $usedFunctions;
+
+    public function __construct(Twig_Node_Module $node, array $usedFilters, array $usedTags, array $usedFunctions)
+    {
+        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());
+
+        $this->setAttribute('index', $node->getAttribute('index'));
+
+        $this->usedFilters = $usedFilters;
+        $this->usedTags = $usedTags;
+        $this->usedFunctions = $usedFunctions;
+    }
+
+    protected function compileDisplayBody(Twig_Compiler $compiler)
+    {
+        $compiler->write("\$this->checkSecurity();\n");
+
+        parent::compileDisplayBody($compiler);
+    }
+
+    protected function compileDisplayFooter(Twig_Compiler $compiler)
+    {
+        parent::compileDisplayFooter($compiler);
+
+        $compiler
+            ->write("protected function checkSecurity() {\n")
+            ->indent()
+            ->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
+            ->indent()
+            ->write(!$this->usedTags ? "array(),\n" : "array('".implode('\', \'', $this->usedTags)."'),\n")
+            ->write(!$this->usedFilters ? "array(),\n" : "array('".implode('\', \'', $this->usedFilters)."'),\n")
+            ->write(!$this->usedFunctions ? "array()\n" : "array('".implode('\', \'', $this->usedFunctions)."')\n")
+            ->outdent()
+            ->write(");\n")
+            ->outdent()
+            ->write("}\n\n")
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SandboxedPrint.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SandboxedPrint.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SandboxedPrint.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SandboxedPrint.php Tue May 22 14:42:25 2012
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Twig_Node_SandboxedPrint adds a check for the __toString() method
+ * when the variable is an object and the sandbox is activated.
+ *
+ * When there is a simple Print statement, like {{ article }},
+ * and if the sandbox is enabled, we need to check that the __toString()
+ * method is allowed if 'article' is an object.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_SandboxedPrint extends Twig_Node_Print
+{
+    public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
+    {
+        parent::__construct($expr, $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->addDebugInfo($this)
+            ->write('echo $this->env->getExtension(\'sandbox\')->ensureToStringAllowed(')
+            ->subcompile($this->getNode('expr'))
+            ->raw(");\n")
+        ;
+    }
+
+    /**
+     * Removes node filters.
+     *
+     * This is mostly needed when another visitor adds filters (like the escaper one).
+     *
+     * @param Twig_Node $node A Node
+     */
+    protected function removeNodeFilter($node)
+    {
+        if ($node instanceof Twig_Node_Expression_Filter) {
+            return $this->removeNodeFilter($node->getNode('node'));
+        }
+
+        return $node;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Set.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Set.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Set.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Set.php Tue May 22 14:42:25 2012
@@ -0,0 +1,102 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a set node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Set extends Twig_Node
+{
+    public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null)
+    {
+        parent::__construct(array('names' => $names, 'values' => $values), array('capture' => $capture, 'safe' => false), $lineno, $tag);
+
+        /*
+         * Optimizes the node when capture is used for a large block of text.
+         *
+         * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig_Markup("foo");
+         */
+        if ($this->getAttribute('capture')) {
+            $this->setAttribute('safe', true);
+
+            $values = $this->getNode('values');
+            if ($values instanceof Twig_Node_Text) {
+                $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getLine()));
+                $this->setAttribute('capture', false);
+            }
+        }
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler->addDebugInfo($this);
+
+        if (count($this->getNode('names')) > 1) {
+            $compiler->write('list(');
+            foreach ($this->getNode('names') as $idx => $node) {
+                if ($idx) {
+                    $compiler->raw(', ');
+                }
+
+                $compiler->subcompile($node);
+            }
+            $compiler->raw(')');
+        } else {
+            if ($this->getAttribute('capture')) {
+                $compiler
+                    ->write("ob_start();\n")
+                    ->subcompile($this->getNode('values'))
+                ;
+            }
+
+            $compiler->subcompile($this->getNode('names'), false);
+
+            if ($this->getAttribute('capture')) {
+                $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())");
+            }
+        }
+
+        if (!$this->getAttribute('capture')) {
+            $compiler->raw(' = ');
+
+            if (count($this->getNode('names')) > 1) {
+                $compiler->write('array(');
+                foreach ($this->getNode('values') as $idx => $value) {
+                    if ($idx) {
+                        $compiler->raw(', ');
+                    }
+
+                    $compiler->subcompile($value);
+                }
+                $compiler->raw(')');
+            } else {
+                if ($this->getAttribute('safe')) {
+                    $compiler
+                        ->raw("('' === \$tmp = ")
+                        ->subcompile($this->getNode('values'))
+                        ->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())")
+                    ;
+                } else {
+                    $compiler->subcompile($this->getNode('values'));
+                }
+            }
+        }
+
+        $compiler->raw(";\n");
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SetTemp.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SetTemp.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SetTemp.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/SetTemp.php Tue May 22 14:42:25 2012
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+class Twig_Node_SetTemp extends Twig_Node
+{
+    public function __construct($name, $lineno)
+    {
+        parent::__construct(array(), array('name' => $name), $lineno);
+    }
+
+    public function compile(Twig_Compiler $compiler)
+    {
+        $name = $this->getAttribute('name');
+        $compiler
+            ->addDebugInfo($this)
+            ->write('if (isset($context[')
+            ->string($name)
+            ->raw('])) { $_')
+            ->raw($name)
+            ->raw('_ = $context[')
+            ->repr($name)
+            ->raw(']; } else { $_')
+            ->raw($name)
+            ->raw("_ = null; }\n")
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Spaceless.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Spaceless.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Spaceless.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Spaceless.php Tue May 22 14:42:25 2012
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a spaceless node.
+ *
+ * It removes spaces between HTML tags.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Spaceless extends Twig_Node
+{
+    public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
+    {
+        parent::__construct(array('body' => $body), array(), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->addDebugInfo($this)
+            ->write("ob_start();\n")
+            ->subcompile($this->getNode('body'))
+            ->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n")
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Text.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Text.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Text.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/Node/Text.php Tue May 22 14:42:25 2012
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a text node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
+{
+    public function __construct($data, $lineno)
+    {
+        parent::__construct(array(), array('data' => $data), $lineno);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->addDebugInfo($this)
+            ->write('echo ')
+            ->string($this->getAttribute('data'))
+            ->raw(";\n")
+        ;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeInterface.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeInterface.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeInterface.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeInterface.php Tue May 22 14:42:25 2012
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a node in the AST.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+interface Twig_NodeInterface extends Countable, IteratorAggregate
+{
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    function compile(Twig_Compiler $compiler);
+
+    function getLine();
+
+    function getNodeTag();
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeOutputInterface.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeOutputInterface.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeOutputInterface.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeOutputInterface.php Tue May 22 14:42:25 2012
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a displayable node in the AST.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+interface Twig_NodeOutputInterface
+{
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeTraverser.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeTraverser.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeTraverser.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeTraverser.php Tue May 22 14:42:25 2012
@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Twig_NodeTraverser is a node traverser.
+ *
+ * It visits all nodes and their children and call the given visitor for each.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_NodeTraverser
+{
+    protected $env;
+    protected $visitors;
+
+    /**
+     * Constructor.
+     *
+     * @param Twig_Environment $env      A Twig_Environment instance
+     * @param array            $visitors An array of Twig_NodeVisitorInterface instances
+     */
+    public function __construct(Twig_Environment $env, array $visitors = array())
+    {
+        $this->env = $env;
+        $this->visitors = array();
+        foreach ($visitors as $visitor) {
+            $this->addVisitor($visitor);
+        }
+    }
+
+    /**
+     * Adds a visitor.
+     *
+     * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance
+     */
+    public function addVisitor(Twig_NodeVisitorInterface $visitor)
+    {
+        if (!isset($this->visitors[$visitor->getPriority()])) {
+            $this->visitors[$visitor->getPriority()] = array();
+        }
+
+        $this->visitors[$visitor->getPriority()][] = $visitor;
+    }
+
+    /**
+     * Traverses a node and calls the registered visitors.
+     *
+     * @param Twig_NodeInterface $node A Twig_NodeInterface instance
+     */
+    public function traverse(Twig_NodeInterface $node)
+    {
+        ksort($this->visitors);
+        foreach ($this->visitors as $visitors) {
+            foreach ($visitors as $visitor) {
+                $node = $this->traverseForVisitor($visitor, $node);
+            }
+        }
+
+        return $node;
+    }
+
+    protected function traverseForVisitor(Twig_NodeVisitorInterface $visitor, Twig_NodeInterface $node = null)
+    {
+        if (null === $node) {
+            return null;
+        }
+
+        $node = $visitor->enterNode($node, $this->env);
+
+        foreach ($node as $k => $n) {
+            if (false !== $n = $this->traverseForVisitor($visitor, $n)) {
+                $node->setNode($k, $n);
+            } else {
+                $node->removeNode($k);
+            }
+        }
+
+        return $visitor->leaveNode($node, $this->env);
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Escaper.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Escaper.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Escaper.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Escaper.php Tue May 22 14:42:25 2012
@@ -0,0 +1,164 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Twig_NodeVisitor_Escaper implements output escaping.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
+{
+    protected $statusStack = array();
+    protected $blocks = array();
+    protected $safeAnalysis;
+    protected $traverser;
+    protected $defaultStrategy = false;
+
+    public function __construct()
+    {
+        $this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis();
+    }
+
+    /**
+     * Called before child nodes are visited.
+     *
+     * @param Twig_NodeInterface $node The node to visit
+     * @param Twig_Environment   $env  The Twig environment instance
+     *
+     * @return Twig_NodeInterface The modified node
+     */
+    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
+    {
+        if ($node instanceof Twig_Node_Module) {
+            if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
+                $this->defaultStrategy = $defaultStrategy;
+            }
+        } elseif ($node instanceof Twig_Node_AutoEscape) {
+            $this->statusStack[] = $node->getAttribute('value');
+        } elseif ($node instanceof Twig_Node_Block) {
+            $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
+        }
+
+        return $node;
+    }
+
+    /**
+     * Called after child nodes are visited.
+     *
+     * @param Twig_NodeInterface $node The node to visit
+     * @param Twig_Environment   $env  The Twig environment instance
+     *
+     * @return Twig_NodeInterface The modified node
+     */
+    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
+    {
+        if ($node instanceof Twig_Node_Module) {
+            $this->defaultStrategy = false;
+        } elseif ($node instanceof Twig_Node_Expression_Filter) {
+            return $this->preEscapeFilterNode($node, $env);
+        } elseif ($node instanceof Twig_Node_Print) {
+            return $this->escapePrintNode($node, $env, $this->needEscaping($env));
+        }
+
+        if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) {
+            array_pop($this->statusStack);
+        } elseif ($node instanceof Twig_Node_BlockReference) {
+            $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env);
+        }
+
+        return $node;
+    }
+
+    protected function escapePrintNode(Twig_Node_Print $node, Twig_Environment $env, $type)
+    {
+        if (false === $type) {
+            return $node;
+        }
+
+        $expression = $node->getNode('expr');
+
+        if ($this->isSafeFor($type, $expression, $env)) {
+            return $node;
+        }
+
+        $class = get_class($node);
+
+        return new $class(
+            $this->getEscaperFilter($type, $expression),
+            $node->getLine()
+        );
+    }
+
+    protected function preEscapeFilterNode(Twig_Node_Expression_Filter $filter, Twig_Environment $env)
+    {
+        $name = $filter->getNode('filter')->getAttribute('value');
+
+        if (false !== $f = $env->getFilter($name)) {
+            $type = $f->getPreEscape();
+            if (null === $type) {
+                return $filter;
+            }
+
+            $node = $filter->getNode('node');
+            if ($this->isSafeFor($type, $node, $env)) {
+                return $filter;
+            }
+
+            $filter->setNode('node', $this->getEscaperFilter($type, $node));
+
+            return $filter;
+        }
+
+        return $filter;
+    }
+
+    protected function isSafeFor($type, Twig_NodeInterface $expression, $env)
+    {
+        $safe = $this->safeAnalysis->getSafe($expression);
+
+        if (null === $safe) {
+            if (null === $this->traverser) {
+                $this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis));
+            }
+            $this->traverser->traverse($expression);
+            $safe = $this->safeAnalysis->getSafe($expression);
+        }
+
+        return in_array($type, $safe) || in_array('all', $safe);
+    }
+
+    protected function needEscaping(Twig_Environment $env)
+    {
+        if (count($this->statusStack)) {
+            return $this->statusStack[count($this->statusStack) - 1];
+        }
+
+        return $this->defaultStrategy ? $this->defaultStrategy : false;
+    }
+
+    protected function getEscaperFilter($type, Twig_NodeInterface $node)
+    {
+        $line = $node->getLine();
+        $name = new Twig_Node_Expression_Constant('escape', $line);
+        $args = new Twig_Node(array(new Twig_Node_Expression_Constant((string) $type, $line), new Twig_Node_Expression_Constant(null, $line), new Twig_Node_Expression_Constant(true, $line)));
+
+        return new Twig_Node_Expression_Filter($node, $name, $args, $line);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPriority()
+    {
+        return 0;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Optimizer.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Optimizer.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Optimizer.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Optimizer.php Tue May 22 14:42:25 2012
@@ -0,0 +1,247 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Twig_NodeVisitor_Optimizer tries to optimizes the AST.
+ *
+ * This visitor is always the last registered one.
+ *
+ * You can configure which optimizations you want to activate via the
+ * optimizer mode.
+ *
+ * @package twig
+ * @author  Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
+{
+    const OPTIMIZE_ALL         = -1;
+    const OPTIMIZE_NONE        = 0;
+    const OPTIMIZE_FOR         = 2;
+    const OPTIMIZE_RAW_FILTER  = 4;
+    const OPTIMIZE_VAR_ACCESS  = 8;
+
+    protected $loops = array();
+    protected $optimizers;
+    protected $prependedNodes = array();
+    protected $inABody = false;
+
+    /**
+     * Constructor.
+     *
+     * @param integer $optimizers The optimizer mode
+     */
+    public function __construct($optimizers = -1)
+    {
+        if (!is_int($optimizers) || $optimizers > 2) {
+            throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers));
+        }
+
+        $this->optimizers = $optimizers;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
+    {
+        if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
+            $this->enterOptimizeFor($node, $env);
+        }
+
+        if (!version_compare(phpversion(), '5.4.0RC1', '>=') && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
+            if ($this->inABody) {
+                if (!$node instanceof Twig_Node_Expression) {
+                    if (get_class($node) !== 'Twig_Node') {
+                        array_unshift($this->prependedNodes, array());
+                    }
+                } else {
+                    $node = $this->optimizeVariables($node, $env);
+                }
+            } elseif ($node instanceof Twig_Node_Body) {
+                $this->inABody = true;
+            }
+        }
+
+        return $node;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
+    {
+        $expression = $node instanceof Twig_Node_Expression;
+
+        if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
+            $this->leaveOptimizeFor($node, $env);
+        }
+
+        if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) {
+            $node = $this->optimizeRawFilter($node, $env);
+        }
+
+        $node = $this->optimizePrintNode($node, $env);
+
+        if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
+            if ($node instanceof Twig_Node_Body) {
+                $this->inABody = false;
+            } elseif ($this->inABody) {
+                if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) {
+                    $nodes = array();
+                    foreach (array_unique($prependedNodes) as $name) {
+                        $nodes[] = new Twig_Node_SetTemp($name, $node->getLine());
+                    }
+
+                    $nodes[] = $node;
+                    $node = new Twig_Node($nodes);
+                }
+            }
+        }
+
+        return $node;
+    }
+
+    protected function optimizeVariables($node, $env)
+    {
+        if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) {
+            $this->prependedNodes[0][] = $node->getAttribute('name');
+
+            return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->getLine());
+        }
+
+        return $node;
+    }
+
+    /**
+     * Optimizes print nodes.
+     *
+     * It replaces:
+     *
+     *   * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()"
+     *
+     * @param Twig_NodeInterface $node A Node
+     * @param Twig_Environment   $env  The current Twig environment
+     */
+    protected function optimizePrintNode($node, $env)
+    {
+        if (!$node instanceof Twig_Node_Print) {
+            return $node;
+        }
+
+        if (
+            $node->getNode('expr') instanceof Twig_Node_Expression_BlockReference ||
+            $node->getNode('expr') instanceof Twig_Node_Expression_Parent
+        ) {
+            $node->getNode('expr')->setAttribute('output', true);
+
+            return $node->getNode('expr');
+        }
+
+        return $node;
+    }
+
+    /**
+     * Removes "raw" filters.
+     *
+     * @param Twig_NodeInterface $node A Node
+     * @param Twig_Environment   $env  The current Twig environment
+     */
+    protected function optimizeRawFilter($node, $env)
+    {
+        if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) {
+            return $node->getNode('node');
+        }
+
+        return $node;
+    }
+
+    /**
+     * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
+     *
+     * @param Twig_NodeInterface $node A Node
+     * @param Twig_Environment   $env  The current Twig environment
+     */
+    protected function enterOptimizeFor($node, $env)
+    {
+        if ($node instanceof Twig_Node_For) {
+            // disable the loop variable by default
+            $node->setAttribute('with_loop', false);
+            array_unshift($this->loops, $node);
+        } elseif (!$this->loops) {
+            // we are outside a loop
+            return;
+        }
+
+        // when do we need to add the loop variable back?
+
+        // the loop variable is referenced for the current loop
+        elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) {
+            $this->addLoopToCurrent();
+        }
+
+        // block reference
+        elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) {
+            $this->addLoopToCurrent();
+        }
+
+        // include without the only attribute
+        elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) {
+            $this->addLoopToAll();
+        }
+
+        // the loop variable is referenced via an attribute
+        elseif ($node instanceof Twig_Node_Expression_GetAttr
+            && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant
+                || 'parent' === $node->getNode('attribute')->getAttribute('value')
+               )
+            && (true === $this->loops[0]->getAttribute('with_loop')
+                || ($node->getNode('node') instanceof Twig_Node_Expression_Name
+                    && 'loop' === $node->getNode('node')->getAttribute('name')
+                   )
+               )
+        ) {
+            $this->addLoopToAll();
+        }
+    }
+
+    /**
+     * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
+     *
+     * @param Twig_NodeInterface $node A Node
+     * @param Twig_Environment   $env  The current Twig environment
+     */
+    protected function leaveOptimizeFor($node, $env)
+    {
+        if ($node instanceof Twig_Node_For) {
+            array_shift($this->loops);
+        }
+    }
+
+    protected function addLoopToCurrent()
+    {
+        $this->loops[0]->setAttribute('with_loop', true);
+    }
+
+    protected function addLoopToAll()
+    {
+        foreach ($this->loops as $loop) {
+            $loop->setAttribute('with_loop', true);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPriority()
+    {
+        return 255;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/SafeAnalysis.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/SafeAnalysis.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/SafeAnalysis.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/SafeAnalysis.php Tue May 22 14:42:25 2012
@@ -0,0 +1,119 @@
+<?php
+
+class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
+{
+    protected $data = array();
+
+    public function getSafe(Twig_NodeInterface $node)
+    {
+        $hash = spl_object_hash($node);
+        if (isset($this->data[$hash])) {
+            foreach($this->data[$hash] as $bucket) {
+                if ($bucket['key'] === $node) {
+                    return $bucket['value'];
+                }
+            }
+        }
+
+        return null;
+    }
+
+    protected function setSafe(Twig_NodeInterface $node, array $safe)
+    {
+        $hash = spl_object_hash($node);
+        if (isset($this->data[$hash])) {
+            foreach($this->data[$hash] as &$bucket) {
+                if ($bucket['key'] === $node) {
+                    $bucket['value'] = $safe;
+
+                    return;
+                }
+            }
+        }
+        $this->data[$hash][] = array(
+            'key' => $node,
+            'value' => $safe,
+        );
+    }
+
+    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
+    {
+        return $node;
+    }
+
+    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
+    {
+        if ($node instanceof Twig_Node_Expression_Constant) {
+            // constants are marked safe for all
+            $this->setSafe($node, array('all'));
+        } elseif ($node instanceof Twig_Node_Expression_BlockReference) {
+            // blocks are safe by definition
+            $this->setSafe($node, array('all'));
+        } elseif ($node instanceof Twig_Node_Expression_Parent) {
+            // parent block is safe by definition
+            $this->setSafe($node, array('all'));
+        } elseif ($node instanceof Twig_Node_Expression_Conditional) {
+            // intersect safeness of both operands
+            $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3')));
+            $this->setSafe($node, $safe);
+        } elseif ($node instanceof Twig_Node_Expression_Filter) {
+            // filter expression is safe when the filter is safe
+            $name = $node->getNode('filter')->getAttribute('value');
+            $args = $node->getNode('arguments');
+            if (false !== $filter = $env->getFilter($name)) {
+                $safe = $filter->getSafe($args);
+                if (null === $safe) {
+                    $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety());
+                }
+                $this->setSafe($node, $safe);
+            } else {
+                $this->setSafe($node, array());
+            }
+        } elseif ($node instanceof Twig_Node_Expression_Function) {
+            // function expression is safe when the function is safe
+            $name = $node->getAttribute('name');
+            $args = $node->getNode('arguments');
+            $function = $env->getFunction($name);
+            if (false !== $function) {
+                $this->setSafe($node, $function->getSafe($args));
+            } else {
+                $this->setSafe($node, array());
+            }
+        } elseif ($node instanceof Twig_Node_Expression_MethodCall) {
+            if ($node->getAttribute('safe')) {
+                $this->setSafe($node, array('all'));
+            } else {
+                $this->setSafe($node, array());
+            }
+        } else {
+            $this->setSafe($node, array());
+        }
+
+        return $node;
+    }
+
+    protected function intersectSafe(array $a = null, array $b = null)
+    {
+        if (null === $a || null === $b) {
+            return array();
+        }
+
+        if (in_array('all', $a)) {
+            return $b;
+        }
+
+        if (in_array('all', $b)) {
+            return $a;
+        }
+
+        return array_intersect($a, $b);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPriority()
+    {
+        return 0;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Sandbox.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Sandbox.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Sandbox.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitor/Sandbox.php Tue May 22 14:42:25 2012
@@ -0,0 +1,106 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Twig_NodeVisitor_Sandbox implements sandboxing.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
+{
+    protected $inAModule = false;
+    protected $tags;
+    protected $filters;
+    protected $functions;
+
+    /**
+     * Called before child nodes are visited.
+     *
+     * @param Twig_NodeInterface $node The node to visit
+     * @param Twig_Environment   $env  The Twig environment instance
+     *
+     * @return Twig_NodeInterface The modified node
+     */
+    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
+    {
+        // in a sandbox tag, only include tags are allowed
+        if ($node instanceof Twig_Node_Sandbox && !$node->getNode('body') instanceof Twig_Node_Include) {
+            foreach ($node->getNode('body') as $n) {
+                if ($n instanceof Twig_Node_Text && ctype_space($n->getAttribute('data'))) {
+                    continue;
+                }
+
+                if (!$n instanceof Twig_Node_Include) {
+                    throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section', $n->getLine());
+                }
+            }
+        }
+
+        if ($node instanceof Twig_Node_Module) {
+            $this->inAModule = true;
+            $this->tags = array();
+            $this->filters = array();
+            $this->functions = array();
+
+            return $node;
+        } elseif ($this->inAModule) {
+            // look for tags
+            if ($node->getNodeTag()) {
+                $this->tags[] = $node->getNodeTag();
+            }
+
+            // look for filters
+            if ($node instanceof Twig_Node_Expression_Filter) {
+                $this->filters[] = $node->getNode('filter')->getAttribute('value');
+            }
+
+            // look for functions
+            if ($node instanceof Twig_Node_Expression_Function) {
+                $this->functions[] = $node->getAttribute('name');
+            }
+
+            // wrap print to check __toString() calls
+            if ($node instanceof Twig_Node_Print) {
+                return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->getLine(), $node->getNodeTag());
+            }
+        }
+
+        return $node;
+    }
+
+    /**
+     * Called after child nodes are visited.
+     *
+     * @param Twig_NodeInterface $node The node to visit
+     * @param Twig_Environment   $env  The Twig environment instance
+     *
+     * @return Twig_NodeInterface The modified node
+     */
+    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
+    {
+        if ($node instanceof Twig_Node_Module) {
+            $this->inAModule = false;
+
+            return new Twig_Node_SandboxedModule($node, array_unique($this->filters), array_unique($this->tags), array_unique($this->functions));
+        }
+
+        return $node;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPriority()
+    {
+        return 0;
+    }
+}

Added: logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitorInterface.php
URL: http://svn.apache.org/viewvc/logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitorInterface.php?rev=1341499&view=auto
==============================================================================
--- logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitorInterface.php (added)
+++ logging/site/branches/experimental-twig-textile/libs/Twig/lib/Twig/NodeVisitorInterface.php Tue May 22 14:42:25 2012
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Twig_NodeVisitorInterface is the interface the all node visitor classes must implement.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+interface Twig_NodeVisitorInterface
+{
+    /**
+     * Called before child nodes are visited.
+     *
+     * @param Twig_NodeInterface $node The node to visit
+     * @param Twig_Environment   $env  The Twig environment instance
+     *
+     * @return Twig_NodeInterface The modified node
+     */
+    function enterNode(Twig_NodeInterface $node, Twig_Environment $env);
+
+    /**
+     * Called after child nodes are visited.
+     *
+     * @param Twig_NodeInterface $node The node to visit
+     * @param Twig_Environment   $env  The Twig environment instance
+     *
+     * @return Twig_NodeInterface The modified node
+     */
+    function leaveNode(Twig_NodeInterface $node, Twig_Environment $env);
+
+    /**
+     * Returns the priority for this visitor.
+     *
+     * Priority should be between -10 and 10 (0 is the default).
+     *
+     * @return integer The priority level
+     */
+    function getPriority();
+}