Index: branches/2.8.x/CHANGELOG
===================================================================
--- branches/2.8.x/CHANGELOG	(revision 1851)
+++ branches/2.8.x/CHANGELOG	(revision 1852)
@@ -12,7 +12,10 @@
 ===============================================================================
 
 
-
+07 Jan-2013 Build 1852 Werner v.d.Decken(DarkViper)
+! updated Twig template engine to stable version 1.11.1 step 2
+07 Jan-2013 Build 1851 Werner v.d.Decken(DarkViper)
+! updated Twig template engine to stable version 1.11.1
 06 Jan-2013 Build 1850 Dietmar Woellbrink (Luisehahne)
 ! add default_timezone in admin account by new installation 
 06 Jan-2013 Build 1849 Dietmar Woellbrink (Luisehahne)
Index: branches/2.8.x/wb/include/Twig/Test/IntegrationTestCase.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Test/IntegrationTestCase.php	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/Test/IntegrationTestCase.php	(revision 1852)
@@ -0,0 +1,155 @@
+<?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.
+ */
+
+/**
+ * Integration test helper
+ *
+ * @package twig
+ * @author  Fabien Potencier <fabien@symfony.com>
+ * @author  Karma Dordrak <drak@zikula.org>
+ */
+abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
+{
+    abstract protected function getExtensions();
+    abstract protected function getFixturesDir();
+
+    /**
+     * @dataProvider getTests
+     */
+    public function testIntegration($file, $message, $condition, $templates, $exception, $outputs)
+    {
+        $this->doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs);
+    }
+
+    public function getTests()
+    {
+        $fixturesDir = realpath($this->getFixturesDir());
+        $tests = array();
+
+        foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
+            if (!preg_match('/\.test$/', $file)) {
+                continue;
+            }
+
+            $test = file_get_contents($file->getRealpath());
+
+            if (preg_match('/
+                    --TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)\s*(?:--DATA--\s*(.*))?\s*--EXCEPTION--\s*(.*)/sx', $test, $match)) {
+                $message = $match[1];
+                $condition = $match[2];
+                $templates = $this->parseTemplates($match[3]);
+                $exception = $match[5];
+                $outputs = array(array(null, $match[4], null, ''));
+            } elseif (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) {
+                $message = $match[1];
+                $condition = $match[2];
+                $templates = $this->parseTemplates($match[3]);
+                $exception = false;
+                preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, PREG_SET_ORDER);
+            } else {
+                throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file)));
+            }
+
+            $tests[] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs);
+        }
+
+        return $tests;
+    }
+
+    protected function doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs)
+    {
+        if ($condition) {
+            eval('$ret = '.$condition.';');
+            if (!$ret) {
+                $this->markTestSkipped($condition);
+            }
+        }
+
+        $loader = new Twig_Loader_Array($templates);
+
+        foreach ($outputs as $match) {
+            $config = array_merge(array(
+                'cache' => false,
+                'strict_variables' => true,
+            ), $match[2] ? eval($match[2].';') : array());
+            $twig = new Twig_Environment($loader, $config);
+            $twig->addGlobal('global', 'global');
+            foreach ($this->getExtensions() as $extension) {
+                $twig->addExtension($extension);
+            }
+
+            try {
+                $template = $twig->loadTemplate('index.twig');
+            } catch (Exception $e) {
+                if (false !== $exception) {
+                    $this->assertEquals(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage())));
+
+                    return;
+                }
+
+                if ($e instanceof Twig_Error_Syntax) {
+                    $e->setTemplateFile($file);
+
+                    throw $e;
+                }
+
+                throw new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e);
+            }
+
+            try {
+                $output = trim($template->render(eval($match[1].';')), "\n ");
+            } catch (Exception $e) {
+                if (false !== $exception) {
+                    $this->assertEquals(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage())));
+
+                    return;
+                }
+
+                if ($e instanceof Twig_Error_Syntax) {
+                    $e->setTemplateFile($file);
+                } else {
+                    $e = new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e);
+                }
+
+                $output = trim(sprintf('%s: %s', get_class($e), $e->getMessage()));
+            }
+
+            if (false !== $exception) {
+                list($class, ) = explode(':', $exception);
+                $this->assertThat(NULL, new PHPUnit_Framework_Constraint_Exception($class));
+            }
+
+            $expected = trim($match[3], "\n ");
+
+            if ($expected != $output) {
+                echo 'Compiled template that failed:';
+
+                foreach (array_keys($templates) as $name) {
+                    echo "Template: $name\n";
+                    $source = $loader->getSource($name);
+                    echo $twig->compile($twig->parse($twig->tokenize($source, $name)));
+                }
+            }
+            $this->assertEquals($expected, $output, $message.' (in '.$file.')');
+        }
+    }
+
+    protected static function parseTemplates($test)
+    {
+        $templates = array();
+        preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $test, $matches, PREG_SET_ORDER);
+        foreach ($matches as $match) {
+            $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2];
+        }
+
+        return $templates;
+    }
+}

Property changes on: branches/2.8.x/wb/include/Twig/Test/IntegrationTestCase.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision HeadURL
\ No newline at end of property
Index: branches/2.8.x/wb/include/Twig/Test/Method.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Test/Method.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Test/Method.php	(revision 1852)
@@ -17,7 +17,8 @@
  */
 class Twig_Test_Method implements Twig_TestInterface
 {
-    protected $extension, $method;
+    protected $extension;
+    protected $method;
 
     public function __construct(Twig_ExtensionInterface $extension, $method)
     {
Index: branches/2.8.x/wb/include/Twig/Test/NodeTestCase.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Test/NodeTestCase.php	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/Test/NodeTestCase.php	(revision 1852)
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+abstract class Twig_Test_NodeTestCase extends PHPUnit_Framework_TestCase
+{
+    abstract public function getTests();
+
+    /**
+     * @dataProvider getTests
+     */
+    public function testCompile($node, $source, $environment = null)
+    {
+        $this->assertNodeCompilation($source, $node, $environment);
+    }
+
+    public function assertNodeCompilation($source, Twig_Node $node, Twig_Environment $environment = null)
+    {
+        $compiler = $this->getCompiler($environment);
+        $compiler->compile($node);
+
+        $this->assertEquals($source, trim($compiler->getSource()));
+    }
+
+    protected function getCompiler(Twig_Environment $environment = null)
+    {
+        return new Twig_Compiler(null === $environment ? $this->getEnvironment() : $environment);
+    }
+
+    protected function getEnvironment()
+    {
+        return new Twig_Environment();
+    }
+
+    protected function getVariableGetter($name)
+    {
+        if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
+            return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name);
+        }
+
+        return sprintf('$this->getContext($context, "%s")', $name);
+    }
+
+    protected function getAttributeGetter()
+    {
+        if (function_exists('twig_template_get_attributes')) {
+            return 'twig_template_get_attributes($this, ';
+        }
+
+        return '$this->getAttribute(';
+    }
+}

Property changes on: branches/2.8.x/wb/include/Twig/Test/NodeTestCase.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision HeadURL
\ No newline at end of property
Index: branches/2.8.x/wb/include/Twig/Parser.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Parser.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Parser.php	(revision 1852)
@@ -29,9 +29,9 @@
     protected $macros;
     protected $env;
     protected $reservedMacroNames;
-    protected $importedFunctions;
-    protected $tmpVarCount;
+    protected $importedSymbols;
     protected $traits;
+    protected $embeddedTemplates = array();
 
     /**
      * Constructor.
@@ -50,17 +50,22 @@
 
     public function getVarName()
     {
-        return sprintf('__internal_%s_%d', substr($this->env->getTemplateClass($this->stream->getFilename()), strlen($this->env->getTemplateClassPrefix())), ++$this->tmpVarCount);
+        return sprintf('__internal_%s', hash('sha1', uniqid(mt_rand(), true), false));
     }
 
+    public function getFilename()
+    {
+        return $this->stream->getFilename();
+    }
+
     /**
      * Converts a token stream to a node tree.
      *
-     * @param  Twig_TokenStream $stream A token stream instance
+     * @param Twig_TokenStream $stream A token stream instance
      *
      * @return Twig_Node_Module A node tree
      */
-    public function parse(Twig_TokenStream $stream)
+    public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false)
     {
         // push all variables into the stack to keep the current state of the parser
         $vars = get_object_vars($this);
@@ -67,8 +72,6 @@
         unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser']);
         $this->stack[] = $vars;
 
-        $this->tmpVarCount = 0;
-
         // tag handlers
         if (null === $this->handlers) {
             $this->handlers = $this->env->getTokenParsers();
@@ -90,10 +93,11 @@
         $this->macros = array();
         $this->traits = array();
         $this->blockStack = array();
-        $this->importedFunctions = array(array());
+        $this->importedSymbols = array(array());
+        $this->embeddedTemplates = array();
 
         try {
-            $body = $this->subparse(null);
+            $body = $this->subparse($test, $dropNeedle);
 
             if (null !== $this->parent) {
                 if (null === $body = $this->filterBodyNodes($body)) {
@@ -101,14 +105,18 @@
                 }
             }
         } catch (Twig_Error_Syntax $e) {
-            if (null === $e->getTemplateFile()) {
-                $e->setTemplateFile($this->stream->getFilename());
+            if (!$e->getTemplateFile()) {
+                $e->setTemplateFile($this->getFilename());
             }
 
+            if (!$e->getTemplateLine()) {
+                $e->setTemplateLine($this->stream->getCurrent()->getLine());
+            }
+
             throw $e;
         }
 
-        $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->stream->getFilename());
+        $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $this->getFilename());
 
         $traverser = new Twig_NodeTraverser($this->env, $this->visitors);
 
@@ -145,7 +153,7 @@
                     $token = $this->getCurrentToken();
 
                     if ($token->getType() !== Twig_Token::NAME_TYPE) {
-                        throw new Twig_Error_Syntax('A block must start with a tag name', $token->getLine(), $this->stream->getFilename());
+                        throw new Twig_Error_Syntax('A block must start with a tag name', $token->getLine(), $this->getFilename());
                     }
 
                     if (null !== $test && call_user_func($test, $token)) {
@@ -163,7 +171,12 @@
                     $subparser = $this->handlers->getTokenParser($token->getValue());
                     if (null === $subparser) {
                         if (null !== $test) {
-                            throw new Twig_Error_Syntax(sprintf('Unexpected tag name "%s" (expecting closing tag for the "%s" tag defined near line %s)', $token->getValue(), $test[0]->getTag(), $lineno), $token->getLine(), $this->stream->getFilename());
+                            $error = sprintf('Unexpected tag name "%s"', $token->getValue());
+                            if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) {
+                                $error .= sprintf(' (expecting closing tag for the "%s" tag defined near line %s)', $test[0]->getTag(), $lineno);
+                            }
+
+                            throw new Twig_Error_Syntax($error, $token->getLine(), $this->getFilename());
                         }
 
                         $message = sprintf('Unknown tag name "%s"', $token->getValue());
@@ -171,7 +184,7 @@
                             $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
                         }
 
-                        throw new Twig_Error_Syntax($message, $token->getLine(), $this->stream->getFilename());
+                        throw new Twig_Error_Syntax($message, $token->getLine(), $this->getFilename());
                     }
 
                     $this->stream->next();
@@ -183,7 +196,7 @@
                     break;
 
                 default:
-                    throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', -1, $this->stream->getFilename());
+                    throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->getFilename());
             }
         }
 
@@ -255,7 +268,7 @@
         }
 
         if (in_array($name, $this->reservedMacroNames)) {
-            throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword', $name), $node->getLine());
+            throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword', $name), $node->getLine(), $this->getFilename());
         }
 
         $this->macros[$name] = $node;
@@ -271,16 +284,23 @@
         return count($this->traits) > 0;
     }
 
-    public function addImportedFunction($alias, $name, Twig_Node_Expression $node)
+    public function embedTemplate(Twig_Node_Module $template)
     {
-        $this->importedFunctions[0][$alias] = array('name' => $name, 'node' => $node);
+        $template->setIndex(mt_rand());
+
+        $this->embeddedTemplates[] = $template;
     }
 
-    public function getImportedFunction($alias)
+    public function addImportedSymbol($type, $alias, $name = null, Twig_Node_Expression $node = null)
     {
-        foreach ($this->importedFunctions as $functions) {
-            if (isset($functions[$alias])) {
-                return $functions[$alias];
+        $this->importedSymbols[0][$type][$alias] = array('name' => $name, 'node' => $node);
+    }
+
+    public function getImportedSymbol($type, $alias)
+    {
+        foreach ($this->importedSymbols as $functions) {
+            if (isset($functions[$type][$alias])) {
+                return $functions[$type][$alias];
             }
         }
     }
@@ -287,17 +307,17 @@
 
     public function isMainScope()
     {
-        return 1 === count($this->importedFunctions);
+        return 1 === count($this->importedSymbols);
     }
 
     public function pushLocalScope()
     {
-        array_unshift($this->importedFunctions, array());
+        array_unshift($this->importedSymbols, array());
     }
 
     public function popLocalScope()
     {
-        array_shift($this->importedFunctions);
+        array_shift($this->importedSymbols);
     }
 
     /**
@@ -349,10 +369,10 @@
             (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface)
         ) {
             if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) {
-                throw new Twig_Error_Syntax('A template that extends another one cannot have a body but a byte order mark (BOM) has been detected; it must be removed.', $node->getLine(), $this->stream->getFilename());
+                throw new Twig_Error_Syntax('A template that extends another one cannot have a body but a byte order mark (BOM) has been detected; it must be removed.', $node->getLine(), $this->getFilename());
             }
 
-            throw new Twig_Error_Syntax('A template that extends another one cannot have a body.', $node->getLine(), $this->stream->getFilename());
+            throw new Twig_Error_Syntax('A template that extends another one cannot have a body.', $node->getLine(), $this->getFilename());
         }
 
         // bypass "set" nodes as they "capture" the output
Index: branches/2.8.x/wb/include/Twig/ExtensionInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/ExtensionInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/ExtensionInterface.php	(revision 1852)
@@ -24,7 +24,7 @@
      *
      * @param Twig_Environment $environment The current Twig_Environment instance
      */
-    function initRuntime(Twig_Environment $environment);
+    public function initRuntime(Twig_Environment $environment);
 
     /**
      * Returns the token parser instances to add to the existing list.
@@ -31,7 +31,7 @@
      *
      * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
      */
-    function getTokenParsers();
+    public function getTokenParsers();
 
     /**
      * Returns the node visitor instances to add to the existing list.
@@ -38,7 +38,7 @@
      *
      * @return array An array of Twig_NodeVisitorInterface instances
      */
-    function getNodeVisitors();
+    public function getNodeVisitors();
 
     /**
      * Returns a list of filters to add to the existing list.
@@ -45,7 +45,7 @@
      *
      * @return array An array of filters
      */
-    function getFilters();
+    public function getFilters();
 
     /**
      * Returns a list of tests to add to the existing list.
@@ -52,7 +52,7 @@
      *
      * @return array An array of tests
      */
-    function getTests();
+    public function getTests();
 
     /**
      * Returns a list of functions to add to the existing list.
@@ -59,7 +59,7 @@
      *
      * @return array An array of functions
      */
-    function getFunctions();
+    public function getFunctions();
 
     /**
      * Returns a list of operators to add to the existing list.
@@ -66,7 +66,7 @@
      *
      * @return array An array of operators
      */
-    function getOperators();
+    public function getOperators();
 
     /**
      * Returns a list of global variables to add to the existing list.
@@ -73,7 +73,7 @@
      *
      * @return array An array of global variables
      */
-    function getGlobals();
+    public function getGlobals();
 
     /**
      * Returns the name of the extension.
@@ -80,5 +80,5 @@
      *
      * @return string The extension name
      */
-    function getName();
+    public function getName();
 }
Index: branches/2.8.x/wb/include/Twig/Node/Macro.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Macro.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Macro.php	(revision 1852)
@@ -31,7 +31,7 @@
     {
         $arguments = array();
         foreach ($this->getNode('arguments') as $argument) {
-            $arguments[] = '$'.$argument->getAttribute('name').' = null';
+            $arguments[] = '$_'.$argument->getAttribute('name').' = null';
         }
 
         $compiler
@@ -52,7 +52,7 @@
                 $compiler
                     ->write('')
                     ->string($argument->getAttribute('name'))
-                    ->raw(' => $'.$argument->getAttribute('name'))
+                    ->raw(' => $_'.$argument->getAttribute('name'))
                     ->raw(",\n")
                 ;
             }
@@ -70,13 +70,13 @@
             ->indent()
             ->subcompile($this->getNode('body'))
             ->outdent()
-            ->write("} catch(Exception \$e) {\n")
+            ->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")
+            ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n")
             ->outdent()
             ->write("}\n\n")
         ;
Index: branches/2.8.x/wb/include/Twig/Node/Expression/Test/Defined.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Expression/Test/Defined.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Expression/Test/Defined.php	(revision 1852)
@@ -35,7 +35,7 @@
 
             $this->changeIgnoreStrictCheck($node);
         } else {
-            throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine());
+            throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine(), $compiler->getFilename());
         }
     }
 
Index: branches/2.8.x/wb/include/Twig/Node/Expression/TempName.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Expression/TempName.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Expression/TempName.php	(revision 1852)
@@ -17,6 +17,10 @@
 
     public function compile(Twig_Compiler $compiler)
     {
-        $compiler->raw('$_')->raw($this->getAttribute('name'))->raw('_');
+        $compiler
+            ->raw('$_')
+            ->raw($this->getAttribute('name'))
+            ->raw('_')
+        ;
     }
 }
Index: branches/2.8.x/wb/include/Twig/Node/Expression/GetAttr.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Expression/GetAttr.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Expression/GetAttr.php	(revision 1852)
@@ -13,12 +13,12 @@
 {
     public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno)
     {
-        parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false), $lineno);
+        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);
     }
 
     public function compile(Twig_Compiler $compiler)
     {
-        if (function_exists('twig_template_get_attributes')) {
+        if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) {
             $compiler->raw('twig_template_get_attributes($this, ');
         } else {
             $compiler->raw('$this->getAttribute(');
Index: branches/2.8.x/wb/include/Twig/Node/Expression/MethodCall.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Expression/MethodCall.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Expression/MethodCall.php	(revision 1852)
@@ -13,6 +13,10 @@
     public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno)
     {
         parent::__construct(array('node' => $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno);
+
+        if ($node instanceof Twig_Node_Expression_Name) {
+            $node->setAttribute('always_defined', true);
+        }
     }
 
     public function compile(Twig_Compiler $compiler)
Index: branches/2.8.x/wb/include/Twig/Node/Expression/Test.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Expression/Test.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Expression/Test.php	(revision 1852)
@@ -25,7 +25,7 @@
                 $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
             }
 
-            throw new Twig_Error_Syntax($message, $this->getLine());
+            throw new Twig_Error_Syntax($message, $this->getLine(), $compiler->getFilename());
         }
 
         $name = $this->getAttribute('name');
Index: branches/2.8.x/wb/include/Twig/Node/Expression/Name.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Expression/Name.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Expression/Name.php	(revision 1852)
@@ -19,7 +19,7 @@
 
     public function __construct($name, $lineno)
     {
-        parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false), $lineno);
+        parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false), $lineno);
     }
 
     public function compile(Twig_Compiler $compiler)
@@ -34,11 +34,17 @@
             }
         } elseif ($this->isSpecial()) {
             $compiler->raw($this->specialVars[$name]);
+        } elseif ($this->getAttribute('always_defined')) {
+            $compiler
+                ->raw('$context[')
+                ->string($name)
+                ->raw(']')
+            ;
         } else {
             // remove the non-PHP 5.4 version when PHP 5.3 support is dropped
             // as the non-optimized version is just a workaround for slow ternary operator
             // when the context has a lot of variables
-            if (version_compare(phpversion(), '5.4.0RC1', '>=') && ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables())) {
+            if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
                 // PHP 5.4 ternary operator performance was optimized
                 $compiler
                     ->raw('(isset($context[')
@@ -45,8 +51,14 @@
                     ->string($name)
                     ->raw(']) ? $context[')
                     ->string($name)
-                    ->raw('] : null)')
+                    ->raw('] : ')
                 ;
+
+                if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) {
+                    $compiler->raw('null)');
+                } else {
+                    $compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
+                }
             } else {
                 $compiler
                     ->raw('$this->getContext($context, ')
Index: branches/2.8.x/wb/include/Twig/Node/Expression/Function.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Expression/Function.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Expression/Function.php	(revision 1852)
@@ -25,7 +25,7 @@
                 $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
             }
 
-            throw new Twig_Error_Syntax($message, $this->getLine());
+            throw new Twig_Error_Syntax($message, $this->getLine(), $compiler->getFilename());
         }
 
         $compiler->raw($function->compile().'(');
Index: branches/2.8.x/wb/include/Twig/Node/Expression/Filter.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Expression/Filter.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Expression/Filter.php	(revision 1852)
@@ -26,7 +26,7 @@
                 $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
             }
 
-            throw new Twig_Error_Syntax($message, $this->getLine());
+            throw new Twig_Error_Syntax($message, $this->getLine(), $compiler->getFilename());
         }
 
         $this->compileFilter($compiler, $filter);
Index: branches/2.8.x/wb/include/Twig/Node/Embed.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Embed.php	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/Node/Embed.php	(revision 1852)
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents an embed node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ */
+class Twig_Node_Embed extends Twig_Node_Include
+{
+    // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module)
+    public function __construct($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
+    {
+        parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
+
+        $this->setAttribute('filename', $filename);
+        $this->setAttribute('index', $index);
+    }
+
+    protected function addGetTemplate(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->write("\$this->env->loadTemplate(")
+            ->string($this->getAttribute('filename'))
+            ->raw(', ')
+            ->string($this->getAttribute('index'))
+            ->raw(")")
+        ;
+    }
+}

Property changes on: branches/2.8.x/wb/include/Twig/Node/Embed.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision HeadURL
\ No newline at end of property
Index: branches/2.8.x/wb/include/Twig/Node/SandboxedModule.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/SandboxedModule.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/SandboxedModule.php	(revision 1852)
@@ -24,8 +24,10 @@
 
     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('filename'), $node->getLine(), $node->getNodeTag());
+        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;
@@ -43,7 +45,7 @@
         parent::compileDisplayFooter($compiler);
 
         $compiler
-            ->write("protected function checkSecurity() {\n")
+            ->write("protected function checkSecurity()\n", "{\n")
             ->indent()
             ->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
             ->indent()
Index: branches/2.8.x/wb/include/Twig/Node/Include.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Include.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Include.php	(revision 1852)
@@ -39,11 +39,33 @@
             ;
         }
 
+        $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(")->display(")
+                ->raw(")")
             ;
         } else {
             $compiler
@@ -50,10 +72,13 @@
                 ->write("\$template = \$this->env->resolveTemplate(")
                 ->subcompile($this->getNode('expr'))
                 ->raw(");\n")
-                ->write('$template->display(')
+                ->write('$template')
             ;
         }
+    }
 
+    protected function addTemplateArguments(Twig_Compiler $compiler)
+    {
         if (false === $this->getAttribute('only')) {
             if (null === $this->getNode('variables')) {
                 $compiler->raw('$context');
@@ -71,18 +96,5 @@
                 $compiler->subcompile($this->getNode('variables'));
             }
         }
-
-        $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")
-            ;
-        }
     }
 }
Index: branches/2.8.x/wb/include/Twig/Node/Module.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node/Module.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node/Module.php	(revision 1852)
@@ -18,11 +18,17 @@
  */
 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, $filename)
+    public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename)
     {
-        parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits), array('filename' => $filename), 1);
+        // 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.
      *
@@ -31,10 +37,18 @@
     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) {
@@ -108,10 +122,10 @@
     protected function compileClassHeader(Twig_Compiler $compiler)
     {
         $compiler
-            ->write("<?php\n\n")
+            ->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')))
+            ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index')))
             ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
             ->write("{\n")
             ->indent()
Index: branches/2.8.x/wb/include/Twig/Filter/Method.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Filter/Method.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Filter/Method.php	(revision 1852)
@@ -17,7 +17,8 @@
  */
 class Twig_Filter_Method extends Twig_Filter
 {
-    protected $extension, $method;
+    protected $extension;
+    protected $method;
 
     public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
     {
Index: branches/2.8.x/wb/include/Twig/LexerInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/LexerInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/LexerInterface.php	(revision 1852)
@@ -20,10 +20,10 @@
     /**
      * Tokenizes a source code.
      *
-     * @param  string $code     The source code
-     * @param  string $filename A unique identifier for the source code
+     * @param string $code     The source code
+     * @param string $filename A unique identifier for the source code
      *
      * @return Twig_TokenStream A token stream instance
      */
-    function tokenize($code, $filename = null);
+    public function tokenize($code, $filename = null);
 }
Index: branches/2.8.x/wb/include/Twig/TestInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TestInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TestInterface.php	(revision 1852)
@@ -22,5 +22,5 @@
      *
      * @return string The PHP code for the test
      */
-    function compile();
+    public function compile();
 }
Index: branches/2.8.x/wb/include/Twig/NodeInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/NodeInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/NodeInterface.php	(revision 1852)
@@ -22,9 +22,9 @@
      *
      * @param Twig_Compiler A Twig_Compiler instance
      */
-    function compile(Twig_Compiler $compiler);
+    public function compile(Twig_Compiler $compiler);
 
-    function getLine();
+    public function getLine();
 
-    function getNodeTag();
+    public function getNodeTag();
 }
Index: branches/2.8.x/wb/include/Twig/FilterInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/FilterInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/FilterInterface.php	(revision 1852)
@@ -22,19 +22,19 @@
      *
      * @return string The PHP code for the filter
      */
-    function compile();
+    public function compile();
 
-    function needsEnvironment();
+    public function needsEnvironment();
 
-    function needsContext();
+    public function needsContext();
 
-    function getSafe(Twig_Node $filterArgs);
+    public function getSafe(Twig_Node $filterArgs);
 
-    function getPreservesSafety();
+    public function getPreservesSafety();
 
-    function getPreEscape();
+    public function getPreEscape();
 
-    function setArguments($arguments);
+    public function setArguments($arguments);
 
-    function getArguments();
+    public function getArguments();
 }
Index: branches/2.8.x/wb/include/Twig/TokenParser/AutoEscape.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/AutoEscape.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/AutoEscape.php	(revision 1852)
@@ -39,23 +39,35 @@
     public function parse(Twig_Token $token)
     {
         $lineno = $token->getLine();
-        $value = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue();
-        if (!in_array($value, array('true', 'false'))) {
-            throw new Twig_Error_Syntax("Autoescape value must be 'true' or 'false'", $lineno);
-        }
-        $value = 'true' === $value ? 'html' : false;
+        $stream = $this->parser->getStream();
 
-        if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE)) {
-            if (false === $value) {
-                throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $lineno);
+        if ($stream->test(Twig_Token::BLOCK_END_TYPE)) {
+            $value = 'html';
+        } else {
+            $expr = $this->parser->getExpressionParser()->parseExpression();
+            if (!$expr instanceof Twig_Node_Expression_Constant) {
+                throw new Twig_Error_Syntax('An escaping strategy must be a string or a Boolean.', $stream->getCurrent()->getLine(), $stream->getFilename());
             }
+            $value = $expr->getAttribute('value');
 
-            $value = $this->parser->getStream()->next()->getValue();
+            $compat = true === $value || false === $value;
+
+            if (true === $value) {
+                $value = 'html';
+            }
+
+            if ($compat && $stream->test(Twig_Token::NAME_TYPE)) {
+                if (false === $value) {
+                    throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getFilename());
+                }
+
+                $value = $stream->next()->getValue();
+            }
         }
 
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
         $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
 
         return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag());
     }
Index: branches/2.8.x/wb/include/Twig/TokenParser/Block.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/Block.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/Block.php	(revision 1852)
@@ -35,7 +35,7 @@
         $stream = $this->parser->getStream();
         $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
         if ($this->parser->hasBlock($name)) {
-            throw new Twig_Error_Syntax(sprintf("The block '$name' has already been defined line %d", $this->parser->getBlock($name)->getLine()), $lineno);
+            throw new Twig_Error_Syntax(sprintf("The block '$name' has already been defined line %d", $this->parser->getBlock($name)->getLine()), $stream->getCurrent()->getLine(), $stream->getFilename());
         }
         $this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node(array()), $lineno));
         $this->parser->pushLocalScope();
@@ -49,7 +49,7 @@
                 $value = $stream->next()->getValue();
 
                 if ($value != $name) {
-                    throw new Twig_Error_Syntax(sprintf("Expected endblock for block '$name' (but %s given)", $value), $lineno);
+                    throw new Twig_Error_Syntax(sprintf("Expected endblock for block '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
                 }
             }
         } else {
Index: branches/2.8.x/wb/include/Twig/TokenParser/Set.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/Set.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/Set.php	(revision 1852)
@@ -49,13 +49,13 @@
             $stream->expect(Twig_Token::BLOCK_END_TYPE);
 
             if (count($names) !== count($values)) {
-                throw new Twig_Error_Syntax("When using set, you must have the same number of variables and assignements.", $lineno);
+                throw new Twig_Error_Syntax("When using set, you must have the same number of variables and assignements.", $stream->getCurrent()->getLine(), $stream->getFilename());
             }
         } else {
             $capture = true;
 
             if (count($names) > 1) {
-                throw new Twig_Error_Syntax("When using set with a block, you cannot have a multi-target.", $lineno);
+                throw new Twig_Error_Syntax("When using set with a block, you cannot have a multi-target.", $stream->getCurrent()->getLine(), $stream->getFilename());
             }
 
             $stream->expect(Twig_Token::BLOCK_END_TYPE);
Index: branches/2.8.x/wb/include/Twig/TokenParser/Use.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/Use.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/Use.php	(revision 1852)
@@ -35,13 +35,12 @@
     public function parse(Twig_Token $token)
     {
         $template = $this->parser->getExpressionParser()->parseExpression();
+        $stream = $this->parser->getStream();
 
         if (!$template instanceof Twig_Node_Expression_Constant) {
-            throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $token->getLine());
+            throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getFilename());
         }
 
-        $stream = $this->parser->getStream();
-
         $targets = array();
         if ($stream->test('with')) {
             $stream->next();
Index: branches/2.8.x/wb/include/Twig/TokenParser/If.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/If.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/If.php	(revision 1852)
@@ -36,7 +36,8 @@
     {
         $lineno = $token->getLine();
         $expr = $this->parser->getExpressionParser()->parseExpression();
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $stream = $this->parser->getStream();
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
         $body = $this->parser->subparse(array($this, 'decideIfFork'));
         $tests = array($expr, $body);
         $else = null;
@@ -43,15 +44,15 @@
 
         $end = false;
         while (!$end) {
-            switch ($this->parser->getStream()->next()->getValue()) {
+            switch ($stream->next()->getValue()) {
                 case 'else':
-                    $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+                    $stream->expect(Twig_Token::BLOCK_END_TYPE);
                     $else = $this->parser->subparse(array($this, 'decideIfEnd'));
                     break;
 
                 case 'elseif':
                     $expr = $this->parser->getExpressionParser()->parseExpression();
-                    $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+                    $stream->expect(Twig_Token::BLOCK_END_TYPE);
                     $body = $this->parser->subparse(array($this, 'decideIfFork'));
                     $tests[] = $expr;
                     $tests[] = $body;
@@ -62,11 +63,11 @@
                     break;
 
                 default:
-                    throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d)', $lineno), -1);
+                    throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d)', $lineno), $stream->getCurrent()->getLine(), $stream->getFilename());
             }
         }
 
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
 
         return new Twig_Node_If(new Twig_Node($tests), $else, $lineno, $this->getTag());
     }
Index: branches/2.8.x/wb/include/Twig/TokenParser/Sandbox.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/Sandbox.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/Sandbox.php	(revision 1852)
@@ -35,6 +35,19 @@
         $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
         $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
 
+        // in a sandbox tag, only include tags are allowed
+        if (!$body instanceof Twig_Node_Include) {
+            foreach ($body as $node) {
+                if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
+                    continue;
+                }
+
+                if (!$node instanceof Twig_Node_Include) {
+                    throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section', $node->getLine(), $this->parser->getFilename());
+                }
+            }
+        }
+
         return new Twig_Node_Sandbox($body, $token->getLine(), $this->getTag());
     }
 
Index: branches/2.8.x/wb/include/Twig/TokenParser/Macro.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/Macro.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/Macro.php	(revision 1852)
@@ -30,22 +30,23 @@
     public function parse(Twig_Token $token)
     {
         $lineno = $token->getLine();
-        $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue();
+        $stream = $this->parser->getStream();
+        $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
 
         $arguments = $this->parser->getExpressionParser()->parseArguments();
 
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
         $this->parser->pushLocalScope();
         $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
-        if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE)) {
-            $value = $this->parser->getStream()->next()->getValue();
+        if ($stream->test(Twig_Token::NAME_TYPE)) {
+            $value = $stream->next()->getValue();
 
             if ($value != $name) {
-                throw new Twig_Error_Syntax(sprintf("Expected endmacro for macro '$name' (but %s given)", $value), $lineno);
+                throw new Twig_Error_Syntax(sprintf("Expected endmacro for macro '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
             }
         }
         $this->parser->popLocalScope();
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
 
         $this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body(array($body)), $arguments, $lineno, $this->getTag()));
 
Index: branches/2.8.x/wb/include/Twig/TokenParser/From.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/From.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/From.php	(revision 1852)
@@ -55,8 +55,8 @@
 
         $node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag());
 
-        foreach($targets as $name => $alias) {
-            $this->parser->addImportedFunction($alias, 'get'.$name, $node->getNode('var'));
+        foreach ($targets as $name => $alias) {
+            $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
         }
 
         return $node;
Index: branches/2.8.x/wb/include/Twig/TokenParser/Extends.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/Extends.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/Extends.php	(revision 1852)
@@ -29,11 +29,11 @@
     public function parse(Twig_Token $token)
     {
         if (!$this->parser->isMainScope()) {
-            throw new Twig_Error_Syntax('Cannot extend from a block', $token->getLine());
+            throw new Twig_Error_Syntax('Cannot extend from a block', $token->getLine(), $this->parser->getFilename());
         }
 
         if (null !== $this->parser->getParent()) {
-            throw new Twig_Error_Syntax('Multiple extends tags are forbidden', $token->getLine());
+            throw new Twig_Error_Syntax('Multiple extends tags are forbidden', $token->getLine(), $this->parser->getFilename());
         }
         $this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
 
Index: branches/2.8.x/wb/include/Twig/TokenParser/Import.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/Import.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/Import.php	(revision 1852)
@@ -32,6 +32,8 @@
         $var = new Twig_Node_Expression_AssignName($this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(), $token->getLine());
         $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
 
+        $this->parser->addImportedSymbol('template', $var->getAttribute('name'));
+
         return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag());
     }
 
Index: branches/2.8.x/wb/include/Twig/TokenParser/Embed.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/Embed.php	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/TokenParser/Embed.php	(revision 1852)
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Embeds a template.
+ */
+class Twig_TokenParser_Embed extends Twig_TokenParser_Include
+{
+    /**
+     * Parses a token and returns a node.
+     *
+     * @param Twig_Token $token A Twig_Token instance
+     *
+     * @return Twig_NodeInterface A Twig_NodeInterface instance
+     */
+    public function parse(Twig_Token $token)
+    {
+        $stream = $this->parser->getStream();
+
+        $parent = $this->parser->getExpressionParser()->parseExpression();
+
+        list($variables, $only, $ignoreMissing) = $this->parseArguments();
+
+        // inject a fake parent to make the parent() function work
+        $stream->injectTokens(array(
+            new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $token->getLine()),
+            new Twig_Token(Twig_Token::NAME_TYPE, 'extends', $token->getLine()),
+            new Twig_Token(Twig_Token::STRING_TYPE, '__parent__', $token->getLine()),
+            new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $token->getLine()),
+        ));
+
+        $module = $this->parser->parse($stream, array($this, 'decideBlockEnd'), true);
+
+        // override the parent with the correct one
+        $module->setNode('parent', $parent);
+
+        $this->parser->embedTemplate($module);
+
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
+
+        return new Twig_Node_Embed($module->getAttribute('filename'), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
+    }
+
+    public function decideBlockEnd(Twig_Token $token)
+    {
+        return $token->test('endembed');
+    }
+
+    /**
+     * Gets the tag name associated with this token parser.
+     *
+     * @return string The tag name
+     */
+    public function getTag()
+    {
+        return 'embed';
+    }
+}

Property changes on: branches/2.8.x/wb/include/Twig/TokenParser/Embed.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision HeadURL
\ No newline at end of property
Index: branches/2.8.x/wb/include/Twig/TokenParser/Include.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParser/Include.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParser/Include.php	(revision 1852)
@@ -32,31 +32,40 @@
     {
         $expr = $this->parser->getExpressionParser()->parseExpression();
 
+        list($variables, $only, $ignoreMissing) = $this->parseArguments();
+
+        return new Twig_Node_Include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
+    }
+
+    protected function parseArguments()
+    {
+        $stream = $this->parser->getStream();
+
         $ignoreMissing = false;
-        if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'ignore')) {
-            $this->parser->getStream()->next();
-            $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, 'missing');
+        if ($stream->test(Twig_Token::NAME_TYPE, 'ignore')) {
+            $stream->next();
+            $stream->expect(Twig_Token::NAME_TYPE, 'missing');
 
             $ignoreMissing = true;
         }
 
         $variables = null;
-        if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'with')) {
-            $this->parser->getStream()->next();
+        if ($stream->test(Twig_Token::NAME_TYPE, 'with')) {
+            $stream->next();
 
             $variables = $this->parser->getExpressionParser()->parseExpression();
         }
 
         $only = false;
-        if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'only')) {
-            $this->parser->getStream()->next();
+        if ($stream->test(Twig_Token::NAME_TYPE, 'only')) {
+            $stream->next();
 
             $only = true;
         }
 
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
 
-        return new Twig_Node_Include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
+        return array($variables, $only, $ignoreMissing);
     }
 
     /**
Index: branches/2.8.x/wb/include/Twig/Sandbox/SecurityPolicyInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Sandbox/SecurityPolicyInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Sandbox/SecurityPolicyInterface.php	(revision 1852)
@@ -17,9 +17,9 @@
  */
 interface Twig_Sandbox_SecurityPolicyInterface
 {
-    function checkSecurity($tags, $filters, $functions);
+    public function checkSecurity($tags, $filters, $functions);
 
-    function checkMethodAllowed($obj, $method);
+    public function checkMethodAllowed($obj, $method);
 
-    function checkPropertyAllowed($obj, $method);
+    public function checkPropertyAllowed($obj, $method);
 }
Index: branches/2.8.x/wb/include/Twig/Template.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Template.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Template.php	(revision 1852)
@@ -18,7 +18,7 @@
  */
 abstract class Twig_Template implements Twig_TemplateInterface
 {
-    static protected $cache = array();
+    protected static $cache = array();
 
     protected $parent;
     protected $parents;
@@ -264,6 +264,17 @@
         try {
             $this->doDisplay($context, $blocks);
         } catch (Twig_Error $e) {
+            if (!$e->getTemplateFile()) {
+                $e->setTemplateFile($this->getTemplateName());
+            }
+
+            // this is mostly useful for Twig_Error_Loader exceptions
+            // see Twig_Error_Loader
+            if (false === $e->getTemplateLine()) {
+                $e->setTemplateLine(-1);
+                $e->guess();
+            }
+
             throw $e;
         } catch (Exception $e) {
             throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, null, $e);
@@ -284,7 +295,7 @@
      * This method is for internal use only and should never be called
      * directly.
      *
-     * This method should not be overriden in a sub-class as this is an
+     * This method should not be overridden in a sub-class as this is an
      * implementation detail that has been introduced to optimize variable
      * access for versions of PHP before 5.4. This is not a way to override
      * the way to get a variable value.
@@ -304,7 +315,7 @@
                 return null;
             }
 
-            throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist', $item));
+            throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist', $item), -1, $this->getTemplateName());
         }
 
         return $context[$item];
@@ -326,7 +337,7 @@
      */
     protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_TemplateInterface::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
     {
-        $item = (string) $item;
+        $item = ctype_digit((string) $item) ? (int) $item : (string) $item;
 
         // array
         if (Twig_TemplateInterface::METHOD_CALL !== $type) {
@@ -350,11 +361,11 @@
                 }
 
                 if (is_object($object)) {
-                    throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $item, get_class($object)));
+                    throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName());
                 } elseif (is_array($object)) {
-                    throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $item, implode(', ', array_keys($object))));
+                    throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $item, implode(', ', array_keys($object))), -1, $this->getTemplateName());
                 } else {
-                    throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a "%s" variable', $item, gettype($object)));
+                    throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a "%s" variable', $item, gettype($object)), -1, $this->getTemplateName());
                 }
             }
         }
@@ -368,7 +379,7 @@
                 return null;
             }
 
-            throw new Twig_Error_Runtime(sprintf('Item "%s" for "%s" does not exist', $item, is_array($object) ? 'Array' : $object));
+            throw new Twig_Error_Runtime(sprintf('Item "%s" for "%s" does not exist', $item, is_array($object) ? 'Array' : $object), -1, $this->getTemplateName());
         }
 
         $class = get_class($object);
@@ -375,14 +386,6 @@
 
         // object property
         if (Twig_TemplateInterface::METHOD_CALL !== $type) {
-            /* apparently, this is not needed as this is already covered by the array_key_exists() call below
-            if (!isset(self::$cache[$class]['properties'])) {
-                foreach (get_object_vars($object) as $k => $v) {
-                    self::$cache[$class]['properties'][$k] = true;
-                }
-            }
-            */
-
             if (isset($object->$item) || array_key_exists($item, $object)) {
                 if ($isDefinedTest) {
                     return true;
@@ -419,7 +422,7 @@
                 return null;
             }
 
-            throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)));
+            throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName());
         }
 
         if ($isDefinedTest) {
@@ -432,7 +435,8 @@
 
         $ret = call_user_func_array(array($object, $method), $arguments);
 
-        // hack to be removed when macro calls are refactored
+        // useful when calling a template method from a template
+        // this is not supported but unfortunately heavily used in the Symfony profiler
         if ($object instanceof Twig_TemplateInterface) {
             return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset());
         }
@@ -443,7 +447,7 @@
     /**
      * This method is only useful when testing Twig. Do not use it.
      */
-    static public function clearCache()
+    public static function clearCache()
     {
         self::$cache = array();
     }
Index: branches/2.8.x/wb/include/Twig/TokenParserInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParserInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParserInterface.php	(revision 1852)
@@ -22,7 +22,7 @@
      *
      * @param $parser A Twig_Parser instance
      */
-    function setParser(Twig_Parser $parser);
+    public function setParser(Twig_Parser $parser);
 
     /**
      * Parses a token and returns a node.
@@ -31,7 +31,7 @@
      *
      * @return Twig_NodeInterface A Twig_NodeInterface instance
      */
-    function parse(Twig_Token $token);
+    public function parse(Twig_Token $token);
 
     /**
      * Gets the tag name associated with this token parser.
@@ -38,5 +38,5 @@
      *
      * @return string The tag name
      */
-    function getTag();
+    public function getTag();
 }
Index: branches/2.8.x/wb/include/Twig/NodeVisitor/Sandbox.php
===================================================================
--- branches/2.8.x/wb/include/Twig/NodeVisitor/Sandbox.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/NodeVisitor/Sandbox.php	(revision 1852)
@@ -32,19 +32,6 @@
      */
     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();
Index: branches/2.8.x/wb/include/Twig/NodeVisitor/Escaper.php
===================================================================
--- branches/2.8.x/wb/include/Twig/NodeVisitor/Escaper.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/NodeVisitor/Escaper.php	(revision 1852)
@@ -19,11 +19,12 @@
 {
     protected $statusStack = array();
     protected $blocks = array();
-
     protected $safeAnalysis;
     protected $traverser;
+    protected $defaultStrategy = false;
+    protected $safeVars = array();
 
-    function __construct()
+    public function __construct()
     {
         $this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis();
     }
@@ -38,10 +39,17 @@
      */
     public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
     {
-        if ($node instanceof Twig_Node_AutoEscape) {
+        if ($node instanceof Twig_Node_Module) {
+            if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
+                $this->defaultStrategy = $defaultStrategy;
+            }
+            $this->safeVars = array();
+        } 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);
+        } elseif ($node instanceof Twig_Node_Import) {
+            $this->safeVars[] = $node->getNode('var')->getAttribute('name');
         }
 
         return $node;
@@ -57,7 +65,10 @@
      */
     public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
     {
-        if ($node instanceof Twig_Node_Expression_Filter) {
+        if ($node instanceof Twig_Node_Module) {
+            $this->defaultStrategy = false;
+            $this->safeVars = array();
+        } 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));
@@ -123,6 +134,9 @@
             if (null === $this->traverser) {
                 $this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis));
             }
+
+            $this->safeAnalysis->setSafeVars($this->safeVars);
+
             $this->traverser->traverse($expression);
             $safe = $this->safeAnalysis->getSafe($expression);
         }
@@ -136,11 +150,7 @@
             return $this->statusStack[count($this->statusStack) - 1];
         }
 
-        if ($env->hasExtension('escaper') && $env->getExtension('escaper')->isGlobal()) {
-            return 'html';
-        }
-
-        return false;
+        return $this->defaultStrategy ? $this->defaultStrategy : false;
     }
 
     protected function getEscaperFilter($type, Twig_NodeInterface $node)
Index: branches/2.8.x/wb/include/Twig/NodeVisitor/Optimizer.php
===================================================================
--- branches/2.8.x/wb/include/Twig/NodeVisitor/Optimizer.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/NodeVisitor/Optimizer.php	(revision 1852)
@@ -56,7 +56,7 @@
             $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 (!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') {
Index: branches/2.8.x/wb/include/Twig/NodeVisitor/SafeAnalysis.php
===================================================================
--- branches/2.8.x/wb/include/Twig/NodeVisitor/SafeAnalysis.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/NodeVisitor/SafeAnalysis.php	(revision 1852)
@@ -3,12 +3,18 @@
 class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
 {
     protected $data = array();
+    protected $safeVars = array();
 
+    public function setSafeVars($safeVars)
+    {
+        $this->safeVars = $safeVars;
+    }
+
     public function getSafe(Twig_NodeInterface $node)
     {
         $hash = spl_object_hash($node);
         if (isset($this->data[$hash])) {
-            foreach($this->data[$hash] as $bucket) {
+            foreach ($this->data[$hash] as $bucket) {
                 if ($bucket['key'] === $node) {
                     return $bucket['value'];
                 }
@@ -22,7 +28,7 @@
     {
         $hash = spl_object_hash($node);
         if (isset($this->data[$hash])) {
-            foreach($this->data[$hash] as &$bucket) {
+            foreach ($this->data[$hash] as &$bucket) {
                 if ($bucket['key'] === $node) {
                     $bucket['value'] = $safe;
 
@@ -85,6 +91,14 @@
             } else {
                 $this->setSafe($node, array());
             }
+        } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) {
+            $name = $node->getNode('node')->getAttribute('name');
+            // attributes on template instances are safe
+            if ('_self' == $name || in_array($name, $this->safeVars)) {
+                $this->setSafe($node, array('all'));
+            } else {
+                $this->setSafe($node, array());
+            }
         } else {
             $this->setSafe($node, array());
         }
Index: branches/2.8.x/wb/include/Twig/Loader/Array.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Loader/Array.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Loader/Array.php	(revision 1852)
@@ -20,7 +20,7 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
  */
-class Twig_Loader_Array implements Twig_LoaderInterface
+class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
 {
     protected $templates;
 
@@ -51,11 +51,7 @@
     }
 
     /**
-     * Gets the source code of a template, given its name.
-     *
-     * @param  string $name The name of the template to load
-     *
-     * @return string The template source code
+     * {@inheritdoc}
      */
     public function getSource($name)
     {
@@ -68,12 +64,16 @@
     }
 
     /**
-     * Gets the cache key to use for the cache for a given template name.
-     *
-     * @param  string $name The name of the template to load
-     *
-     * @return string The cache key
+     * {@inheritdoc}
      */
+    public function exists($name)
+    {
+        return isset($this->templates[(string) $name]);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
     public function getCacheKey($name)
     {
         $name = (string) $name;
@@ -85,10 +85,7 @@
     }
 
     /**
-     * Returns true if the template is still fresh.
-     *
-     * @param string    $name The template name
-     * @param timestamp $time The last modification time of the cached template
+     * {@inheritdoc}
      */
     public function isFresh($name, $time)
     {
Index: branches/2.8.x/wb/include/Twig/Loader/Chain.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Loader/Chain.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Loader/Chain.php	(revision 1852)
@@ -15,8 +15,9 @@
  * @package twig
  * @author  Fabien Potencier <fabien@symfony.com>
  */
-class Twig_Loader_Chain implements Twig_LoaderInterface
+class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
 {
+    private $hasSourceCache = array();
     protected $loaders;
 
     /**
@@ -40,61 +41,96 @@
     public function addLoader(Twig_LoaderInterface $loader)
     {
         $this->loaders[] = $loader;
+        $this->hasSourceCache = array();
     }
 
     /**
-     * Gets the source code of a template, given its name.
-     *
-     * @param  string $name The name of the template to load
-     *
-     * @return string The template source code
+     * {@inheritdoc}
      */
     public function getSource($name)
     {
+        $exceptions = array();
         foreach ($this->loaders as $loader) {
+            if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
+                continue;
+            }
+
             try {
                 return $loader->getSource($name);
             } catch (Twig_Error_Loader $e) {
+                $exceptions[] = $e->getMessage();
             }
         }
 
-        throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
+        throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions)));
     }
 
     /**
-     * Gets the cache key to use for the cache for a given template name.
-     *
-     * @param  string $name The name of the template to load
-     *
-     * @return string The cache key
+     * {@inheritdoc}
      */
+    public function exists($name)
+    {
+        $name = (string) $name;
+
+        if (isset($this->hasSourceCache[$name])) {
+            return $this->hasSourceCache[$name];
+        }
+
+        foreach ($this->loaders as $loader) {
+            if ($loader instanceof Twig_ExistsLoaderInterface && $loader->exists($name)) {
+                return $this->hasSourceCache[$name] = true;
+            }
+
+            try {
+                $loader->getSource($name);
+
+                return $this->hasSourceCache[$name] = true;
+            } catch (Twig_Error_Loader $e) {
+            }
+        }
+
+        return $this->hasSourceCache[$name] = false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
     public function getCacheKey($name)
     {
+        $exceptions = array();
         foreach ($this->loaders as $loader) {
+            if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
+                continue;
+            }
+
             try {
                 return $loader->getCacheKey($name);
             } catch (Twig_Error_Loader $e) {
+                $exceptions[] = get_class($loader).': '.$e->getMessage();
             }
         }
 
-        throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
+        throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
     }
 
     /**
-     * Returns true if the template is still fresh.
-     *
-     * @param string    $name The template name
-     * @param timestamp $time The last modification time of the cached template
+     * {@inheritdoc}
      */
     public function isFresh($name, $time)
     {
+        $exceptions = array();
         foreach ($this->loaders as $loader) {
+            if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
+                continue;
+            }
+
             try {
                 return $loader->isFresh($name, $time);
             } catch (Twig_Error_Loader $e) {
+                $exceptions[] = get_class($loader).': '.$e->getMessage();
             }
         }
 
-        throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
+        throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
     }
 }
Index: branches/2.8.x/wb/include/Twig/Loader/Filesystem.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Loader/Filesystem.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Loader/Filesystem.php	(revision 1852)
@@ -15,7 +15,7 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
  */
-class Twig_Loader_Filesystem implements Twig_LoaderInterface
+class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
 {
     protected $paths;
     protected $cache;
@@ -33,27 +33,42 @@
     /**
      * Returns the paths to the templates.
      *
+     * @param string $namespace A path namespace
+     *
      * @return array The array of paths where to look for templates
      */
-    public function getPaths()
+    public function getPaths($namespace = '__main__')
     {
-        return $this->paths;
+        return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array();
     }
 
     /**
+     * Returns the path namespaces.
+     *
+     * The "__main__" namespace is always defined.
+     *
+     * @return array The array of defined namespaces
+     */
+    public function getNamespaces()
+    {
+        return array_keys($this->paths);
+    }
+
+    /**
      * Sets the paths where templates are stored.
      *
-     * @param string|array $paths A path or an array of paths where to look for templates
+     * @param string|array $paths     A path or an array of paths where to look for templates
+     * @param string       $namespace A path namespace
      */
-    public function setPaths($paths)
+    public function setPaths($paths, $namespace = '__main__')
     {
         if (!is_array($paths)) {
             $paths = array($paths);
         }
 
-        $this->paths = array();
+        $this->paths[$namespace] = array();
         foreach ($paths as $path) {
-            $this->addPath($path);
+            $this->addPath($path, $namespace);
         }
     }
 
@@ -60,9 +75,12 @@
     /**
      * Adds a path where templates are stored.
      *
-     * @param string $path A path where to look for templates
+     * @param string $path      A path where to look for templates
+     * @param string $namespace A path name
+     *
+     * @throws Twig_Error_Loader
      */
-    public function addPath($path)
+    public function addPath($path, $namespace = '__main__')
     {
         // invalidate the cache
         $this->cache = array();
@@ -71,16 +89,38 @@
             throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
         }
 
-        $this->paths[] = $path;
+        $this->paths[$namespace][] = rtrim($path, '/\\');
     }
 
     /**
-     * Gets the source code of a template, given its name.
+     * Prepends a path where templates are stored.
      *
-     * @param  string $name The name of the template to load
+     * @param string $path      A path where to look for templates
+     * @param string $namespace A path name
      *
-     * @return string The template source code
+     * @throws Twig_Error_Loader
      */
+    public function prependPath($path, $namespace = '__main__')
+    {
+        // invalidate the cache
+        $this->cache = array();
+
+        if (!is_dir($path)) {
+            throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
+        }
+
+        $path = rtrim($path, '/\\');
+
+        if (!isset($this->paths[$namespace])) {
+            $this->paths[$namespace][] = $path;
+        } else {
+            array_unshift($this->paths[$namespace], $path);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
     public function getSource($name)
     {
         return file_get_contents($this->findTemplate($name));
@@ -87,11 +127,7 @@
     }
 
     /**
-     * Gets the cache key to use for the cache for a given template name.
-     *
-     * @param  string $name The name of the template to load
-     *
-     * @return string The cache key
+     * {@inheritdoc}
      */
     public function getCacheKey($name)
     {
@@ -99,11 +135,27 @@
     }
 
     /**
-     * Returns true if the template is still fresh.
-     *
-     * @param string    $name The template name
-     * @param timestamp $time The last modification time of the cached template
+     * {@inheritdoc}
      */
+    public function exists($name)
+    {
+        $name = (string) $name;
+        if (isset($this->cache[$name])) {
+            return true;
+        }
+
+        try {
+            $this->findTemplate($name);
+
+            return true;
+        } catch (Twig_Error_Loader $exception) {
+            return false;
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
     public function isFresh($name, $time)
     {
         return filemtime($this->findTemplate($name)) <= $time;
@@ -111,6 +163,8 @@
 
     protected function findTemplate($name)
     {
+        $name = (string) $name;
+
         // normalize name
         $name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/'));
 
@@ -120,13 +174,28 @@
 
         $this->validateName($name);
 
-        foreach ($this->paths as $path) {
+        $namespace = '__main__';
+        if (isset($name[0]) && '@' == $name[0]) {
+            if (false === $pos = strpos($name, '/')) {
+                throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
+            }
+
+            $namespace = substr($name, 1, $pos - 1);
+
+            $name = substr($name, $pos + 1);
+        }
+
+        if (!isset($this->paths[$namespace])) {
+            throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace));
+        }
+
+        foreach ($this->paths[$namespace] as $path) {
             if (is_file($path.'/'.$name)) {
                 return $this->cache[$name] = $path.'/'.$name;
             }
         }
 
-        throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths)));
+        throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])));
     }
 
     protected function validateName($name)
Index: branches/2.8.x/wb/include/Twig/Loader/String.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Loader/String.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Loader/String.php	(revision 1852)
@@ -12,6 +12,10 @@
 /**
  * Loads a template from a string.
  *
+ * This loader should only be used for unit testing as it has many limitations
+ * (for instance, the include or extends tag does not make any sense for a string
+ * loader).
+ *
  * When using this loader with a cache mechanism, you should know that a new cache
  * key is generated each time a template content "changes" (the cache key being the
  * source code of the template). If you don't want to see your cache grows out of
@@ -20,14 +24,10 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
  */
-class Twig_Loader_String implements Twig_LoaderInterface
+class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
 {
     /**
-     * Gets the source code of a template, given its name.
-     *
-     * @param  string $name The name of the template to load
-     *
-     * @return string The template source code
+     * {@inheritdoc}
      */
     public function getSource($name)
     {
@@ -35,12 +35,16 @@
     }
 
     /**
-     * Gets the cache key to use for the cache for a given template name.
-     *
-     * @param  string $name The name of the template to load
-     *
-     * @return string The cache key
+     * {@inheritdoc}
      */
+    public function exists($name)
+    {
+        return true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
     public function getCacheKey($name)
     {
         return $name;
@@ -47,10 +51,7 @@
     }
 
     /**
-     * Returns true if the template is still fresh.
-     *
-     * @param string    $name The template name
-     * @param timestamp $time The last modification time of the cached template
+     * {@inheritdoc}
      */
     public function isFresh($name, $time)
     {
Index: branches/2.8.x/wb/include/Twig/TokenParserBrokerInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParserBrokerInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParserBrokerInterface.php	(revision 1852)
@@ -23,11 +23,11 @@
     /**
      * Gets a TokenParser suitable for a tag.
      *
-     * @param  string $tag A tag name
+     * @param string $tag A tag name
      *
      * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found
      */
-    function getTokenParser($tag);
+    public function getTokenParser($tag);
 
     /**
      * Calls Twig_TokenParserInterface::setParser on all parsers the implementation knows of.
@@ -34,12 +34,12 @@
      *
      * @param Twig_ParserInterface $parser A Twig_ParserInterface interface
      */
-    function setParser(Twig_ParserInterface $parser);
+    public function setParser(Twig_ParserInterface $parser);
 
     /**
      * Gets the Twig_ParserInterface.
      *
-     * @return null|Twig_ParserInterface A Twig_ParserInterface instance of null
+     * @return null|Twig_ParserInterface A Twig_ParserInterface instance or null
      */
-    function getParser();
+    public function getParser();
 }
Index: branches/2.8.x/wb/include/Twig/Extension/StringLoader.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Extension/StringLoader.php	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/Extension/StringLoader.php	(revision 1852)
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Extension_StringLoader extends Twig_Extension
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getFunctions()
+    {
+        return array(
+            'template_from_string' => new Twig_Function_Function('twig_template_from_string', array('needs_environment' => true)),
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'string_loader';
+    }
+}
+
+/**
+ * Loads a template from a string.
+ *
+ * <pre>
+ * {% include template_from_string("Hello {{ name }}") }}
+ * </pre>
+ *
+ * @param Twig_Environment $env      A Twig_Environment instance
+ * @param string           $template A template as a string
+ *
+ * @return Twig_Template A Twig_Template instance
+ */
+function twig_template_from_string(Twig_Environment $env, $template)
+{
+    static $loader;
+
+    if (null === $loader) {
+        $loader = new Twig_Loader_String();
+    }
+
+    $current = $env->getLoader();
+    $env->setLoader($loader);
+    try {
+        $template = $env->loadTemplate($template);
+    } catch (Exception $e) {
+        $env->setLoader($current);
+
+        throw $e;
+    }
+    $env->setLoader($current);
+
+    return $template;
+}

Property changes on: branches/2.8.x/wb/include/Twig/Extension/StringLoader.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision HeadURL
\ No newline at end of property
Index: branches/2.8.x/wb/include/Twig/Extension/Escaper.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Extension/Escaper.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Extension/Escaper.php	(revision 1852)
@@ -10,11 +10,11 @@
  */
 class Twig_Extension_Escaper extends Twig_Extension
 {
-    protected $autoescape;
+    protected $defaultStrategy;
 
-    public function __construct($autoescape = true)
+    public function __construct($defaultStrategy = 'html')
     {
-        $this->autoescape = $autoescape;
+        $this->setDefaultStrategy($defaultStrategy);
     }
 
     /**
@@ -49,12 +49,43 @@
         );
     }
 
-    public function isGlobal()
+    /**
+     * Sets the default strategy to use when not defined by the user.
+     *
+     * The strategy can be a valid PHP callback that takes the template
+     * "filename" as an argument and returns the strategy to use.
+     *
+     * @param mixed $defaultStrategy An escaping strategy
+     */
+    public function setDefaultStrategy($defaultStrategy)
     {
-        return $this->autoescape;
+        // for BC
+        if (true === $defaultStrategy) {
+            $defaultStrategy = 'html';
+        }
+
+        $this->defaultStrategy = $defaultStrategy;
     }
 
     /**
+     * Gets the default strategy to use when not defined by the user.
+     *
+     * @param string $filename The template "filename"
+     *
+     * @return string The default strategy to use for the template
+     */
+    public function getDefaultStrategy($filename)
+    {
+        // disable string callables to avoid calling a function named html or js,
+        // or any other upcoming escaping strategy
+        if (!is_string($this->defaultStrategy) && is_callable($this->defaultStrategy)) {
+            return call_user_func($this->defaultStrategy, $filename);
+        }
+
+        return $this->defaultStrategy;
+    }
+
+    /**
      * Returns the name of the extension.
      *
      * @return string The extension name
@@ -74,4 +105,3 @@
 {
     return $string;
 }
-
Index: branches/2.8.x/wb/include/Twig/Extension/Debug.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Extension/Debug.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Extension/Debug.php	(revision 1852)
@@ -17,8 +17,14 @@
      */
     public function getFunctions()
     {
-        // dump is safe if var_dump is overriden by xdebug
-        $isDumpOutputHtmlSafe = extension_loaded('xdebug') && (false === get_cfg_var('xdebug.overload_var_dump') || get_cfg_var('xdebug.overload_var_dump')) && get_cfg_var('html_errors');
+        // dump is safe if var_dump is overridden by xdebug
+        $isDumpOutputHtmlSafe = extension_loaded('xdebug')
+            // false means that it was not set (and the default is on) or it explicitly enabled
+            && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump'))
+            // false means that it was not set (and the default is on) or it explicitly enabled
+            // xdebug.overload_var_dump produces HTML only when html_errors is also enabled
+            && (false === ini_get('html_errors') || ini_get('html_errors'))
+        ;
 
         return array(
             'dump' => new Twig_Function_Function('twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)),
Index: branches/2.8.x/wb/include/Twig/Extension/Core.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Extension/Core.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Extension/Core.php	(revision 1852)
@@ -48,7 +48,7 @@
     /**
      * Sets the default timezone to be used by the date filter.
      *
-     * @param DateTimeZone|string $timezone  The default timezone string or a DateTimeZone object
+     * @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object
      */
     public function setTimezone($timezone)
     {
@@ -62,6 +62,10 @@
      */
     public function getTimezone()
     {
+        if (null === $this->timezone) {
+            $this->timezone = new DateTimeZone(date_default_timezone_get());
+        }
+
         return $this->timezone;
     }
 
@@ -68,9 +72,9 @@
     /**
      * Sets the default format to be used by the number_format filter.
      *
-     * @param integer $decimal The number of decimal places to use.
-     * @param string $decimalPoint The character(s) to use for the decimal point.
-     * @param string $thousandSep The character(s) to use for the thousands separator.
+     * @param integer $decimal      The number of decimal places to use.
+     * @param string  $decimalPoint The character(s) to use for the decimal point.
+     * @param string  $thousandSep  The character(s) to use for the thousands separator.
      */
     public function setNumberFormat($decimal, $decimalPoint, $thousandSep)
     {
@@ -109,6 +113,7 @@
             new Twig_TokenParser_Spaceless(),
             new Twig_TokenParser_Flush(),
             new Twig_TokenParser_Do(),
+            new Twig_TokenParser_Embed(),
         );
     }
 
@@ -122,9 +127,11 @@
         $filters = array(
             // formatting filters
             'date'          => new Twig_Filter_Function('twig_date_format_filter', array('needs_environment' => true)),
+            'date_modify'   => new Twig_Filter_Function('twig_date_modify_filter', array('needs_environment' => true)),
             'format'        => new Twig_Filter_Function('sprintf'),
             'replace'       => new Twig_Filter_Function('strtr'),
             'number_format' => new Twig_Filter_Function('twig_number_format_filter', array('needs_environment' => true)),
+            'abs'           => new Twig_Filter_Function('abs'),
 
             // encoding
             'url_encode'       => new Twig_Filter_Function('twig_urlencode_filter'),
@@ -142,6 +149,7 @@
 
             // array helpers
             'join'    => new Twig_Filter_Function('twig_join_filter'),
+            'split'   => new Twig_Filter_Function('twig_split_filter'),
             'sort'    => new Twig_Filter_Function('twig_sort_filter'),
             'merge'   => new Twig_Filter_Function('twig_array_merge'),
 
@@ -220,11 +228,11 @@
                 '+'   => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'),
             ),
             array(
-                'b-and'  => array('precedence' => 5, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
-                'b-xor'  => array('precedence' => 5, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
-                'b-or'   => array('precedence' => 5, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                 'or'     => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                 'and'    => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                'b-or'   => array('precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                'b-xor'  => array('precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                'b-and'  => array('precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                 '=='     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                 '!='     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                 '<'      => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
@@ -311,8 +319,8 @@
  * - a random character from a string
  * - a random integer between 0 and the integer parameter
  *
- * @param Twig_Environment             $env    A Twig_Environment instance
- * @param Traversable|array|int|string $values The values to pick a random item from
+ * @param Twig_Environment                 $env    A Twig_Environment instance
+ * @param Traversable|array|integer|string $values The values to pick a random item from
  *
  * @throws Twig_Error_Runtime When $values is an empty array (does not apply to an empty string which is returned as is).
  *
@@ -376,7 +384,7 @@
  * @param string                       $format   A format
  * @param DateTimeZone|string          $timezone A timezone
  *
- * @return string The formatter date
+ * @return string The formatted date
  */
 function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
 {
@@ -385,11 +393,7 @@
         $format = $date instanceof DateInterval ? $formats[1] : $formats[0];
     }
 
-    if ($date instanceof DateInterval || $date instanceof DateTime) {
-        if (null !== $timezone) {
-            $date->setTimezone($timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone));
-        }
-
+    if ($date instanceof DateInterval) {
         return $date->format($format);
     }
 
@@ -397,6 +401,27 @@
 }
 
 /**
+ * Returns a new date object modified
+ *
+ * <pre>
+ *   {{ post.published_at|modify("-1day")|date("m/d/Y") }}
+ * </pre>
+ *
+ * @param Twig_Environment  $env      A Twig_Environment instance
+ * @param DateTime|string   $date     A date
+ * @param string            $modifier A modifier string
+ *
+ * @return DateTime A new date object
+ */
+function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
+{
+    $date = twig_date_converter($env, $date, false);
+    $date->modify($modifier);
+
+    return $date;
+}
+
+/**
  * Converts an input to a DateTime instance.
  *
  * <pre>
@@ -413,31 +438,33 @@
  */
 function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null)
 {
+    // determine the timezone
+    if (!$timezone) {
+        $defaultTimezone = $env->getExtension('core')->getTimezone();
+    } elseif (!$timezone instanceof DateTimeZone) {
+        $defaultTimezone = new DateTimeZone($timezone);
+    } else {
+        $defaultTimezone = $timezone;
+    }
+
     if ($date instanceof DateTime) {
+        $date = clone $date;
+        if (false !== $timezone) {
+            $date->setTimezone($defaultTimezone);
+        }
+
         return $date;
     }
 
     $asString = (string) $date;
-
     if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
         $date = new DateTime('@'.$date);
-        $date->setTimezone(new DateTimeZone(date_default_timezone_get()));
-    } else {
-        $date = new DateTime($date);
-    }
+        $date->setTimezone($defaultTimezone);
 
-    // set Timezone
-    if (null !== $timezone) {
-        if (!$timezone instanceof DateTimeZone) {
-            $timezone = new DateTimeZone($timezone);
-        }
-
-        $date->setTimezone($timezone);
-    } elseif (($timezone = $env->getExtension('core')->getTimezone()) instanceof DateTimeZone) {
-        $date->setTimezone($timezone);
+        return $date;
     }
 
-    return $date;
+    return new DateTime($date, $defaultTimezone);
 }
 
 /**
@@ -449,7 +476,7 @@
  *
  * @param Twig_Environment    $env          A Twig_Environment instance
  * @param mixed               $number       A float/int/string of the number to format
- * @param int                 $decimal      The number of decimal points to display.
+ * @param integer             $decimal      The number of decimal points to display.
  * @param string              $decimalPoint The character(s) to use for the decimal point.
  * @param string              $thousandSep  The character(s) to use for the thousands separator.
  *
@@ -619,6 +646,38 @@
     return implode($glue, (array) $value);
 }
 
+/**
+ * Splits the string into an array.
+ *
+ * <pre>
+ *  {{ "one,two,three"|split(',') }}
+ *  {# returns [one, two, three] #}
+ *
+ *  {{ "one,two,three,four,five"|split(',', 3) }}
+ *  {# returns [one, two, "three,four,five"] #}
+ *
+ *  {{ "123"|split('') }}
+ *  {# returns [1, 2, 3] #}
+ *
+ *  {{ "aabbcc"|split('', 2) }}
+ *  {# returns [aa, bb, cc] #}
+ * </pre>
+ *
+ * @param string  $value     A string
+ * @param string  $delimiter The delimiter
+ * @param integer $limit     The limit
+ *
+ * @return array The split string as an array
+ */
+function twig_split_filter($value, $delimiter, $limit = null)
+{
+    if (empty($delimiter)) {
+        return str_split($value, null === $limit ? 1 : $limit);
+    }
+
+    return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
+}
+
 // The '_default' filter is used internally to avoid using the ternary operator
 // which costs a lot for big contexts (before PHP 5.4). So, on average,
 // a function call is cheaper.
@@ -714,8 +773,10 @@
 /* used internally */
 function twig_in_filter($value, $compare)
 {
+    $strict = is_object($value);
+
     if (is_array($compare)) {
-        return in_array($value, $compare);
+        return in_array($value, $compare, $strict);
     } elseif (is_string($compare)) {
         if (!strlen((string) $value)) {
             return empty($compare);
@@ -723,7 +784,7 @@
 
         return false !== strpos($compare, (string) $value);
     } elseif (is_object($compare) && $compare instanceof Traversable) {
-        return in_array($value, iterator_to_array($compare, false));
+        return in_array($value, iterator_to_array($compare, false), $strict);
     }
 
     return false;
@@ -734,11 +795,11 @@
  *
  * @param Twig_Environment $env        A Twig_Environment instance
  * @param string           $string     The value to be escaped
- * @param string           $type       The escaping strategy
+ * @param string           $strategy   The escaping strategy
  * @param string           $charset    The charset
  * @param Boolean          $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
  */
-function twig_escape_filter(Twig_Environment $env, $string, $type = 'html', $charset = null, $autoescape = false)
+function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
 {
     if ($autoescape && is_object($string) && $string instanceof Twig_Markup) {
         return $string;
@@ -754,7 +815,7 @@
 
     $string = (string) $string;
 
-    switch ($type) {
+    switch ($strategy) {
         case 'js':
             // escape all non-alphanumeric characters
             // into their \xHH or \uHHHH representations
@@ -762,10 +823,12 @@
                 $string = twig_convert_encoding($string, 'UTF-8', $charset);
             }
 
-            if (null === $string = preg_replace_callback('#[^\p{L}\p{N} ]#u', '_twig_escape_js_callback', $string)) {
+            if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
                 throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
             }
 
+            $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);
+
             if ('UTF-8' != $charset) {
                 $string = twig_convert_encoding($string, $charset, 'UTF-8');
             }
@@ -772,12 +835,46 @@
 
             return $string;
 
+        case 'css':
+            if ('UTF-8' != $charset) {
+                $string = twig_convert_encoding($string, 'UTF-8', $charset);
+            }
+
+            if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
+                throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
+            }
+
+            $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);
+
+            if ('UTF-8' != $charset) {
+                $string = twig_convert_encoding($string, $charset, 'UTF-8');
+            }
+
+            return $string;
+
+        case 'html_attr':
+            if ('UTF-8' != $charset) {
+                $string = twig_convert_encoding($string, 'UTF-8', $charset);
+            }
+
+            if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
+                throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
+            }
+
+            $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);
+
+            if ('UTF-8' != $charset) {
+                $string = twig_convert_encoding($string, $charset, 'UTF-8');
+            }
+
+            return $string;
+
         case 'html':
             // see http://php.net/htmlspecialchars
 
             // Using a static variable to avoid initializing the array
             // each time the function is called. Moving the declaration on the
-            // top of the function slow downs other escaping types.
+            // top of the function slow downs other escaping strategies.
             static $htmlspecialcharsCharsets = array(
                 'iso-8859-1' => true, 'iso8859-1' => true,
                 'iso-8859-15' => true, 'iso8859-15' => true,
@@ -804,8 +901,15 @@
 
             return twig_convert_encoding($string, $charset, 'UTF-8');
 
+        case 'url':
+            if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+                return str_replace('%7E', '~', rawurlencode($string));
+            }
+
+            return rawurlencode($string);
+
         default:
-            throw new Twig_Error_Runtime(sprintf('Invalid escape type "%s".', $type));
+            throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: html, js, url, css, and html_attr).', $strategy));
     }
 }
 
@@ -823,15 +927,15 @@
     return array('html');
 }
 
-if (function_exists('iconv')) {
+if (function_exists('mb_convert_encoding')) {
     function twig_convert_encoding($string, $to, $from)
     {
-        return iconv($from, $to, $string);
+        return mb_convert_encoding($string, $to, $from);
     }
-} elseif (function_exists('mb_convert_encoding')) {
+} elseif (function_exists('iconv')) {
     function twig_convert_encoding($string, $to, $from)
     {
-        return mb_convert_encoding($string, $to, $from);
+        return iconv($from, $to, $string);
     }
 } else {
     function twig_convert_encoding($string, $to, $from)
@@ -846,15 +950,91 @@
 
     // \xHH
     if (!isset($char[1])) {
-        return '\\x'.substr('00'.bin2hex($char), -2);
+        return '\\x'.strtoupper(substr('00'.bin2hex($char), -2));
     }
 
     // \uHHHH
     $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
 
-    return '\\u'.substr('0000'.bin2hex($char), -4);
+    return '\\u'.strtoupper(substr('0000'.bin2hex($char), -4));
 }
 
+function _twig_escape_css_callback($matches)
+{
+    $char = $matches[0];
+
+    // \xHH
+    if (!isset($char[1])) {
+        $hex = ltrim(strtoupper(bin2hex($char)), '0');
+        if (0 === strlen($hex)) {
+            $hex = '0';
+        }
+
+        return '\\'.$hex.' ';
+    }
+
+    // \uHHHH
+    $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
+
+    return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' ';
+}
+
+/**
+ * This function is adapted from code coming from Zend Framework.
+ *
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ */
+function _twig_escape_html_attr_callback($matches)
+{
+    /*
+     * While HTML supports far more named entities, the lowest common denominator
+     * has become HTML5's XML Serialisation which is restricted to the those named
+     * entities that XML supports. Using HTML entities would result in this error:
+     *     XML Parsing Error: undefined entity
+     */
+    static $entityMap = array(
+        34 => 'quot', /* quotation mark */
+        38 => 'amp',  /* ampersand */
+        60 => 'lt',   /* less-than sign */
+        62 => 'gt',   /* greater-than sign */
+    );
+
+    $chr = $matches[0];
+    $ord = ord($chr);
+
+    /**
+     * The following replaces characters undefined in HTML with the
+     * hex entity for the Unicode replacement character.
+     */
+    if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) {
+        return '&#xFFFD;';
+    }
+
+    /**
+     * Check if the current character to escape has a name entity we should
+     * replace it with while grabbing the hex value of the character.
+     */
+    if (strlen($chr) == 1) {
+        $hex = strtoupper(substr('00'.bin2hex($chr), -2));
+    } else {
+        $chr = twig_convert_encoding($chr, 'UTF-16BE', 'UTF-8');
+        $hex = strtoupper(substr('0000'.bin2hex($chr), -4));
+    }
+
+    $int = hexdec($hex);
+    if (array_key_exists($int, $entityMap)) {
+        return sprintf('&%s;', $entityMap[$int]);
+    }
+
+    /**
+     * Per OWASP recommendations, we'll use hex entities for any other
+     * characters where a named entity does not exist.
+     */
+
+    return sprintf('&#x%s;', $hex);
+}
+
 // add multibyte extensions if possible
 if (function_exists('mb_get_info')) {
     /**
@@ -940,8 +1120,7 @@
     }
 }
 // and byte fallback
-else
-{
+else {
     /**
      * Returns the length of a variable.
      *
Index: branches/2.8.x/wb/include/Twig/NodeVisitorInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/NodeVisitorInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/NodeVisitorInterface.php	(revision 1852)
@@ -25,7 +25,7 @@
      *
      * @return Twig_NodeInterface The modified node
      */
-    function enterNode(Twig_NodeInterface $node, Twig_Environment $env);
+    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env);
 
     /**
      * Called after child nodes are visited.
@@ -35,7 +35,7 @@
      *
      * @return Twig_NodeInterface The modified node
      */
-    function leaveNode(Twig_NodeInterface $node, Twig_Environment $env);
+    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env);
 
     /**
      * Returns the priority for this visitor.
@@ -44,5 +44,5 @@
      *
      * @return integer The priority level
      */
-    function getPriority();
+    public function getPriority();
 }
Index: branches/2.8.x/wb/include/Twig/Error.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Error.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Error.php	(revision 1852)
@@ -12,6 +12,23 @@
 /**
  * Twig base exception.
  *
+ * This exception class and its children must only be used when
+ * an error occurs during the loading of a template, when a syntax error
+ * is detected in a template, or when rendering a template. Other
+ * errors must use regular PHP exception classes (like when the template
+ * cache directory is not writable for instance).
+ *
+ * To help debugging template issues, this class tracks the original template
+ * name and line where the error occurred.
+ *
+ * Whenever possible, you must set these information (original template name
+ * and line number) yourself by passing them to the constructor. If some or all
+ * these information are not available from where you throw the exception, then
+ * this class will guess them automatically (when the line number is set to -1
+ * and/or the filename is set to null). As this is a costly operation, this
+ * can be disabled by passing false for both the filename and the line number
+ * when creating a new instance of this class.
+ *
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
  */
@@ -25,6 +42,15 @@
     /**
      * Constructor.
      *
+     * Set both the line number and the filename to false to
+     * disable automatic guessing of the original template name
+     * and line number.
+     *
+     * Set the line number to -1 to enable its automatic guessing.
+     * Set the filename to null to enable its automatic guessing.
+     *
+     * By default, automatic guessing is enabled.
+     *
      * @param string    $message  The error message
      * @param integer   $lineno   The template line where the error occurred
      * @param string    $filename The template file name where the error occurred
@@ -105,13 +131,21 @@
         $this->updateRepr();
     }
 
+    public function guess()
+    {
+        $this->guessTemplateInfo();
+        $this->updateRepr();
+    }
+
     /**
      * For PHP < 5.3.0, provides access to the getPrevious() method.
      *
-     * @param  string $method    The method name
-     * @param  array  $arguments The parameters to be passed to the method
+     * @param string $method    The method name
+     * @param array  $arguments The parameters to be passed to the method
      *
      * @return Exception The previous exception or null
+     *
+     * @throws BadMethodCallException
      */
     public function __call($method, $arguments)
     {
@@ -132,7 +166,7 @@
             $dot = true;
         }
 
-        if (null !== $this->filename) {
+        if ($this->filename) {
             if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
                 $filename = sprintf('"%s"', $this->filename);
             } else {
@@ -141,7 +175,7 @@
             $this->message .= sprintf(' in %s', $filename);
         }
 
-        if ($this->lineno >= 0) {
+        if ($this->lineno && $this->lineno >= 0) {
             $this->message .= sprintf(' at line %d', $this->lineno);
         }
 
@@ -155,15 +189,17 @@
         $template = null;
         foreach (debug_backtrace() as $trace) {
             if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
-                $template = $trace['object'];
-
-                // update template filename
-                if (null === $this->filename) {
-                    $this->filename = $template->getTemplateName();
+                if (null === $this->filename || $this->filename == $trace['object']->getTemplateName()) {
+                    $template = $trace['object'];
                 }
             }
         }
 
+        // update template filename
+        if (null !== $template && null === $this->filename) {
+            $this->filename = $template->getTemplateName();
+        }
+
         if (null === $template || $this->lineno > -1) {
             return;
         }
@@ -172,7 +208,7 @@
         $file = $r->getFileName();
 
         $exceptions = array($e = $this);
-        while (method_exists($e, 'getPrevious') && $e = $e->getPrevious()) {
+        while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) {
             $exceptions[] = $e;
         }
 
Index: branches/2.8.x/wb/include/Twig/CompilerInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/CompilerInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/CompilerInterface.php	(revision 1852)
@@ -20,11 +20,11 @@
     /**
      * Compiles a node.
      *
-     * @param  Twig_NodeInterface $node The node to compile
+     * @param Twig_NodeInterface $node The node to compile
      *
      * @return Twig_CompilerInterface The current compiler instance
      */
-    function compile(Twig_NodeInterface $node);
+    public function compile(Twig_NodeInterface $node);
 
     /**
      * Gets the current PHP code after compilation.
@@ -31,5 +31,5 @@
      *
      * @return string The PHP code
      */
-    function getSource();
+    public function getSource();
 }
Index: branches/2.8.x/wb/include/Twig/TokenStream.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenStream.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenStream.php	(revision 1852)
@@ -45,6 +45,11 @@
         return implode("\n", $this->tokens);
     }
 
+    public function injectTokens(array $tokens)
+    {
+        $this->tokens = array_merge(array_slice($this->tokens, 0, $this->current), $tokens, array_slice($this->tokens, $this->current));
+    }
+
     /**
      * Sets the pointer to the next token and returns the old one.
      *
@@ -53,7 +58,7 @@
     public function next()
     {
         if (!isset($this->tokens[++$this->current])) {
-            throw new Twig_Error_Syntax('Unexpected end of template', -1, $this->filename);
+            throw new Twig_Error_Syntax('Unexpected end of template', $this->token[$this->current - 1]->getLine(), $this->filename);
         }
 
         return $this->tokens[$this->current - 1];
@@ -92,7 +97,7 @@
     public function look($number = 1)
     {
         if (!isset($this->tokens[$this->current + $number])) {
-            throw new Twig_Error_Syntax('Unexpected end of template', -1, $this->filename);
+            throw new Twig_Error_Syntax('Unexpected end of template', $this->token[$this->current + $number - 1]->getLine(), $this->filename);
         }
 
         return $this->tokens[$this->current + $number];
Index: branches/2.8.x/wb/include/Twig/TemplateInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TemplateInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TemplateInterface.php	(revision 1852)
@@ -28,7 +28,7 @@
      *
      * @return string The rendered template
      */
-    function render(array $context);
+    public function render(array $context);
 
     /**
      * Displays the template with the given context.
@@ -36,7 +36,7 @@
      * @param array $context An array of parameters to pass to the template
      * @param array $blocks  An array of blocks to pass to the template
      */
-    function display(array $context, array $blocks = array());
+    public function display(array $context, array $blocks = array());
 
     /**
      * Returns the bound environment for this template.
@@ -43,5 +43,5 @@
      *
      * @return Twig_Environment The current environment
      */
-    function getEnvironment();
+    public function getEnvironment();
 }
Index: branches/2.8.x/wb/include/Twig/Function/Method.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Function/Method.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Function/Method.php	(revision 1852)
@@ -18,7 +18,8 @@
  */
 class Twig_Function_Method extends Twig_Function
 {
-    protected $extension, $method;
+    protected $extension;
+    protected $method;
 
     public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
     {
Index: branches/2.8.x/wb/include/Twig/Function/Node.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Function/Node.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Function/Node.php	(revision 1852)
@@ -15,7 +15,7 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
  */
-class Twig_Function_Node extends Twig_Filter
+class Twig_Function_Node extends Twig_Function
 {
     protected $class;
 
Index: branches/2.8.x/wb/include/Twig/Autoloader.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Autoloader.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Autoloader.php	(revision 1852)
@@ -20,7 +20,7 @@
     /**
      * Registers Twig_Autoloader as an SPL autoloader.
      */
-    static public function register()
+    public static function register()
     {
         ini_set('unserialize_callback_func', 'spl_autoload_call');
         spl_autoload_register(array(new self, 'autoload'));
@@ -29,11 +29,9 @@
     /**
      * Handles autoloading of classes.
      *
-     * @param  string  $class  A class name.
-     *
-     * @return boolean Returns true if the class has been loaded
+     * @param string $class A class name.
      */
-    static public function autoload($class)
+    public static function autoload($class)
     {
         if (0 !== strpos($class, 'Twig')) {
             return;
Index: branches/2.8.x/wb/include/Twig/TokenParserBroker.php
===================================================================
--- branches/2.8.x/wb/include/Twig/TokenParserBroker.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/TokenParserBroker.php	(revision 1852)
@@ -32,13 +32,13 @@
     {
         foreach ($parsers as $parser) {
             if (!$parser instanceof Twig_TokenParserInterface) {
-                throw new Twig_Error('$parsers must a an array of Twig_TokenParserInterface');
+                throw new LogicException('$parsers must a an array of Twig_TokenParserInterface');
             }
             $this->parsers[$parser->getTag()] = $parser;
         }
         foreach ($brokers as $broker) {
             if (!$broker instanceof Twig_TokenParserBrokerInterface) {
-                throw new Twig_Error('$brokers must a an array of Twig_TokenParserBrokerInterface');
+                throw new LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface');
             }
             $this->brokers[] = $broker;
         }
Index: branches/2.8.x/wb/include/Twig/Error/Loader.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Error/Loader.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Error/Loader.php	(revision 1852)
@@ -12,9 +12,21 @@
 /**
  * Exception thrown when an error occurs during template loading.
  *
+ * Automatic template information guessing is always turned off as
+ * if a template cannot be loaded, there is nothing to guess.
+ * However, when a template is loaded from another one, then, we need
+ * to find the current context and this is automatically done by
+ * Twig_Template::displayWithErrorHandling().
+ *
+ * This strategy makes Twig_Environment::resolveTemplate() much faster.
+ *
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
  */
 class Twig_Error_Loader extends Twig_Error
 {
+    public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
+    {
+        parent::__construct($message, false, false, $previous);
+    }
 }
Index: branches/2.8.x/wb/include/Twig/Environment.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Environment.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Environment.php	(revision 1852)
@@ -17,7 +17,7 @@
  */
 class Twig_Environment
 {
-    const VERSION = '1.7.0';
+    const VERSION = '1.11.1';
 
     protected $charset;
     protected $loader;
@@ -50,9 +50,8 @@
      *
      * Available options:
      *
-     *  * debug: When set to `true`, the generated templates have a __toString()
-     *           method that you can use to display the generated nodes (default to
-     *           false).
+     *  * debug: When set to true, it automatically set "auto_reload" to true as
+     *           well (default to false).
      *
      *  * charset: The charset used by the templates (default to utf-8).
      *
@@ -60,7 +59,7 @@
      *                         templates (default to Twig_Template).
      *
      *  * cache: An absolute path where to store the compiled templates, or
-     *           false to disable compilation cache (default)
+     *           false to disable compilation cache (default).
      *
      *  * auto_reload: Whether to reload the template is the original source changed.
      *                 If you don't provide the auto_reload option, it will be
@@ -69,14 +68,18 @@
      *  * strict_variables: Whether to ignore invalid variables in templates
      *                      (default to false).
      *
-     *  * autoescape: Whether to enable auto-escaping (default to true);
+     *  * autoescape: Whether to enable auto-escaping (default to html):
+     *                  * false: disable auto-escaping
+     *                  * true: equivalent to html
+     *                  * html, js: set the autoescaping to one of the supported strategies
+     *                  * PHP callback: a PHP callback that returns an escaping strategy based on the template "filename"
      *
      *  * optimizations: A flag that indicates which optimizations to apply
      *                   (default to -1 which means that all optimizations are enabled;
-     *                   set it to 0 to disable)
+     *                   set it to 0 to disable).
      *
-     * @param Twig_LoaderInterface   $loader  A Twig_LoaderInterface instance
-     * @param array                  $options An array of options
+     * @param Twig_LoaderInterface $loader  A Twig_LoaderInterface instance
+     * @param array                $options An array of options
      */
     public function __construct(Twig_LoaderInterface $loader = null, $options = array())
     {
@@ -89,7 +92,7 @@
             'charset'             => 'UTF-8',
             'base_template_class' => 'Twig_Template',
             'strict_variables'    => false,
-            'autoescape'          => true,
+            'autoescape'          => 'html',
             'cache'               => false,
             'auto_reload'         => null,
             'optimizations'       => -1,
@@ -101,7 +104,7 @@
         $this->autoReload         = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
         $this->extensions         = array(
             'core'      => new Twig_Extension_Core(),
-            'escaper'   => new Twig_Extension_Escaper((bool) $options['autoescape']),
+            'escaper'   => new Twig_Extension_Escaper($options['autoescape']),
             'optimizer' => new Twig_Extension_Optimizer($options['optimizations']),
         );
         $this->strictVariables    = (bool) $options['strict_variables'];
@@ -109,6 +112,14 @@
         $this->setCache($options['cache']);
         $this->functionCallbacks = array();
         $this->filterCallbacks = array();
+        $this->staging = array(
+            'functions'     => array(),
+            'filters'       => array(),
+            'tests'         => array(),
+            'token_parsers' => array(),
+            'visitors'      => array(),
+            'globals'       => array(),
+        );
     }
 
     /**
@@ -251,13 +262,14 @@
     /**
      * Gets the template class associated with the given string.
      *
-     * @param string $name The name for which to calculate the template class name
+     * @param string  $name  The name for which to calculate the template class name
+     * @param integer $index The index if it is an embedded template
      *
      * @return string The template class name
      */
-    public function getTemplateClass($name)
+    public function getTemplateClass($name, $index = null)
     {
-        return $this->templateClassPrefix.md5($this->loader->getCacheKey($name));
+        return $this->templateClassPrefix.md5($this->loader->getCacheKey($name)).(null === $index ? '' : '_'.$index);
     }
 
     /**
@@ -297,13 +309,14 @@
     /**
      * Loads a template by name.
      *
-     * @param  string  $name  The template name
+     * @param string  $name  The template name
+     * @param integer $index The index if it is an embedded template
      *
      * @return Twig_TemplateInterface A template instance representing the given template name
      */
-    public function loadTemplate($name)
+    public function loadTemplate($name, $index = null)
     {
-        $cls = $this->getTemplateClass($name);
+        $cls = $this->getTemplateClass($name, $index);
 
         if (isset($this->loadedTemplates[$cls])) {
             return $this->loadedTemplates[$cls];
@@ -692,13 +705,13 @@
 
             foreach ($this->getExtensions() as $extension) {
                 $parsers = $extension->getTokenParsers();
-                foreach($parsers as $parser) {
+                foreach ($parsers as $parser) {
                     if ($parser instanceof Twig_TokenParserInterface) {
                         $this->parsers->addTokenParser($parser);
                     } elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
                         $this->parsers->addTokenParserBroker($parser);
                     } else {
-                        throw new Twig_Error_Runtime('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
+                        throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
                     }
                 }
             }
@@ -745,10 +758,13 @@
     public function getNodeVisitors()
     {
         if (null === $this->visitors) {
-            $this->visitors = isset($this->staging['visitors']) ? $this->staging['visitors'] : array();
             foreach ($this->getExtensions() as $extension) {
-                $this->visitors = array_merge($this->visitors, $extension->getNodeVisitors());
+                foreach ($extension->getNodeVisitors() as $visitor) {
+                    $this->addNodeVisitor($visitor);
+                }
             }
+
+            $this->visitors = $this->staging['visitors'];
         }
 
         return $this->visitors;
@@ -825,10 +841,13 @@
     public function getFilters()
     {
         if (null === $this->filters) {
-            $this->filters = isset($this->staging['filters']) ? $this->staging['filters'] : array();
             foreach ($this->getExtensions() as $extension) {
-                $this->filters = array_merge($this->filters, $extension->getFilters());
+                foreach ($extension->getFilters() as $name => $filter) {
+                    $this->addFilter($name, $filter);
+                }
             }
+
+            $this->filters = $this->staging['filters'];
         }
 
         return $this->filters;
@@ -854,10 +873,13 @@
     public function getTests()
     {
         if (null === $this->tests) {
-            $this->tests = isset($this->staging['tests']) ? $this->staging['tests'] : array();
             foreach ($this->getExtensions() as $extension) {
-                $this->tests = array_merge($this->tests, $extension->getTests());
+                foreach ($extension->getTests() as $name => $test) {
+                    $this->addTest($name, $test);
+                }
             }
+
+            $this->tests = $this->staging['tests'];
         }
 
         return $this->tests;
@@ -934,10 +956,13 @@
     public function getFunctions()
     {
         if (null === $this->functions) {
-            $this->functions = isset($this->staging['functions']) ? $this->staging['functions'] : array();
             foreach ($this->getExtensions() as $extension) {
-                $this->functions = array_merge($this->functions, $extension->getFunctions());
+                foreach ($extension->getFunctions() as $name => $function) {
+                    $this->addFunction($name, $function);
+                }
             }
+
+            $this->functions = $this->staging['functions'];
         }
 
         return $this->functions;
@@ -1069,12 +1094,12 @@
         if (false !== @file_put_contents($tmpFile, $content)) {
             // rename does not work on Win32 before 5.2.6
             if (@rename($tmpFile, $file) || (@copy($tmpFile, $file) && unlink($tmpFile))) {
-                @chmod($file, 0644);
+                @chmod($file, 0666 & ~umask());
 
                 return;
             }
         }
 
-        throw new Twig_Error_Runtime(sprintf('Failed to write cache file "%s".', $file));
+        throw new RuntimeException(sprintf('Failed to write cache file "%s".', $file));
     }
 }
Index: branches/2.8.x/wb/include/Twig/FunctionInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/FunctionInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/FunctionInterface.php	(revision 1852)
@@ -23,15 +23,15 @@
      *
      * @return string The PHP code for the function
      */
-    function compile();
+    public function compile();
 
-    function needsEnvironment();
+    public function needsEnvironment();
 
-    function needsContext();
+    public function needsContext();
 
-    function getSafe(Twig_Node $filterArgs);
+    public function getSafe(Twig_Node $filterArgs);
 
-    function setArguments($arguments);
+    public function setArguments($arguments);
 
-    function getArguments();
+    public function getArguments();
 }
Index: branches/2.8.x/wb/include/Twig/Compiler.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Compiler.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Compiler.php	(revision 1852)
@@ -25,6 +25,7 @@
     protected $debugInfo;
     protected $sourceOffset;
     protected $sourceLine;
+    protected $filename;
 
     /**
      * Constructor.
@@ -37,6 +38,11 @@
         $this->debugInfo = array();
     }
 
+    public function getFilename()
+    {
+        return $this->filename;
+    }
+
     /**
      * Returns the environment instance related to this compiler.
      *
@@ -70,9 +76,14 @@
         $this->lastLine = null;
         $this->source = '';
         $this->sourceOffset = 0;
-        $this->sourceLine = 0;
+        // source code starts at 1 (as we then increment it when we encounter new lines)
+        $this->sourceLine = 1;
         $this->indentation = $indentation;
 
+        if ($node instanceof Twig_Node_Module) {
+            $this->filename = $node->getAttribute('filename');
+        }
+
         $node->compile($this);
 
         return $this;
@@ -92,7 +103,7 @@
     /**
      * Adds a raw string to the compiled code.
      *
-     * @param  string $string The string
+     * @param string $string The string
      *
      * @return Twig_Compiler The current compiler instance
      */
@@ -119,6 +130,11 @@
         return $this;
     }
 
+    /**
+     * Appends an indentation to the current PHP code after compilation.
+     *
+     * @return Twig_Compiler The current compiler instance
+     */
     public function addIndentation()
     {
         $this->source .= str_repeat(' ', $this->indentation * 4);
@@ -129,7 +145,7 @@
     /**
      * Adds a quoted string to the compiled code.
      *
-     * @param  string $value The string
+     * @param string $value The string
      *
      * @return Twig_Compiler The current compiler instance
      */
@@ -143,7 +159,7 @@
     /**
      * Returns a PHP representation of a given value.
      *
-     * @param  mixed $value The value to convert
+     * @param mixed $value The value to convert
      *
      * @return Twig_Compiler The current compiler instance
      */
@@ -192,12 +208,21 @@
     public function addDebugInfo(Twig_NodeInterface $node)
     {
         if ($node->getLine() != $this->lastLine) {
-            $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
+            $this->write("// line {$node->getLine()}\n");
+
+            // when mbstring.func_overload is set to 2
+            // mb_substr_count() replaces substr_count()
+            // but they have different signatures!
+            if (((int) ini_get('mbstring.func_overload')) & 2) {
+                // this is much slower than the "right" version
+                $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
+            } else {
+                $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
+            }
             $this->sourceOffset = strlen($this->source);
             $this->debugInfo[$this->sourceLine] = $node->getLine();
 
             $this->lastLine = $node->getLine();
-            $this->write("// line {$node->getLine()}\n");
         }
 
         return $this;
@@ -231,12 +256,13 @@
      */
     public function outdent($step = 1)
     {
+        // can't outdent by more steps that the current indentation level
+        if ($this->indentation < $step) {
+            throw new LogicException('Unable to call outdent() as the indentation would become negative');
+        }
+
         $this->indentation -= $step;
 
-        if ($this->indentation < 0) {
-            throw new Twig_Error('Unable to call outdent() as the indentation would become negative');
-        }
-
         return $this;
     }
 }
Index: branches/2.8.x/wb/include/Twig/ExpressionParser.php
===================================================================
--- branches/2.8.x/wb/include/Twig/ExpressionParser.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/ExpressionParser.php	(revision 1852)
@@ -158,7 +158,7 @@
                 } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
                     $node = $this->parseHashExpression();
                 } else {
-                    throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine());
+                    throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine(), $this->parser->getFilename());
                 }
         }
 
@@ -252,7 +252,7 @@
             } else {
                 $current = $stream->getCurrent();
 
-                throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType(), $current->getLine()), $current->getValue()), $current->getLine());
+                throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType(), $current->getLine()), $current->getValue()), $current->getLine(), $this->parser->getFilename());
             }
 
             $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
@@ -291,11 +291,11 @@
         switch ($name) {
             case 'parent':
                 if (!count($this->parser->getBlockStack())) {
-                    throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line);
+                    throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
                 }
 
                 if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
-                    throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line);
+                    throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line, $this->parser->getFilename());
                 }
 
                 return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
@@ -303,12 +303,12 @@
                 return new Twig_Node_Expression_BlockReference($args->getNode(0), false, $line);
             case 'attribute':
                 if (count($args) < 2) {
-                    throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line);
+                    throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename());
                 }
 
                 return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_TemplateInterface::ANY_CALL, $line);
             default:
-                if (null !== $alias = $this->parser->getImportedFunction($name)) {
+                if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
                     $arguments = new Twig_Node_Expression_Array(array(), $line);
                     foreach ($args as $n) {
                         $arguments->addElement($n);
@@ -351,7 +351,7 @@
                     }
                 }
             } else {
-                throw new Twig_Error_Syntax('Expected name or number', $lineno);
+                throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
             }
         } else {
             $type = Twig_TemplateInterface::ARRAY_CALL;
@@ -380,6 +380,13 @@
             $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
         }
 
+        if ($node instanceof Twig_Node_Expression_Name && null !== $alias = $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
+            $node = new Twig_Node_Expression_MethodCall($node, 'get'.$arg->getAttribute('value'), $arguments, $lineno);
+            $node->setAttribute('safe', true);
+
+            return $node;
+        }
+
         return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno);
     }
 
@@ -439,7 +446,7 @@
         while (true) {
             $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
             if (in_array($token->getValue(), array('true', 'false', 'none'))) {
-                throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine());
+                throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename());
             }
             $targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine());
 
Index: branches/2.8.x/wb/include/Twig/ParserInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/ParserInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/ParserInterface.php	(revision 1852)
@@ -20,9 +20,9 @@
     /**
      * Converts a token stream to a node tree.
      *
-     * @param  Twig_TokenStream $stream A token stream instance
+     * @param Twig_TokenStream $stream A token stream instance
      *
      * @return Twig_Node_Module A node tree
      */
-    function parse(Twig_TokenStream $stream);
+    public function parse(Twig_TokenStream $stream);
 }
Index: branches/2.8.x/wb/include/Twig/Lexer.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Lexer.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Lexer.php	(revision 1852)
@@ -30,6 +30,8 @@
     protected $filename;
     protected $options;
     protected $regexes;
+    protected $position;
+    protected $positions;
 
     const STATE_DATA            = 0;
     const STATE_BLOCK           = 1;
@@ -73,8 +75,8 @@
     /**
      * Tokenizes a source code.
      *
-     * @param  string $code     The source code
-     * @param  string $filename A unique identifier for the source code
+     * @param string $code     The source code
+     * @param string $filename A unique identifier for the source code
      *
      * @return Twig_TokenStream A token stream instance
      */
@@ -330,8 +332,6 @@
 
             $this->popState();
             ++$this->cursor;
-
-            return;
         }
     }
 
Index: branches/2.8.x/wb/include/Twig/DOC/LICENSE
===================================================================
--- branches/2.8.x/wb/include/Twig/DOC/LICENSE	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/DOC/LICENSE	(revision 1852)
@@ -0,0 +1,31 @@
+Copyright (c) 2009 by the Twig Team, see AUTHORS for more details.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * The names of the contributors may not be used to endorse or
+      promote products derived from this software without specific
+      prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: branches/2.8.x/wb/include/Twig/DOC/AUTHORS
===================================================================
--- branches/2.8.x/wb/include/Twig/DOC/AUTHORS	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/DOC/AUTHORS	(revision 1852)
@@ -0,0 +1,9 @@
+Twig is written and maintained by the Twig Team:
+
+Lead Developer:
+
+- Fabien Potencier <fabien.potencier@symfony-project.org>
+
+Project Founder:
+
+- Armin Ronacher <armin.ronacher@active-4.com>
Index: branches/2.8.x/wb/include/Twig/DOC/CHANGELOG
===================================================================
--- branches/2.8.x/wb/include/Twig/DOC/CHANGELOG	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/DOC/CHANGELOG	(revision 1852)
@@ -0,0 +1,579 @@
+* 1.11.1 (2012-11-11)
+
+ * fixed debug info line numbering (was off by 2)
+ * fixed escaping when calling a macro inside another one (regression introduced in 1.9.1)
+ * optimized variable access on PHP 5.4
+ * fixed a crash of the C extension when an exception was thrown from a macro called without being imported (using _self.XXX)
+
+* 1.11.0 (2012-11-07)
+
+ * fixed macro compilation when a variable name is a PHP reserved keyword
+ * changed the date filter behavior to always apply the default timezone, except if false is passed as the timezone
+ * fixed bitwise operator precedences
+ * added the template_from_string function
+ * fixed default timezone usage for the date function
+ * optimized the way Twig exceptions are managed (to make them faster)
+ * added Twig_ExistsLoaderInterface (implementing this interface in your loader make the chain loader much faster)
+
+* 1.10.3 (2012-10-19)
+
+ * fixed wrong template location in some error messages
+ * reverted a BC break introduced in 1.10.2
+ * added a split filter
+
+* 1.10.2 (2012-10-15)
+
+ * fixed macro calls on PHP 5.4
+
+* 1.10.1 (2012-10-15)
+
+ * made a speed optimization to macro calls when imported via the "import" tag
+ * fixed C extension compilation on Windows
+ * fixed a segfault in the C extension when using DateTime objects
+
+* 1.10.0 (2012-09-28)
+
+ * extracted functional tests framework to make it reusable for third-party extensions
+ * added namespaced templates support in Twig_Loader_Filesystem
+ * added Twig_Loader_Filesystem::prependPath()
+ * fixed an error when a token parser pass a closure as a test to the subparse() method
+
+* 1.9.2 (2012-08-25)
+
+ * fixed the in operator for objects that contain circular references
+ * fixed the C extension when accessing a public property of an object implementing the \ArrayAccess interface
+
+* 1.9.1 (2012-07-22)
+
+ * optimized macro calls when auto-escaping is on
+ * fixed wrong parent class for Twig_Function_Node
+ * made Twig_Loader_Chain more explicit about problems
+
+* 1.9.0 (2012-07-13)
+
+ * made the parsing independent of the template loaders
+ * fixed exception trace when an error occurs when rendering a child template
+ * added escaping strategies for CSS, URL, and HTML attributes
+ * fixed nested embed tag calls
+ * added the date_modify filter
+
+* 1.8.3 (2012-06-17)
+
+ * fixed paths in the filesystem loader when passing a path that ends with a slash or a backslash
+ * fixed escaping when a project defines a function named html or js
+ * fixed chmod mode to apply the umask correctly
+
+* 1.8.2 (2012-05-30)
+
+ * added the abs filter
+ * fixed a regression when using a number in template attributes
+ * fixed compiler when mbstring.func_overload is set to 2
+ * fixed DateTimeZone support in date filter
+
+* 1.8.1 (2012-05-17)
+
+ * fixed a regression when dealing with SimpleXMLElement instances in templates
+ * fixed "is_safe" value for the "dump" function when "html_errors" is not defined in php.ini
+ * switched to use mbstring whenever possible instead of iconv (you might need to update your encoding as mbstring and iconv encoding names sometimes differ)
+
+* 1.8.0 (2012-05-08)
+
+ * enforced interface when adding tests, filters, functions, and node visitors from extensions
+ * fixed a side-effect of the date filter where the timezone might be changed
+ * simplified usage of the autoescape tag; the only (optional) argument is now the escaping strategy or false (with a BC layer)
+ * added a way to dynamically change the auto-escaping strategy according to the template "filename"
+ * changed the autoescape option to also accept a supported escaping strategy (for BC, true is equivalent to html)
+ * added an embed tag
+
+* 1.7.0 (2012-04-24)
+
+ * fixed a PHP warning when using CIFS
+ * fixed template line number in some exceptions
+ * added an iterable test
+ * added an error when defining two blocks with the same name in a template
+ * added the preserves_safety option for filters
+ * fixed a PHP notice when trying to access a key on a non-object/array variable
+ * enhanced error reporting when the template file is an instance of SplFileInfo
+ * added Twig_Environment::mergeGlobals()
+ * added compilation checks to avoid misuses of the sandbox tag
+ * fixed filesystem loader freshness logic for high traffic websites
+ * fixed random function when charset is null
+
+* 1.6.5 (2012-04-11)
+
+ * fixed a regression when a template only extends another one without defining any blocks
+
+* 1.6.4 (2012-04-02)
+
+ * fixed PHP notice in Twig_Error::guessTemplateLine() introduced in 1.6.3
+ * fixed performance when compiling large files
+ * optimized parent template creation when the template does not use dynamic inheritance
+
+* 1.6.3 (2012-03-22)
+
+ * fixed usage of Z_ADDREF_P for PHP 5.2 in the C extension
+ * fixed compilation of numeric values used in templates when using a locale where the decimal separator is not a dot
+ * made the strategy used to guess the real template file name and line number in exception messages much faster and more accurate
+
+* 1.6.2 (2012-03-18)
+
+ * fixed sandbox mode when used with inheritance
+ * added preserveKeys support for the slice filter
+ * fixed the date filter when a DateTime instance is passed with a specific timezone
+ * added a trim filter
+
+* 1.6.1 (2012-02-29)
+
+ * fixed Twig C extension
+ * removed the creation of Twig_Markup instances when not needed
+ * added a way to set the default global timezone for dates
+ * fixed the slice filter on strings when the length is not specified
+ * fixed the creation of the cache directory in case of a race condition
+
+* 1.6.0 (2012-02-04)
+
+ * fixed raw blocks when used with the whitespace trim option
+ * made a speed optimization to macro calls when imported via the "from" tag
+ * fixed globals, parsers, visitors, filters, tests, and functions management in Twig_Environment when a new one or new extension is added
+ * fixed the attribute function when passing arguments
+ * added slice notation support for the [] operator (syntactic sugar for the slice operator)
+ * added a slice filter
+ * added string support for the reverse filter
+ * fixed the empty test and the length filter for Twig_Markup instances
+ * added a date function to ease date comparison
+ * fixed unary operators precedence
+ * added recursive parsing support in the parser
+ * added string and integer handling for the random function
+
+* 1.5.1 (2012-01-05)
+
+ * fixed a regression when parsing strings
+
+* 1.5.0 (2012-01-04)
+
+ * added Traversable objects support for the join filter
+
+* 1.5.0-RC2 (2011-12-30)
+
+ * added a way to set the default global date interval format
+ * fixed the date filter for DateInterval instances (setTimezone() does not exist for them)
+ * refactored Twig_Template::display() to ease its extension
+ * added a number_format filter
+
+* 1.5.0-RC1 (2011-12-26)
+
+ * removed the need to quote hash keys
+ * allowed hash keys to be any expression
+ * added a do tag
+ * added a flush tag
+ * added support for dynamically named filters and functions
+ * added a dump function to help debugging templates
+ * added a nl2br filter
+ * added a random function
+ * added a way to change the default format for the date filter
+ * fixed the lexer when an operator ending with a letter ends a line
+ * added string interpolation support
+ * enhanced exceptions for unknown filters, functions, tests, and tags
+
+* 1.4.0 (2011-12-07)
+
+ * fixed lexer when using big numbers (> PHP_INT_MAX)
+ * added missing preserveKeys argument to the reverse filter
+ * fixed macros containing filter tag calls
+
+* 1.4.0-RC2 (2011-11-27)
+
+ * removed usage of Reflection in Twig_Template::getAttribute()
+ * added a C extension that can optionally replace Twig_Template::getAttribute()
+ * added negative timestamp support to the date filter
+
+* 1.4.0-RC1 (2011-11-20)
+
+ * optimized variable access when using PHP 5.4
+ * changed the precedence of the .. operator to be more consistent with languages that implements such a feature like Ruby
+ * added an Exception to Twig_Loader_Array::isFresh() method when the template does not exist to be consistent with other loaders
+ * added Twig_Function_Node to allow more complex functions to have their own Node class
+ * added Twig_Filter_Node to allow more complex filters to have their own Node class
+ * added Twig_Test_Node to allow more complex tests to have their own Node class
+ * added a better error message when a template is empty but contain a BOM
+ * fixed "in" operator for empty strings
+ * fixed the "defined" test and the "default" filter (now works with more than one call (foo.bar.foo) and for both values of the strict_variables option)
+ * changed the way extensions are loaded (addFilter/addFunction/addGlobal/addTest/addNodeVisitor/addTokenParser/addExtension can now be called in any order)
+ * added Twig_Environment::display()
+ * made the escape filter smarter when the encoding is not supported by PHP
+ * added a convert_encoding filter
+ * moved all node manipulations outside the compile() Node method
+ * made several speed optimizations
+
+* 1.3.0 (2011-10-08)
+
+no changes
+
+* 1.3.0-RC1 (2011-10-04)
+
+ * added an optimization for the parent() function
+ * added cache reloading when auto_reload is true and an extension has been modified
+ * added the possibility to force the escaping of a string already marked as safe (instance of Twig_Markup)
+ * allowed empty templates to be used as traits
+ * added traits support for the "parent" function
+
+* 1.2.0 (2011-09-13)
+
+no changes
+
+* 1.2.0-RC1 (2011-09-10)
+
+ * enhanced the exception when a tag remains unclosed
+ * added support for empty Countable objects for the "empty" test
+ * fixed algorithm that determines if a template using inheritance is valid (no output between block definitions)
+ * added better support for encoding problems when escaping a string (available as of PHP 5.4)
+ * added a way to ignore a missing template when using the "include" tag ({% include "foo" ignore missing %})
+ * added support for an array of templates to the "include" and "extends" tags ({% include ['foo', 'bar'] %})
+ * added support for bitwise operators in expressions
+ * added the "attribute" function to allow getting dynamic attributes on variables
+ * added Twig_Loader_Chain
+ * added Twig_Loader_Array::setTemplate()
+ * added an optimization for the set tag when used to capture a large chunk of static text
+ * changed name regex to match PHP one "[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*" (works for blocks, tags, functions, filters, and macros)
+ * removed the possibility to use the "extends" tag from a block
+ * added "if" modifier support to "for" loops
+
+* 1.1.2 (2011-07-30)
+
+ * fixed json_encode filter on PHP 5.2
+ * fixed regression introduced in 1.1.1 ({{ block(foo|lower) }})
+ * fixed inheritance when using conditional parents
+ * fixed compilation of templates when the body of a child template is not empty
+ * fixed output when a macro throws an exception
+ * fixed a parsing problem when a large chunk of text is enclosed in a comment tag
+ * added PHPDoc for all Token parsers and Core extension functions
+
+* 1.1.1 (2011-07-17)
+
+ * added a performance optimization in the Optimizer (also helps to lower the number of nested level calls)
+ * made some performance improvement for some edge cases
+
+* 1.1.0 (2011-06-28)
+
+ * fixed json_encode filter
+
+* 1.1.0-RC3 (2011-06-24)
+
+ * fixed method case-sensitivity when using the sandbox mode
+ * added timezone support for the date filter
+ * fixed possible security problems with NUL bytes
+
+* 1.1.0-RC2 (2011-06-16)
+
+ * added an exception when the template passed to "use" is not a string
+ * made 'a.b is defined' not throw an exception if a is not defined (in strict mode)
+ * added {% line \d+ %} directive
+
+* 1.1.0-RC1 (2011-05-28)
+
+Flush your cache after upgrading.
+
+ * fixed date filter when using a timestamp
+ * fixed the defined test for some cases
+ * fixed a parsing problem when a large chunk of text is enclosed in a raw tag
+ * added support for horizontal reuse of template blocks (see docs for more information)
+ * added whitespace control modifier to all tags (see docs for more information)
+ * added null as an alias for none (the null test is also an alias for the none test now)
+ * made TRUE, FALSE, NONE equivalent to their lowercase counterparts
+ * wrapped all compilation and runtime exceptions with Twig_Error_Runtime and added logic to guess the template name and line
+ * moved display() method to Twig_Template (generated templates should now use doDisplay() instead)
+
+* 1.0.0 (2011-03-27)
+
+ * fixed output when using mbstring
+ * fixed duplicate call of methods when using the sandbox
+ * made the charset configurable for the escape filter
+
+* 1.0.0-RC2 (2011-02-21)
+
+ * changed the way {% set %} works when capturing (the content is now marked as safe)
+ * added support for macro name in the endmacro tag
+ * make Twig_Error compatible with PHP 5.3.0 >
+ * fixed an infinite loop on some Windows configurations
+ * fixed the "length" filter for numbers
+ * fixed Template::getAttribute() as properties in PHP are case sensitive
+ * removed coupling between Twig_Node and Twig_Template
+ * fixed the ternary operator precedence rule
+
+* 1.0.0-RC1 (2011-01-09)
+
+Backward incompatibilities:
+
+ * the "items" filter, which has been deprecated for quite a long time now, has been removed
+ * the "range" filter has been converted to a function: 0|range(10) -> range(0, 10)
+ * the "constant" filter has been converted to a function: {{ some_date|date('DATE_W3C'|constant) }} -> {{ some_date|date(constant('DATE_W3C')) }}
+ * the "cycle" filter has been converted to a function: {{ ['odd', 'even']|cycle(i) }} -> {{ cycle(['odd', 'even'], i) }}
+ * the "for" tag does not support "joined by" anymore
+ * the "autoescape" first argument is now "true"/"false" (instead of "on"/"off")
+ * the "parent" tag has been replaced by a "parent" function ({{ parent() }} instead of {% parent %})
+ * the "display" tag has been replaced by a "block" function ({{ block('title') }} instead of {% display title %})
+ * removed the grammar and simple token parser (moved to the Twig Extensions repository)
+
+Changes:
+
+ * added "needs_context" option for filters and functions (the context is then passed as a first argument)
+ * added global variables support
+ * made macros return their value instead of echoing directly (fixes calling a macro in sandbox mode)
+ * added the "from" tag to import macros as functions
+ * added support for functions (a function is just syntactic sugar for a getAttribute() call)
+ * made macros callable when sandbox mode is enabled
+ * added an exception when a macro uses a reserved name
+ * the "default" filter now uses the "empty" test instead of just checking for null
+ * added the "empty" test
+
+* 0.9.10 (2010-12-16)
+
+Backward incompatibilities:
+
+ * The Escaper extension is enabled by default, which means that all displayed
+   variables are now automatically escaped. You can revert to the previous
+   behavior by removing the extension via $env->removeExtension('escaper')
+   or just set the 'autoescape' option to 'false'.
+ * removed the "without loop" attribute for the "for" tag (not needed anymore
+   as the Optimizer take care of that for most cases)
+ * arrays and hashes have now a different syntax
+     * arrays keep the same syntax with square brackets: [1, 2]
+     * hashes now use curly braces (["a": "b"] should now be written as {"a": "b"})
+     * support for "arrays with keys" and "hashes without keys" is not supported anymore ([1, "foo": "bar"] or {"foo": "bar", 1})
+ * the i18n extension is now part of the Twig Extensions repository
+
+Changes:
+
+ * added the merge filter
+ * removed 'is_escaper' option for filters (a left over from the previous version) -- you must use 'is_safe' now instead
+ * fixed usage of operators as method names (like is, in, and not)
+ * changed the order of execution for node visitors
+ * fixed default() filter behavior when used with strict_variables set to on
+ * fixed filesystem loader compatibility with PHAR files
+ * enhanced error messages when an unexpected token is parsed in an expression
+ * fixed filename not being added to syntax error messages
+ * added the autoescape option to enable/disable autoescaping
+ * removed the newline after a comment (mimicks PHP behavior)
+ * added a syntax error exception when parent block is used on a template that does not extend another one
+ * made the Escaper extension enabled by default
+ * fixed sandbox extension when used with auto output escaping
+ * fixed escaper when wrapping a Twig_Node_Print (the original class must be preserved)
+ * added an Optimizer extension (enabled by default; optimizes "for" loops and "raw" filters)
+ * added priority to node visitors
+
+* 0.9.9 (2010-11-28)
+
+Backward incompatibilities:
+ * the self special variable has been renamed to _self
+ * the odd and even filters are now tests:
+     {{ foo|odd }} must now be written {{ foo is odd }}
+ * the "safe" filter has been renamed to "raw"
+ * in Node classes,
+        sub-nodes are now accessed via getNode() (instead of property access)
+        attributes via getAttribute() (instead of array access)
+ * the urlencode filter had been renamed to url_encode
+ * the include tag now merges the passed variables with the current context by default
+   (the old behavior is still possible by adding the "only" keyword)
+ * moved Exceptions to Twig_Error_* (Twig_SyntaxError/Twig_RuntimeError are now Twig_Error_Syntax/Twig_Error_Runtime)
+ * removed support for {{ 1 < i < 3 }} (use {{ i > 1 and i < 3 }} instead)
+ * the "in" filter has been removed ({{ a|in(b) }} should now be written {{ a in b }})
+
+Changes:
+ * added file and line to Twig_Error_Runtime exceptions thrown from Twig_Template
+ * changed trans tag to accept any variable for the plural count
+ * fixed sandbox mode (__toString() method check was not enforced if called implicitly from complex statements)
+ * added the ** (power) operator
+ * changed the algorithm used for parsing expressions
+ * added the spaceless tag
+ * removed trim_blocks option
+ * added support for is*() methods for attributes (foo.bar now looks for foo->getBar() or foo->isBar())
+ * changed all exceptions to extend Twig_Error
+ * fixed unary expressions ({{ not(1 or 0) }})
+ * fixed child templates (with an extend tag) that uses one or more imports
+ * added support for {{ 1 not in [2, 3] }} (more readable than the current {{ not (1 in [2, 3]) }})
+ * escaping has been rewritten
+ * the implementation of template inheritance has been rewritten
+   (blocks can now be called individually and still work with inheritance)
+ * fixed error handling for if tag when a syntax error occurs within a subparse process
+ * added a way to implement custom logic for resolving token parsers given a tag name
+ * fixed js escaper to be stricter (now uses a whilelist-based js escaper)
+ * added the following filers: "constant", "trans", "replace", "json_encode"
+ * added a "constant" test
+ * fixed objects with __toString() not being autoescaped
+ * fixed subscript expressions when calling __call() (methods now keep the case)
+ * added "test" feature (accessible via the "is" operator)
+ * removed the debug tag (should be done in an extension)
+ * fixed trans tag when no vars are used in plural form
+ * fixed race condition when writing template cache
+ * added the special _charset variable to reference the current charset
+ * added the special _context variable to reference the current context
+ * renamed self to _self (to avoid conflict)
+ * fixed Twig_Template::getAttribute() for protected properties
+
+* 0.9.8 (2010-06-28)
+
+Backward incompatibilities:
+ * the trans tag plural count is now attached to the plural tag:
+    old: `{% trans count %}...{% plural %}...{% endtrans %}`
+    new: `{% trans %}...{% plural count %}...{% endtrans %}`
+
+ * added a way to translate strings coming from a variable ({% trans var %})
+ * fixed trans tag when used with the Escaper extension
+ * fixed default cache umask
+ * removed Twig_Template instances from the debug tag output
+ * fixed objects with __isset() defined
+ * fixed set tag when used with a capture
+ * fixed type hinting for Twig_Environment::addFilter() method
+
+* 0.9.7 (2010-06-12)
+
+Backward incompatibilities:
+ * changed 'as' to '=' for the set tag ({% set title as "Title" %} must now be {% set title = "Title" %})
+ * removed the sandboxed attribute of the include tag (use the new sandbox tag instead)
+ * refactored the Node system (if you have custom nodes, you will have to update them to use the new API)
+
+ * added self as a special variable that refers to the current template (useful for importing macros from the current template)
+ * added Twig_Template instance support to the include tag
+ * added support for dynamic and conditional inheritance ({% extends some_var %} and {% extends standalone ? "minimum" : "base" %})
+ * added a grammar sub-framework to ease the creation of custom tags
+ * fixed the for tag for large arrays (some loop variables are now only available for arrays and objects that implement the Countable interface)
+ * removed the Twig_Resource::resolveMissingFilter() method
+ * fixed the filter tag which did not apply filtering to included files
+ * added a bunch of unit tests
+ * added a bunch of phpdoc
+ * added a sandbox tag in the sandbox extension
+ * changed the date filter to support any date format supported by DateTime
+ * added strict_variable setting to throw an exception when an invalid variable is used in a template (disabled by default)
+ * added the lexer, parser, and compiler as arguments to the Twig_Environment constructor
+ * changed the cache option to only accepts an explicit path to a cache directory or false
+ * added a way to add token parsers, filters, and visitors without creating an extension
+ * added three interfaces: Twig_NodeInterface, Twig_TokenParserInterface, and Twig_FilterInterface
+ * changed the generated code to match the new coding standards
+ * fixed sandbox mode (__toString() method check was not enforced if called implicitly from a simple statement like {{ article }})
+ * added an exception when a child template has a non-empty body (as it is always ignored when rendering)
+
+* 0.9.6 (2010-05-12)
+
+ * fixed variables defined outside a loop and for which the value changes in a for loop
+ * fixed the test suite for PHP 5.2 and older versions of PHPUnit
+ * added support for __call() in expression resolution
+ * fixed node visiting for macros (macros are now visited by visitors as any other node)
+ * fixed nested block definitions with a parent call (rarely useful but nonetheless supported now)
+ * added the cycle filter
+ * fixed the Lexer when mbstring.func_overload is used with an mbstring.internal_encoding different from ASCII
+ * added a long-syntax for the set tag ({% set foo %}...{% endset %})
+ * unit tests are now powered by PHPUnit
+ * added support for gettext via the `i18n` extension
+ * fixed twig_capitalize_string_filter() and fixed twig_length_filter() when used with UTF-8 values
+ * added a more useful exception if an if tag is not closed properly
+ * added support for escaping strategy in the autoescape tag
+ * fixed lexer when a template has a big chunk of text between/in a block
+
+* 0.9.5 (2010-01-20)
+
+As for any new release, don't forget to remove all cached templates after
+upgrading.
+
+If you have defined custom filters, you MUST upgrade them for this release. To
+upgrade, replace "array" with "new Twig_Filter_Function", and replace the
+environment constant by the "needs_environment" option:
+
+  // before
+  'even'   => array('twig_is_even_filter', false),
+  'escape' => array('twig_escape_filter', true),
+
+  // after
+  'even'   => new Twig_Filter_Function('twig_is_even_filter'),
+  'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true)),
+
+If you have created NodeTransformer classes, you will need to upgrade them to
+the new interface (please note that the interface is not yet considered
+stable).
+
+ * fixed list nodes that did not extend the Twig_NodeListInterface
+ * added the "without loop" option to the for tag (it disables the generation of the loop variable)
+ * refactored node transformers to node visitors
+ * fixed automatic-escaping for blocks
+ * added a way to specify variables to pass to an included template
+ * changed the automatic-escaping rules to be more sensible and more configurable in custom filters (the documentation lists all the rules)
+ * improved the filter system to allow object methods to be used as filters
+ * changed the Array and String loaders to actually make use of the cache mechanism
+ * included the default filter function definitions in the extension class files directly (Core, Escaper)
+ * added the // operator (like the floor() PHP function)
+ * added the .. operator (as a syntactic sugar for the range filter when the step is 1)
+ * added the in operator (as a syntactic sugar for the in filter)
+ * added the following filters in the Core extension: in, range
+ * added support for arrays (same behavior as in PHP, a mix between lists and dictionaries, arrays and hashes)
+ * enhanced some error messages to provide better feedback in case of parsing errors
+
+* 0.9.4 (2009-12-02)
+
+If you have custom loaders, you MUST upgrade them for this release: The
+Twig_Loader base class has been removed, and the Twig_LoaderInterface has also
+been changed (see the source code for more information or the documentation).
+
+ * added support for DateTime instances for the date filter
+ * fixed loop.last when the array only has one item
+ * made it possible to insert newlines in tag and variable blocks
+ * fixed a bug when a literal '\n' were present in a template text
+ * fixed bug when the filename of a template contains */
+ * refactored loaders
+
+* 0.9.3 (2009-11-11)
+
+This release is NOT backward compatible with the previous releases.
+
+  The loaders do not take the cache and autoReload arguments anymore. Instead,
+  the Twig_Environment class has two new options: cache and auto_reload.
+  Upgrading your code means changing this kind of code:
+
+      $loader = new Twig_Loader_Filesystem('/path/to/templates', '/path/to/compilation_cache', true);
+      $twig = new Twig_Environment($loader);
+
+  to something like this:
+
+      $loader = new Twig_Loader_Filesystem('/path/to/templates');
+      $twig = new Twig_Environment($loader, array(
+        'cache' => '/path/to/compilation_cache',
+        'auto_reload' => true,
+      ));
+
+ * deprecated the "items" filter as it is not needed anymore
+ * made cache and auto_reload options of Twig_Environment instead of arguments of Twig_Loader
+ * optimized template loading speed
+ * removed output when an error occurs in a template and render() is used
+ * made major speed improvements for loops (up to 300% on even the smallest loops)
+ * added properties as part of the sandbox mode
+ * added public properties support (obj.item can now be the item property on the obj object)
+ * extended set tag to support expression as value ({% set foo as 'foo' ~ 'bar' %} )
+ * fixed bug when \ was used in HTML
+
+* 0.9.2 (2009-10-29)
+
+ * made some speed optimizations
+ * changed the cache extension to .php
+ * added a js escaping strategy
+ * added support for short block tag
+ * changed the filter tag to allow chained filters
+ * made lexer more flexible as you can now change the default delimiters
+ * added set tag
+ * changed default directory permission when cache dir does not exist (more secure)
+ * added macro support
+ * changed filters first optional argument to be a Twig_Environment instance instead of a Twig_Template instance
+ * made Twig_Autoloader::autoload() a static method
+ * avoid writing template file if an error occurs
+ * added $ escaping when outputting raw strings
+ * enhanced some error messages to ease debugging
+ * fixed empty cache files when the template contains an error
+
+* 0.9.1 (2009-10-14)
+
+  * fixed a bug in PHP 5.2.6
+  * fixed numbers with one than one decimal
+  * added support for method calls with arguments ({{ foo.bar('a', 43) }})
+  * made small speed optimizations
+  * made minor tweaks to allow better extensibility and flexibility
+
+* 0.9.0 (2009-10-12)
+
+ * Initial release
Index: branches/2.8.x/wb/include/Twig/DOC/README.markdown
===================================================================
--- branches/2.8.x/wb/include/Twig/DOC/README.markdown	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/DOC/README.markdown	(revision 1852)
@@ -0,0 +1,17 @@
+Twig, the flexible, fast, and secure template language for PHP
+==============================================================
+
+[![Build Status](https://secure.travis-ci.org/fabpot/Twig.png?branch=master)](http://travis-ci.org/fabpot/Twig)
+
+Twig is a template language for PHP, released under the new BSD license (code
+and documentation).
+
+Twig uses a syntax similar to the Django and Jinja template languages which
+inspired the Twig runtime environment.
+
+More Information
+----------------
+
+Read the [documentation][1] for more information.
+
+[1]: http://twig.sensiolabs.org/documentation
Index: branches/2.8.x/wb/include/Twig/Token.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Token.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Token.php	(revision 1852)
@@ -126,7 +126,7 @@
      *
      * @return string The string representation
      */
-    static public function typeToString($type, $short = false, $line = -1)
+    public static function typeToString($type, $short = false, $line = -1)
     {
         switch ($type) {
             case self::EOF_TYPE:
@@ -169,7 +169,7 @@
                 $name = 'INTERPOLATION_END_TYPE';
                 break;
             default:
-                throw new Twig_Error_Syntax(sprintf('Token of type "%s" does not exist.', $type), $line);
+                throw new LogicException(sprintf('Token of type "%s" does not exist.', $type));
         }
 
         return $short ? $name : 'Twig_Token::'.$name;
@@ -183,7 +183,7 @@
      *
      * @return string The string representation
      */
-    static public function typeToEnglish($type, $line = -1)
+    public static function typeToEnglish($type, $line = -1)
     {
         switch ($type) {
             case self::EOF_TYPE:
@@ -213,7 +213,7 @@
             case self::INTERPOLATION_END_TYPE:
                 return 'end of string interpolation';
             default:
-                throw new Twig_Error_Syntax(sprintf('Token of type "%s" does not exist.', $type), $line);
+                throw new LogicException(sprintf('Token of type "%s" does not exist.', $type));
         }
     }
 }
Index: branches/2.8.x/wb/include/Twig/Node.php
===================================================================
--- branches/2.8.x/wb/include/Twig/Node.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/Node.php	(revision 1852)
@@ -134,12 +134,12 @@
      *
      * @param  string The attribute name
      *
-     * @return mixed  The attribute value
+     * @return mixed The attribute value
      */
     public function getAttribute($name)
     {
         if (!array_key_exists($name, $this->attributes)) {
-            throw new Twig_Error_Runtime(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this)));
+            throw new LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this)));
         }
 
         return $this->attributes[$name];
@@ -188,7 +188,7 @@
     public function getNode($name)
     {
         if (!array_key_exists($name, $this->nodes)) {
-            throw new Twig_Error_Runtime(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this)));
+            throw new LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this)));
         }
 
         return $this->nodes[$name];
Index: branches/2.8.x/wb/include/Twig/LoaderInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/LoaderInterface.php	(revision 1851)
+++ branches/2.8.x/wb/include/Twig/LoaderInterface.php	(revision 1852)
@@ -20,24 +20,24 @@
     /**
      * Gets the source code of a template, given its name.
      *
-     * @param  string $name The name of the template to load
+     * @param string $name The name of the template to load
      *
      * @return string The template source code
      *
      * @throws Twig_Error_Loader When $name is not found
      */
-    function getSource($name);
+    public function getSource($name);
 
     /**
      * Gets the cache key to use for the cache for a given template name.
      *
-     * @param  string $name The name of the template to load
+     * @param string $name The name of the template to load
      *
      * @return string The cache key
      *
      * @throws Twig_Error_Loader When $name is not found
      */
-    function getCacheKey($name);
+    public function getCacheKey($name);
 
     /**
      * Returns true if the template is still fresh.
@@ -49,5 +49,5 @@
      *
      * @throws Twig_Error_Loader When $name is not found
      */
-    function isFresh($name, $time);
+    public function isFresh($name, $time);
 }
Index: branches/2.8.x/wb/include/Twig/ExistsLoaderInterface.php
===================================================================
--- branches/2.8.x/wb/include/Twig/ExistsLoaderInterface.php	(nonexistent)
+++ branches/2.8.x/wb/include/Twig/ExistsLoaderInterface.php	(revision 1852)
@@ -0,0 +1,28 @@
+<?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.
+ */
+
+/**
+ * Adds an exists() method for loaders.
+ *
+ * @package    twig
+ * @author     Florin Patan <florinpatan@gmail.com>
+ */
+interface Twig_ExistsLoaderInterface
+{
+    /**
+     * Check if we have the source code of a template, given its name.
+     *
+     * @param string $name The name of the template to check if we can load
+     *
+     * @return boolean If the template source code is handled by this loader or not
+     */
+    public function exists($name);
+}

Property changes on: branches/2.8.x/wb/include/Twig/ExistsLoaderInterface.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision HeadURL
\ No newline at end of property
Index: branches/2.8.x/wb/include/Twig
===================================================================
--- branches/2.8.x/wb/include/Twig	(revision 1851)
+++ branches/2.8.x/wb/include/Twig	(revision 1852)

Property changes on: branches/2.8.x/wb/include/Twig
___________________________________________________________________
Added: svn:ignore
## -0,0 +1 ##
+.goutputstream-4REEQW
Index: branches/2.8.x/wb/admin/interface/version.php
===================================================================
--- branches/2.8.x/wb/admin/interface/version.php	(revision 1851)
+++ branches/2.8.x/wb/admin/interface/version.php	(revision 1852)
@@ -51,5 +51,5 @@
 
 // check if defined to avoid errors during installation (redirect to admin panel fails if PHP error/warnings are enabled)
 if(!defined('VERSION')) define('VERSION', '2.8.3');
-if(!defined('REVISION')) define('REVISION', '1850');
+if(!defined('REVISION')) define('REVISION', '1852');
 if(!defined('SP')) define('SP', '');
