You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2012/05/27 21:59:52 UTC

svn commit: r1343084 [8/13] - in /logging/site/branches/cms/trunk: ./ content/ content/pages/ content/resources/ content/resources/css/ content/resources/img/ content/resources/js/ libs/ libs/Twig/ libs/Twig/lib/ libs/Twig/lib/Twig/ libs/Twig/lib/Twig/...

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/ExpressionParser.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/ExpressionParser.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/ExpressionParser.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/ExpressionParser.php Sun May 27 19:59:46 2012
@@ -0,0 +1,488 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2009 Armin Ronacher
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Parses expressions.
+ *
+ * This parser implements a "Precedence climbing" algorithm.
+ *
+ * @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
+ * @see http://en.wikipedia.org/wiki/Operator-precedence_parser
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_ExpressionParser
+{
+    const OPERATOR_LEFT = 1;
+    const OPERATOR_RIGHT = 2;
+
+    protected $parser;
+    protected $unaryOperators;
+    protected $binaryOperators;
+
+    public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators)
+    {
+        $this->parser = $parser;
+        $this->unaryOperators = $unaryOperators;
+        $this->binaryOperators = $binaryOperators;
+    }
+
+    public function parseExpression($precedence = 0)
+    {
+        $expr = $this->getPrimary();
+        $token = $this->parser->getCurrentToken();
+        while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) {
+            $op = $this->binaryOperators[$token->getValue()];
+            $this->parser->getStream()->next();
+
+            if (isset($op['callable'])) {
+                $expr = call_user_func($op['callable'], $this->parser, $expr);
+            } else {
+                $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
+                $class = $op['class'];
+                $expr = new $class($expr, $expr1, $token->getLine());
+            }
+
+            $token = $this->parser->getCurrentToken();
+        }
+
+        if (0 === $precedence) {
+            return $this->parseConditionalExpression($expr);
+        }
+
+        return $expr;
+    }
+
+    protected function getPrimary()
+    {
+        $token = $this->parser->getCurrentToken();
+
+        if ($this->isUnary($token)) {
+            $operator = $this->unaryOperators[$token->getValue()];
+            $this->parser->getStream()->next();
+            $expr = $this->parseExpression($operator['precedence']);
+            $class = $operator['class'];
+
+            return $this->parsePostfixExpression(new $class($expr, $token->getLine()));
+        } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
+            $this->parser->getStream()->next();
+            $expr = $this->parseExpression();
+            $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed');
+
+            return $this->parsePostfixExpression($expr);
+        }
+
+        return $this->parsePrimaryExpression();
+    }
+
+    protected function parseConditionalExpression($expr)
+    {
+        while ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '?')) {
+            $this->parser->getStream()->next();
+            $expr2 = $this->parseExpression();
+            $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'The ternary operator must have a default value');
+            $expr3 = $this->parseExpression();
+
+            $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
+        }
+
+        return $expr;
+    }
+
+    protected function isUnary(Twig_Token $token)
+    {
+        return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]);
+    }
+
+    protected function isBinary(Twig_Token $token)
+    {
+        return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]);
+    }
+
+    public function parsePrimaryExpression()
+    {
+        $token = $this->parser->getCurrentToken();
+        switch ($token->getType()) {
+            case Twig_Token::NAME_TYPE:
+                $this->parser->getStream()->next();
+                switch ($token->getValue()) {
+                    case 'true':
+                    case 'TRUE':
+                        $node = new Twig_Node_Expression_Constant(true, $token->getLine());
+                        break;
+
+                    case 'false':
+                    case 'FALSE':
+                        $node = new Twig_Node_Expression_Constant(false, $token->getLine());
+                        break;
+
+                    case 'none':
+                    case 'NONE':
+                    case 'null':
+                    case 'NULL':
+                        $node = new Twig_Node_Expression_Constant(null, $token->getLine());
+                        break;
+
+                    default:
+                        if ('(' === $this->parser->getCurrentToken()->getValue()) {
+                            $node = $this->getFunctionNode($token->getValue(), $token->getLine());
+                        } else {
+                            $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
+                        }
+                }
+                break;
+
+            case Twig_Token::NUMBER_TYPE:
+                $this->parser->getStream()->next();
+                $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
+                break;
+
+            case Twig_Token::STRING_TYPE:
+            case Twig_Token::INTERPOLATION_START_TYPE:
+                $node = $this->parseStringExpression();
+                break;
+
+            default:
+                if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) {
+                    $node = $this->parseArrayExpression();
+                } 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());
+                }
+        }
+
+        return $this->parsePostfixExpression($node);
+    }
+
+    public function parseStringExpression()
+    {
+        $stream = $this->parser->getStream();
+
+        $nodes = array();
+        // a string cannot be followed by another string in a single expression
+        $nextCanBeString = true;
+        while (true) {
+            if ($stream->test(Twig_Token::STRING_TYPE) && $nextCanBeString) {
+                $token = $stream->next();
+                $nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
+                $nextCanBeString = false;
+            } elseif ($stream->test(Twig_Token::INTERPOLATION_START_TYPE)) {
+                $stream->next();
+                $nodes[] = $this->parseExpression();
+                $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
+                $nextCanBeString = true;
+            } else {
+                break;
+            }
+        }
+
+        $expr = array_shift($nodes);
+        foreach ($nodes as $node) {
+            $expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getLine());
+        }
+
+        return $expr;
+    }
+
+    public function parseArrayExpression()
+    {
+        $stream = $this->parser->getStream();
+        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected');
+
+        $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
+        $first = true;
+        while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
+            if (!$first) {
+                $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma');
+
+                // trailing ,?
+                if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
+                    break;
+                }
+            }
+            $first = false;
+
+            $node->addElement($this->parseExpression());
+        }
+        $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed');
+
+        return $node;
+    }
+
+    public function parseHashExpression()
+    {
+        $stream = $this->parser->getStream();
+        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected');
+
+        $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
+        $first = true;
+        while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
+            if (!$first) {
+                $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma');
+
+                // trailing ,?
+                if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
+                    break;
+                }
+            }
+            $first = false;
+
+            // a hash key can be:
+            //
+            //  * a number -- 12
+            //  * a string -- 'a'
+            //  * a name, which is equivalent to a string -- a
+            //  * an expression, which must be enclosed in parentheses -- (1 + 2)
+            if ($stream->test(Twig_Token::STRING_TYPE) || $stream->test(Twig_Token::NAME_TYPE) || $stream->test(Twig_Token::NUMBER_TYPE)) {
+                $token = $stream->next();
+                $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
+            } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
+                $key = $this->parseExpression();
+            } 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());
+            }
+
+            $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
+            $value = $this->parseExpression();
+
+            $node->addElement($value, $key);
+        }
+        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed');
+
+        return $node;
+    }
+
+    public function parsePostfixExpression($node)
+    {
+        while (true) {
+            $token = $this->parser->getCurrentToken();
+            if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) {
+                if ('.' == $token->getValue() || '[' == $token->getValue()) {
+                    $node = $this->parseSubscriptExpression($node);
+                } elseif ('|' == $token->getValue()) {
+                    $node = $this->parseFilterExpression($node);
+                } else {
+                    break;
+                }
+            } else {
+                break;
+            }
+        }
+
+        return $node;
+    }
+
+    public function getFunctionNode($name, $line)
+    {
+        $args = $this->parseArguments();
+        switch ($name) {
+            case 'parent':
+                if (!count($this->parser->getBlockStack())) {
+                    throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line);
+                }
+
+                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);
+                }
+
+                return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
+            case 'block':
+                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);
+                }
+
+                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)) {
+                    $arguments = new Twig_Node_Expression_Array(array(), $line);
+                    foreach ($args as $n) {
+                        $arguments->addElement($n);
+                    }
+
+                    $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line);
+                    $node->setAttribute('safe', true);
+
+                    return $node;
+                }
+
+                $class = $this->getFunctionNodeClass($name);
+
+                return new $class($name, $args, $line);
+        }
+    }
+
+    public function parseSubscriptExpression($node)
+    {
+        $stream = $this->parser->getStream();
+        $token = $stream->next();
+        $lineno = $token->getLine();
+        $arguments = new Twig_Node_Expression_Array(array(), $lineno);
+        $type = Twig_TemplateInterface::ANY_CALL;
+        if ($token->getValue() == '.') {
+            $token = $stream->next();
+            if (
+                $token->getType() == Twig_Token::NAME_TYPE
+                ||
+                $token->getType() == Twig_Token::NUMBER_TYPE
+                ||
+                ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
+            ) {
+                $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
+
+                if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
+                    $type = Twig_TemplateInterface::METHOD_CALL;
+                    foreach ($this->parseArguments() as $n) {
+                        $arguments->addElement($n);
+                    }
+                }
+            } else {
+                throw new Twig_Error_Syntax('Expected name or number', $lineno);
+            }
+        } else {
+            $type = Twig_TemplateInterface::ARRAY_CALL;
+
+            $arg = $this->parseExpression();
+
+            // slice?
+            if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
+                $stream->next();
+
+                if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
+                    $length = new Twig_Node_Expression_Constant(null, $token->getLine());
+                } else {
+                    $length = $this->parseExpression();
+                }
+
+                $class = $this->getFilterNodeClass('slice');
+                $arguments = new Twig_Node(array($arg, $length));
+                $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine());
+
+                $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
+
+                return $filter;
+            }
+
+            $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
+        }
+
+        return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno);
+    }
+
+    public function parseFilterExpression($node)
+    {
+        $this->parser->getStream()->next();
+
+        return $this->parseFilterExpressionRaw($node);
+    }
+
+    public function parseFilterExpressionRaw($node, $tag = null)
+    {
+        while (true) {
+            $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE);
+
+            $name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
+            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
+                $arguments = new Twig_Node();
+            } else {
+                $arguments = $this->parseArguments();
+            }
+
+            $class = $this->getFilterNodeClass($name->getAttribute('value'));
+
+            $node = new $class($node, $name, $arguments, $token->getLine(), $tag);
+
+            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) {
+                break;
+            }
+
+            $this->parser->getStream()->next();
+        }
+
+        return $node;
+    }
+
+    public function parseArguments()
+    {
+        $args = array();
+        $stream = $this->parser->getStream();
+
+        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must be opened by a parenthesis');
+        while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) {
+            if (!empty($args)) {
+                $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
+            }
+            $args[] = $this->parseExpression();
+        }
+        $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
+
+        return new Twig_Node($args);
+    }
+
+    public function parseAssignmentExpression()
+    {
+        $targets = array();
+        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());
+            }
+            $targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine());
+
+            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
+                break;
+            }
+            $this->parser->getStream()->next();
+        }
+
+        return new Twig_Node($targets);
+    }
+
+    public function parseMultitargetExpression()
+    {
+        $targets = array();
+        while (true) {
+            $targets[] = $this->parseExpression();
+            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
+                break;
+            }
+            $this->parser->getStream()->next();
+        }
+
+        return new Twig_Node($targets);
+    }
+
+    protected function getFunctionNodeClass($name)
+    {
+        $functionMap = $this->parser->getEnvironment()->getFunctions();
+        if (isset($functionMap[$name]) && $functionMap[$name] instanceof Twig_Function_Node) {
+            return $functionMap[$name]->getClass();
+        }
+
+        return 'Twig_Node_Expression_Function';
+    }
+
+    protected function getFilterNodeClass($name)
+    {
+        $filterMap = $this->parser->getEnvironment()->getFilters();
+        if (isset($filterMap[$name]) && $filterMap[$name] instanceof Twig_Filter_Node) {
+            return $filterMap[$name]->getClass();
+        }
+
+        return 'Twig_Node_Expression_Filter';
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension.php Sun May 27 19:59:46 2012
@@ -0,0 +1,93 @@
+<?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.
+ */
+abstract class Twig_Extension implements Twig_ExtensionInterface
+{
+    /**
+     * Initializes the runtime environment.
+     *
+     * This is where you can load some file that contains filter functions for instance.
+     *
+     * @param Twig_Environment $environment The current Twig_Environment instance
+     */
+    public function initRuntime(Twig_Environment $environment)
+    {
+    }
+
+    /**
+     * Returns the token parser instances to add to the existing list.
+     *
+     * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
+     */
+    public function getTokenParsers()
+    {
+        return array();
+    }
+
+    /**
+     * Returns the node visitor instances to add to the existing list.
+     *
+     * @return array An array of Twig_NodeVisitorInterface instances
+     */
+    public function getNodeVisitors()
+    {
+        return array();
+    }
+
+    /**
+     * Returns a list of filters to add to the existing list.
+     *
+     * @return array An array of filters
+     */
+    public function getFilters()
+    {
+        return array();
+    }
+
+    /**
+     * Returns a list of tests to add to the existing list.
+     *
+     * @return array An array of tests
+     */
+    public function getTests()
+    {
+        return array();
+    }
+
+    /**
+     * Returns a list of functions to add to the existing list.
+     *
+     * @return array An array of functions
+     */
+    public function getFunctions()
+    {
+        return array();
+    }
+
+    /**
+     * Returns a list of operators to add to the existing list.
+     *
+     * @return array An array of operators
+     */
+    public function getOperators()
+    {
+        return array();
+    }
+
+    /**
+     * Returns a list of global variables to add to the existing list.
+     *
+     * @return array An array of global variables
+     */
+    public function getGlobals()
+    {
+        return array();
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Core.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Core.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Core.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Core.php Sun May 27 19:59:46 2012
@@ -0,0 +1,1037 @@
+<?php
+
+if (!defined('ENT_SUBSTITUTE')) {
+    define('ENT_SUBSTITUTE', 8);
+}
+
+/*
+ * 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.
+ */
+class Twig_Extension_Core extends Twig_Extension
+{
+    protected $dateFormats = array('F j, Y H:i', '%d days');
+    protected $numberFormat = array(0, '.', ',');
+    protected $timezone = null;
+
+    /**
+     * Sets the default format to be used by the date filter.
+     *
+     * @param string $format             The default date format string
+     * @param string $dateIntervalFormat The default date interval format string
+     */
+    public function setDateFormat($format = null, $dateIntervalFormat = null)
+    {
+        if (null !== $format) {
+            $this->dateFormats[0] = $format;
+        }
+
+        if (null !== $dateIntervalFormat) {
+            $this->dateFormats[1] = $dateIntervalFormat;
+        }
+    }
+
+    /**
+     * Gets the default format to be used by the date filter.
+     *
+     * @return array The default date format string and the default date interval format string
+     */
+    public function getDateFormat()
+    {
+        return $this->dateFormats;
+    }
+
+    /**
+     * Sets the default timezone to be used by the date filter.
+     *
+     * @param DateTimeZone|string $timezone  The default timezone string or a DateTimeZone object
+     */
+    public function setTimezone($timezone)
+    {
+        $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone);
+    }
+
+    /**
+     * Gets the default timezone to be used by the date filter.
+     *
+     * @return DateTimeZone The default timezone currently in use
+     */
+    public function getTimezone()
+    {
+        return $this->timezone;
+    }
+
+    /**
+     * 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.
+     */
+    public function setNumberFormat($decimal, $decimalPoint, $thousandSep)
+    {
+        $this->numberFormat = array($decimal, $decimalPoint, $thousandSep);
+    }
+
+    /**
+     * Get the default format used by the number_format filter.
+     *
+     * @return array The arguments for number_format()
+     */
+    public function getNumberFormat()
+    {
+        return $this->numberFormat;
+    }
+
+    /**
+     * Returns the token parser instance to add to the existing list.
+     *
+     * @return array An array of Twig_TokenParser instances
+     */
+    public function getTokenParsers()
+    {
+        return array(
+            new Twig_TokenParser_For(),
+            new Twig_TokenParser_If(),
+            new Twig_TokenParser_Extends(),
+            new Twig_TokenParser_Include(),
+            new Twig_TokenParser_Block(),
+            new Twig_TokenParser_Use(),
+            new Twig_TokenParser_Filter(),
+            new Twig_TokenParser_Macro(),
+            new Twig_TokenParser_Import(),
+            new Twig_TokenParser_From(),
+            new Twig_TokenParser_Set(),
+            new Twig_TokenParser_Spaceless(),
+            new Twig_TokenParser_Flush(),
+            new Twig_TokenParser_Do(),
+            new Twig_TokenParser_Embed(),
+        );
+    }
+
+    /**
+     * Returns a list of filters to add to the existing list.
+     *
+     * @return array An array of filters
+     */
+    public function getFilters()
+    {
+        $filters = array(
+            // formatting filters
+            'date'          => new Twig_Filter_Function('twig_date_format_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)),
+
+            // encoding
+            'url_encode'       => new Twig_Filter_Function('twig_urlencode_filter'),
+            'json_encode'      => new Twig_Filter_Function('twig_jsonencode_filter'),
+            'convert_encoding' => new Twig_Filter_Function('twig_convert_encoding'),
+
+            // string filters
+            'title'      => new Twig_Filter_Function('twig_title_string_filter', array('needs_environment' => true)),
+            'capitalize' => new Twig_Filter_Function('twig_capitalize_string_filter', array('needs_environment' => true)),
+            'upper'      => new Twig_Filter_Function('strtoupper'),
+            'lower'      => new Twig_Filter_Function('strtolower'),
+            'striptags'  => new Twig_Filter_Function('strip_tags'),
+            'trim'       => new Twig_Filter_Function('trim'),
+            'nl2br'      => new Twig_Filter_Function('nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),
+
+            // array helpers
+            'join'    => new Twig_Filter_Function('twig_join_filter'),
+            'sort'    => new Twig_Filter_Function('twig_sort_filter'),
+            'merge'   => new Twig_Filter_Function('twig_array_merge'),
+
+            // string/array filters
+            'reverse' => new Twig_Filter_Function('twig_reverse_filter', array('needs_environment' => true)),
+            'length'  => new Twig_Filter_Function('twig_length_filter', array('needs_environment' => true)),
+            'slice'   => new Twig_Filter_Function('twig_slice', array('needs_environment' => true)),
+
+            // iteration and runtime
+            'default' => new Twig_Filter_Node('Twig_Node_Expression_Filter_Default'),
+            '_default' => new Twig_Filter_Function('_twig_default_filter'),
+
+            'keys'    => new Twig_Filter_Function('twig_get_array_keys_filter'),
+
+            // escaping
+            'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
+            'e'      => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
+        );
+
+        if (function_exists('mb_get_info')) {
+            $filters['upper'] = new Twig_Filter_Function('twig_upper_filter', array('needs_environment' => true));
+            $filters['lower'] = new Twig_Filter_Function('twig_lower_filter', array('needs_environment' => true));
+        }
+
+        return $filters;
+    }
+
+    /**
+     * Returns a list of global functions to add to the existing list.
+     *
+     * @return array An array of global functions
+     */
+    public function getFunctions()
+    {
+        return array(
+            'range'    => new Twig_Function_Function('range'),
+            'constant' => new Twig_Function_Function('constant'),
+            'cycle'    => new Twig_Function_Function('twig_cycle'),
+            'random'   => new Twig_Function_Function('twig_random', array('needs_environment' => true)),
+            'date'     => new Twig_Function_Function('twig_date_converter', array('needs_environment' => true)),
+        );
+    }
+
+    /**
+     * Returns a list of tests to add to the existing list.
+     *
+     * @return array An array of tests
+     */
+    public function getTests()
+    {
+        return array(
+            'even'        => new Twig_Test_Node('Twig_Node_Expression_Test_Even'),
+            'odd'         => new Twig_Test_Node('Twig_Node_Expression_Test_Odd'),
+            'defined'     => new Twig_Test_Node('Twig_Node_Expression_Test_Defined'),
+            'sameas'      => new Twig_Test_Node('Twig_Node_Expression_Test_Sameas'),
+            'none'        => new Twig_Test_Node('Twig_Node_Expression_Test_Null'),
+            'null'        => new Twig_Test_Node('Twig_Node_Expression_Test_Null'),
+            'divisibleby' => new Twig_Test_Node('Twig_Node_Expression_Test_Divisibleby'),
+            'constant'    => new Twig_Test_Node('Twig_Node_Expression_Test_Constant'),
+            'empty'       => new Twig_Test_Function('twig_test_empty'),
+            'iterable'    => new Twig_Test_Function('twig_test_iterable'),
+        );
+    }
+
+    /**
+     * Returns a list of operators to add to the existing list.
+     *
+     * @return array An array of operators
+     */
+    public function getOperators()
+    {
+        return array(
+            array(
+                'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
+                '-'   => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'),
+                '+'   => 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),
+                '=='     => 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),
+                '>'      => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '>='     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '<='     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                'in'     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '..'     => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '+'      => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '-'      => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '~'      => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '*'      => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '/'      => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '//'     => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '%'      => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                'is'     => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                '**'     => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
+            ),
+        );
+    }
+
+    public function parseNotTestExpression(Twig_Parser $parser, $node)
+    {
+        return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine());
+    }
+
+    public function parseTestExpression(Twig_Parser $parser, $node)
+    {
+        $stream = $parser->getStream();
+        $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
+        $arguments = null;
+        if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
+            $arguments = $parser->getExpressionParser()->parseArguments();
+        }
+
+        $class = $this->getTestNodeClass($parser->getEnvironment(), $name);
+
+        return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
+    }
+
+    protected function getTestNodeClass(Twig_Environment $env, $name)
+    {
+        $testMap = $env->getTests();
+        if (isset($testMap[$name]) && $testMap[$name] instanceof Twig_Test_Node) {
+            return $testMap[$name]->getClass();
+        }
+
+        return 'Twig_Node_Expression_Test';
+    }
+
+    /**
+     * Returns the name of the extension.
+     *
+     * @return string The extension name
+     */
+    public function getName()
+    {
+        return 'core';
+    }
+}
+
+/**
+ * Cycles over a value.
+ *
+ * @param ArrayAccess|array $values An array or an ArrayAccess instance
+ * @param integer           $i      The cycle value
+ *
+ * @return string The next value in the cycle
+ */
+function twig_cycle($values, $i)
+{
+    if (!is_array($values) && !$values instanceof ArrayAccess) {
+        return $values;
+    }
+
+    return $values[$i % count($values)];
+}
+
+/**
+ * Returns a random value depending on the supplied parameter type:
+ * - a random item from a Traversable or array
+ * - 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
+ *
+ * @throws Twig_Error_Runtime When $values is an empty array (does not apply to an empty string which is returned as is).
+ *
+ * @return mixed A random value from the given sequence
+ */
+function twig_random(Twig_Environment $env, $values = null)
+{
+    if (null === $values) {
+        return mt_rand();
+    }
+
+    if (is_int($values) || is_float($values)) {
+        return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values);
+    }
+
+    if ($values instanceof Traversable) {
+        $values = iterator_to_array($values);
+    } elseif (is_string($values)) {
+        if ('' === $values) {
+            return '';
+        }
+        if (null !== $charset = $env->getCharset()) {
+            if ('UTF-8' != $charset) {
+                $values = twig_convert_encoding($values, 'UTF-8', $charset);
+            }
+
+            // unicode version of str_split()
+            // split at all positions, but not after the start and not before the end
+            $values = preg_split('/(?<!^)(?!$)/u', $values);
+
+            if ('UTF-8' != $charset) {
+                foreach ($values as $i => $value) {
+                    $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8');
+                }
+            }
+        } else {
+            return $values[mt_rand(0, strlen($values) - 1)];
+        }
+    }
+
+    if (!is_array($values)) {
+        return $values;
+    }
+
+    if (0 === count($values)) {
+        throw new Twig_Error_Runtime('The random function cannot pick from an empty array.');
+    }
+
+    return $values[array_rand($values, 1)];
+}
+
+/**
+ * Converts a date to the given format.
+ *
+ * <pre>
+ *   {{ post.published_at|date("m/d/Y") }}
+ * </pre>
+ *
+ * @param Twig_Environment             $env      A Twig_Environment instance
+ * @param DateTime|DateInterval|string $date     A date
+ * @param string                       $format   A format
+ * @param DateTimeZone|string          $timezone A timezone
+ *
+ * @return string The formatter date
+ */
+function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
+{
+    if (null === $format) {
+        $formats = $env->getExtension('core')->getDateFormat();
+        $format = $date instanceof DateInterval ? $formats[1] : $formats[0];
+    }
+
+    if ($date instanceof DateInterval || $date instanceof DateTime) {
+        if (null !== $timezone) {
+            $date = clone $date;
+            $date->setTimezone($timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone));
+        }
+
+        return $date->format($format);
+    }
+
+    return twig_date_converter($env, $date, $timezone)->format($format);
+}
+
+/**
+ * Converts an input to a DateTime instance.
+ *
+ * <pre>
+ *    {% if date(user.created_at) < date('+2days') %}
+ *      {# do something #}
+ *    {% endif %}
+ * </pre>
+ *
+ * @param Twig_Environment    $env      A Twig_Environment instance
+ * @param DateTime|string     $date     A date
+ * @param DateTimeZone|string $timezone A timezone
+ *
+ * @return DateTime A DateTime instance
+ */
+function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null)
+{
+    if ($date instanceof DateTime) {
+        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);
+    }
+
+    // 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;
+}
+
+/**
+ * Number format filter.
+ *
+ * All of the formatting options can be left null, in that case the defaults will
+ * be used.  Supplying any of the parameters will override the defaults set in the
+ * environment object.
+ *
+ * @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 string              $decimalPoint The character(s) to use for the decimal point.
+ * @param string              $thousandSep  The character(s) to use for the thousands separator.
+ *
+ * @return string The formatted number
+ */
+function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
+{
+    $defaults = $env->getExtension('core')->getNumberFormat();
+    if (null === $decimal) {
+        $decimal = $defaults[0];
+    }
+
+    if (null === $decimalPoint) {
+        $decimalPoint = $defaults[1];
+    }
+
+    if (null === $thousandSep) {
+        $thousandSep = $defaults[2];
+    }
+
+    return number_format((float) $number, $decimal, $decimalPoint, $thousandSep);
+}
+
+/**
+ * URL encodes a string.
+ *
+ * @param string $url A URL
+ * @param bool   $raw true to use rawurlencode() instead of urlencode
+ *
+ * @return string The URL encoded value
+ */
+function twig_urlencode_filter($url, $raw = false)
+{
+    if ($raw) {
+        return rawurlencode($url);
+    }
+
+    return urlencode($url);
+}
+
+if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+    /**
+     * JSON encodes a variable.
+     *
+     * @param mixed   $value   The value to encode.
+     * @param integer $options Not used on PHP 5.2.x
+     *
+     * @return mixed The JSON encoded value
+     */
+    function twig_jsonencode_filter($value, $options = 0)
+    {
+        if ($value instanceof Twig_Markup) {
+            $value = (string) $value;
+        } elseif (is_array($value)) {
+            array_walk_recursive($value, '_twig_markup2string');
+        }
+
+        return json_encode($value);
+    }
+} else {
+    /**
+     * JSON encodes a variable.
+     *
+     * @param mixed   $value   The value to encode.
+     * @param integer $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT
+     *
+     * @return mixed The JSON encoded value
+     */
+    function twig_jsonencode_filter($value, $options = 0)
+    {
+        if ($value instanceof Twig_Markup) {
+            $value = (string) $value;
+        } elseif (is_array($value)) {
+            array_walk_recursive($value, '_twig_markup2string');
+        }
+
+        return json_encode($value, $options);
+    }
+}
+
+function _twig_markup2string(&$value)
+{
+    if ($value instanceof Twig_Markup) {
+        $value = (string) $value;
+    }
+}
+
+/**
+ * Merges an array with another one.
+ *
+ * <pre>
+ *  {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
+ *
+ *  {% set items = items|merge({ 'peugeot': 'car' }) %}
+ *
+ *  {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
+ * </pre>
+ *
+ * @param array $arr1 An array
+ * @param array $arr2 An array
+ *
+ * @return array The merged array
+ */
+function twig_array_merge($arr1, $arr2)
+{
+    if (!is_array($arr1) || !is_array($arr2)) {
+        throw new Twig_Error_Runtime('The merge filter only works with arrays or hashes.');
+    }
+
+    return array_merge($arr1, $arr2);
+}
+
+/**
+ * Slices a variable.
+ *
+ * @param Twig_Environment $env          A Twig_Environment instance
+ * @param mixed            $item         A variable
+ * @param integer          $start        Start of the slice
+ * @param integer          $length       Size of the slice
+ * @param Boolean          $preserveKeys Whether to preserve key or not (when the input is an array)
+ *
+ * @return mixed The sliced variable
+ */
+function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
+{
+    if ($item instanceof Traversable) {
+        $item = iterator_to_array($item, false);
+    }
+
+    if (is_array($item)) {
+        return array_slice($item, $start, $length, $preserveKeys);
+    }
+
+    $item = (string) $item;
+
+    if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) {
+        return mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset);
+    }
+
+    return null === $length ? substr($item, $start) : substr($item, $start, $length);
+}
+
+/**
+ * Joins the values to a string.
+ *
+ * The separator between elements is an empty string per default, you can define it with the optional parameter.
+ *
+ * <pre>
+ *  {{ [1, 2, 3]|join('|') }}
+ *  {# returns 1|2|3 #}
+ *
+ *  {{ [1, 2, 3]|join }}
+ *  {# returns 123 #}
+ * </pre>
+ *
+ * @param array  $value An array
+ * @param string $glue  The separator
+ *
+ * @return string The concatenated string
+ */
+function twig_join_filter($value, $glue = '')
+{
+    if ($value instanceof Traversable) {
+        $value = iterator_to_array($value, false);
+    }
+
+    return implode($glue, (array) $value);
+}
+
+// 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.
+function _twig_default_filter($value, $default = '')
+{
+    if (twig_test_empty($value)) {
+        return $default;
+    }
+
+    return $value;
+}
+
+/**
+ * Returns the keys for the given array.
+ *
+ * It is useful when you want to iterate over the keys of an array:
+ *
+ * <pre>
+ *  {% for key in array|keys %}
+ *      {# ... #}
+ *  {% endfor %}
+ * </pre>
+ *
+ * @param array $array An array
+ *
+ * @return array The keys
+ */
+function twig_get_array_keys_filter($array)
+{
+    if (is_object($array) && $array instanceof Traversable) {
+        return array_keys(iterator_to_array($array));
+    }
+
+    if (!is_array($array)) {
+        return array();
+    }
+
+    return array_keys($array);
+}
+
+/**
+ * Reverses a variable.
+ *
+ * @param Twig_Environment         $env          A Twig_Environment instance
+ * @param array|Traversable|string $item         An array, a Traversable instance, or a string
+ * @param Boolean                  $preserveKeys Whether to preserve key or not
+ *
+ * @return mixed The reversed input
+ */
+function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
+{
+    if (is_object($item) && $item instanceof Traversable) {
+        return array_reverse(iterator_to_array($item), $preserveKeys);
+    }
+
+    if (is_array($item)) {
+        return array_reverse($item, $preserveKeys);
+    }
+
+    if (null !== $charset = $env->getCharset()) {
+        $string = (string) $item;
+
+        if ('UTF-8' != $charset) {
+            $item = twig_convert_encoding($string, 'UTF-8', $charset);
+        }
+
+        preg_match_all('/./us', $item, $matches);
+
+        $string = implode('', array_reverse($matches[0]));
+
+        if ('UTF-8' != $charset) {
+            $string = twig_convert_encoding($string, $charset, 'UTF-8');
+        }
+
+        return $string;
+    }
+
+    return strrev((string) $item);
+}
+
+/**
+ * Sorts an array.
+ *
+ * @param array $array An array
+ */
+function twig_sort_filter($array)
+{
+    asort($array);
+
+    return $array;
+}
+
+/* used internally */
+function twig_in_filter($value, $compare)
+{
+    if (is_array($compare)) {
+        return in_array($value, $compare);
+    } elseif (is_string($compare)) {
+        if (!strlen((string) $value)) {
+            return empty($compare);
+        }
+
+        return false !== strpos($compare, (string) $value);
+    } elseif (is_object($compare) && $compare instanceof Traversable) {
+        return in_array($value, iterator_to_array($compare, false));
+    }
+
+    return false;
+}
+
+/**
+ * Escapes a string.
+ *
+ * @param Twig_Environment $env        A Twig_Environment instance
+ * @param string           $string     The value to be escaped
+ * @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, $strategy = 'html', $charset = null, $autoescape = false)
+{
+    if ($autoescape && is_object($string) && $string instanceof Twig_Markup) {
+        return $string;
+    }
+
+    if (!is_string($string) && !(is_object($string) && method_exists($string, '__toString'))) {
+        return $string;
+    }
+
+    if (null === $charset) {
+        $charset = $env->getCharset();
+    }
+
+    $string = (string) $string;
+
+    switch ($strategy) {
+        case 'js':
+            // escape all non-alphanumeric characters
+            // into their \xHH or \uHHHH representations
+            if ('UTF-8' != $charset) {
+                $string = twig_convert_encoding($string, 'UTF-8', $charset);
+            }
+
+            if (null === $string = preg_replace_callback('#[^\p{L}\p{N} ]#u', '_twig_escape_js_callback', $string)) {
+                throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 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 strategies.
+            static $htmlspecialcharsCharsets = array(
+                'iso-8859-1' => true, 'iso8859-1' => true,
+                'iso-8859-15' => true, 'iso8859-15' => true,
+                'utf-8' => true,
+                'cp866' => true, 'ibm866' => true, '866' => true,
+                'cp1251' => true, 'windows-1251' => true, 'win-1251' => true,
+                '1251' => true,
+                'cp1252' => true, 'windows-1252' => true, '1252' => true,
+                'koi8-r' => true, 'koi8-ru' => true, 'koi8r' => true,
+                'big5' => true, '950' => true,
+                'gb2312' => true, '936' => true,
+                'big5-hkscs' => true,
+                'shift_jis' => true, 'sjis' => true, '932' => true,
+                'euc-jp' => true, 'eucjp' => true,
+                'iso8859-5' => true, 'iso-8859-5' => true, 'macroman' => true,
+            );
+
+            if (isset($htmlspecialcharsCharsets[strtolower($charset)])) {
+                return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
+            }
+
+            $string = twig_convert_encoding($string, 'UTF-8', $charset);
+            $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
+
+            return twig_convert_encoding($string, $charset, 'UTF-8');
+
+        default:
+            throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: html, js).', $strategy));
+    }
+}
+
+/* used internally */
+function twig_escape_filter_is_safe(Twig_Node $filterArgs)
+{
+    foreach ($filterArgs as $arg) {
+        if ($arg instanceof Twig_Node_Expression_Constant) {
+            return array($arg->getAttribute('value'));
+        }
+
+        return array();
+    }
+
+    return array('html');
+}
+
+if (function_exists('mb_convert_encoding')) {
+    function twig_convert_encoding($string, $to, $from)
+    {
+        return mb_convert_encoding($string, $to, $from);
+    }
+} elseif (function_exists('iconv')) {
+    function twig_convert_encoding($string, $to, $from)
+    {
+        return iconv($from, $to, $string);
+    }
+} else {
+    function twig_convert_encoding($string, $to, $from)
+    {
+        throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
+    }
+}
+
+function _twig_escape_js_callback($matches)
+{
+    $char = $matches[0];
+
+    // \xHH
+    if (!isset($char[1])) {
+        return '\\x'.substr('00'.bin2hex($char), -2);
+    }
+
+    // \uHHHH
+    $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
+
+    return '\\u'.substr('0000'.bin2hex($char), -4);
+}
+
+// add multibyte extensions if possible
+if (function_exists('mb_get_info')) {
+    /**
+     * Returns the length of a variable.
+     *
+     * @param Twig_Environment $env   A Twig_Environment instance
+     * @param mixed            $thing A variable
+     *
+     * @return integer The length of the value
+     */
+    function twig_length_filter(Twig_Environment $env, $thing)
+    {
+        return is_scalar($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing);
+    }
+
+    /**
+     * Converts a string to uppercase.
+     *
+     * @param Twig_Environment $env    A Twig_Environment instance
+     * @param string           $string A string
+     *
+     * @return string The uppercased string
+     */
+    function twig_upper_filter(Twig_Environment $env, $string)
+    {
+        if (null !== ($charset = $env->getCharset())) {
+            return mb_strtoupper($string, $charset);
+        }
+
+        return strtoupper($string);
+    }
+
+    /**
+     * Converts a string to lowercase.
+     *
+     * @param Twig_Environment $env    A Twig_Environment instance
+     * @param string           $string A string
+     *
+     * @return string The lowercased string
+     */
+    function twig_lower_filter(Twig_Environment $env, $string)
+    {
+        if (null !== ($charset = $env->getCharset())) {
+            return mb_strtolower($string, $charset);
+        }
+
+        return strtolower($string);
+    }
+
+    /**
+     * Returns a titlecased string.
+     *
+     * @param Twig_Environment $env    A Twig_Environment instance
+     * @param string           $string A string
+     *
+     * @return string The titlecased string
+     */
+    function twig_title_string_filter(Twig_Environment $env, $string)
+    {
+        if (null !== ($charset = $env->getCharset())) {
+            return mb_convert_case($string, MB_CASE_TITLE, $charset);
+        }
+
+        return ucwords(strtolower($string));
+    }
+
+    /**
+     * Returns a capitalized string.
+     *
+     * @param Twig_Environment $env    A Twig_Environment instance
+     * @param string           $string A string
+     *
+     * @return string The capitalized string
+     */
+    function twig_capitalize_string_filter(Twig_Environment $env, $string)
+    {
+        if (null !== ($charset = $env->getCharset())) {
+            return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).
+                         mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
+        }
+
+        return ucfirst(strtolower($string));
+    }
+}
+// and byte fallback
+else
+{
+    /**
+     * Returns the length of a variable.
+     *
+     * @param Twig_Environment $env   A Twig_Environment instance
+     * @param mixed            $thing A variable
+     *
+     * @return integer The length of the value
+     */
+    function twig_length_filter(Twig_Environment $env, $thing)
+    {
+        return is_scalar($thing) ? strlen($thing) : count($thing);
+    }
+
+    /**
+     * Returns a titlecased string.
+     *
+     * @param Twig_Environment $env    A Twig_Environment instance
+     * @param string           $string A string
+     *
+     * @return string The titlecased string
+     */
+    function twig_title_string_filter(Twig_Environment $env, $string)
+    {
+        return ucwords(strtolower($string));
+    }
+
+    /**
+     * Returns a capitalized string.
+     *
+     * @param Twig_Environment $env    A Twig_Environment instance
+     * @param string           $string A string
+     *
+     * @return string The capitalized string
+     */
+    function twig_capitalize_string_filter(Twig_Environment $env, $string)
+    {
+        return ucfirst(strtolower($string));
+    }
+}
+
+/* used internally */
+function twig_ensure_traversable($seq)
+{
+    if ($seq instanceof Traversable || is_array($seq)) {
+        return $seq;
+    }
+
+    return array();
+}
+
+/**
+ * Checks if a variable is empty.
+ *
+ * <pre>
+ * {# evaluates to true if the foo variable is null, false, or the empty string #}
+ * {% if foo is empty %}
+ *     {# ... #}
+ * {% endif %}
+ * </pre>
+ *
+ * @param mixed $value A variable
+ *
+ * @return Boolean true if the value is empty, false otherwise
+ */
+function twig_test_empty($value)
+{
+    if ($value instanceof Countable) {
+        return 0 == count($value);
+    }
+
+    return false === $value || (empty($value) && '0' != $value);
+}
+
+/**
+ * Checks if a variable is traversable.
+ *
+ * <pre>
+ * {# evaluates to true if the foo variable is an array or a traversable object #}
+ * {% if foo is traversable %}
+ *     {# ... #}
+ * {% endif %}
+ * </pre>
+ *
+ * @param mixed $value A variable
+ *
+ * @return Boolean true if the value is traversable
+ */
+function twig_test_iterable($value)
+{
+    return $value instanceof Traversable || is_array($value);
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Debug.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Debug.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Debug.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Debug.php Sun May 27 19:59:46 2012
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Extension_Debug extends Twig_Extension
+{
+    /**
+     * Returns a list of global functions to add to the existing list.
+     *
+     * @return array An array of global functions
+     */
+    public function getFunctions()
+    {
+        // dump is safe if var_dump is overriden 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)),
+        );
+    }
+
+    /**
+     * Returns the name of the extension.
+     *
+     * @return string The extension name
+     */
+    public function getName()
+    {
+        return 'debug';
+    }
+}
+
+function twig_var_dump(Twig_Environment $env, $context)
+{
+    if (!$env->isDebug()) {
+        return;
+    }
+
+    ob_start();
+
+    $count = func_num_args();
+    if (2 === $count) {
+        $vars = array();
+        foreach ($context as $key => $value) {
+            if (!$value instanceof Twig_Template) {
+                $vars[$key] = $value;
+            }
+        }
+
+        var_dump($vars);
+    } else {
+        for ($i = 2; $i < $count; $i++) {
+            var_dump(func_get_arg($i));
+        }
+    }
+
+    return ob_get_clean();
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Escaper.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Escaper.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Escaper.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Escaper.php Sun May 27 19:59:46 2012
@@ -0,0 +1,106 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Extension_Escaper extends Twig_Extension
+{
+    protected $defaultStrategy;
+
+    public function __construct($defaultStrategy = 'html')
+    {
+        $this->setDefaultStrategy($defaultStrategy);
+    }
+
+    /**
+     * Returns the token parser instances to add to the existing list.
+     *
+     * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
+     */
+    public function getTokenParsers()
+    {
+        return array(new Twig_TokenParser_AutoEscape());
+    }
+
+    /**
+     * Returns the node visitor instances to add to the existing list.
+     *
+     * @return array An array of Twig_NodeVisitorInterface instances
+     */
+    public function getNodeVisitors()
+    {
+        return array(new Twig_NodeVisitor_Escaper());
+    }
+
+    /**
+     * Returns a list of filters to add to the existing list.
+     *
+     * @return array An array of filters
+     */
+    public function getFilters()
+    {
+        return array(
+            'raw' => new Twig_Filter_Function('twig_raw_filter', array('is_safe' => array('all'))),
+        );
+    }
+
+    /**
+     * 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)
+    {
+        // 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)
+    {
+        if (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
+     */
+    public function getName()
+    {
+        return 'escaper';
+    }
+}
+
+/**
+ * Marks a variable as being safe.
+ *
+ * @param string $string A PHP variable
+ */
+function twig_raw_filter($string)
+{
+    return $string;
+}
+

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Optimizer.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Optimizer.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Optimizer.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Optimizer.php Sun May 27 19:59:46 2012
@@ -0,0 +1,35 @@
+<?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.
+ */
+class Twig_Extension_Optimizer extends Twig_Extension
+{
+    protected $optimizers;
+
+    public function __construct($optimizers = -1)
+    {
+        $this->optimizers = $optimizers;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getNodeVisitors()
+    {
+        return array(new Twig_NodeVisitor_Optimizer($this->optimizers));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'optimizer';
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Sandbox.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Sandbox.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Sandbox.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Extension/Sandbox.php Sun May 27 19:59:46 2012
@@ -0,0 +1,112 @@
+<?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.
+ */
+class Twig_Extension_Sandbox extends Twig_Extension
+{
+    protected $sandboxedGlobally;
+    protected $sandboxed;
+    protected $policy;
+
+    public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
+    {
+        $this->policy            = $policy;
+        $this->sandboxedGlobally = $sandboxed;
+    }
+
+    /**
+     * Returns the token parser instances to add to the existing list.
+     *
+     * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
+     */
+    public function getTokenParsers()
+    {
+        return array(new Twig_TokenParser_Sandbox());
+    }
+
+    /**
+     * Returns the node visitor instances to add to the existing list.
+     *
+     * @return array An array of Twig_NodeVisitorInterface instances
+     */
+    public function getNodeVisitors()
+    {
+        return array(new Twig_NodeVisitor_Sandbox());
+    }
+
+    public function enableSandbox()
+    {
+        $this->sandboxed = true;
+    }
+
+    public function disableSandbox()
+    {
+        $this->sandboxed = false;
+    }
+
+    public function isSandboxed()
+    {
+        return $this->sandboxedGlobally || $this->sandboxed;
+    }
+
+    public function isSandboxedGlobally()
+    {
+        return $this->sandboxedGlobally;
+    }
+
+    public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy)
+    {
+        $this->policy = $policy;
+    }
+
+    public function getSecurityPolicy()
+    {
+        return $this->policy;
+    }
+
+    public function checkSecurity($tags, $filters, $functions)
+    {
+        if ($this->isSandboxed()) {
+            $this->policy->checkSecurity($tags, $filters, $functions);
+        }
+    }
+
+    public function checkMethodAllowed($obj, $method)
+    {
+        if ($this->isSandboxed()) {
+            $this->policy->checkMethodAllowed($obj, $method);
+        }
+    }
+
+    public function checkPropertyAllowed($obj, $method)
+    {
+        if ($this->isSandboxed()) {
+            $this->policy->checkPropertyAllowed($obj, $method);
+        }
+    }
+
+    public function ensureToStringAllowed($obj)
+    {
+        if (is_object($obj)) {
+            $this->policy->checkMethodAllowed($obj, '__toString');
+        }
+
+        return $obj;
+    }
+
+    /**
+     * Returns the name of the extension.
+     *
+     * @return string The extension name
+     */
+    public function getName()
+    {
+        return 'sandbox';
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/ExtensionInterface.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/ExtensionInterface.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/ExtensionInterface.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/ExtensionInterface.php Sun May 27 19:59:46 2012
@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Interface implemented by extension classes.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+interface Twig_ExtensionInterface
+{
+    /**
+     * Initializes the runtime environment.
+     *
+     * This is where you can load some file that contains filter functions for instance.
+     *
+     * @param Twig_Environment $environment The current Twig_Environment instance
+     */
+    function initRuntime(Twig_Environment $environment);
+
+    /**
+     * Returns the token parser instances to add to the existing list.
+     *
+     * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
+     */
+    function getTokenParsers();
+
+    /**
+     * Returns the node visitor instances to add to the existing list.
+     *
+     * @return array An array of Twig_NodeVisitorInterface instances
+     */
+    function getNodeVisitors();
+
+    /**
+     * Returns a list of filters to add to the existing list.
+     *
+     * @return array An array of filters
+     */
+    function getFilters();
+
+    /**
+     * Returns a list of tests to add to the existing list.
+     *
+     * @return array An array of tests
+     */
+    function getTests();
+
+    /**
+     * Returns a list of functions to add to the existing list.
+     *
+     * @return array An array of functions
+     */
+    function getFunctions();
+
+    /**
+     * Returns a list of operators to add to the existing list.
+     *
+     * @return array An array of operators
+     */
+    function getOperators();
+
+    /**
+     * Returns a list of global variables to add to the existing list.
+     *
+     * @return array An array of global variables
+     */
+    function getGlobals();
+
+    /**
+     * Returns the name of the extension.
+     *
+     * @return string The extension name
+     */
+    function getName();
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter.php Sun May 27 19:59:46 2012
@@ -0,0 +1,75 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template filter.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+abstract class Twig_Filter implements Twig_FilterInterface
+{
+    protected $options;
+    protected $arguments = array();
+
+    public function __construct(array $options = array())
+    {
+        $this->options = array_merge(array(
+            'needs_environment' => false,
+            'needs_context'     => false,
+            'pre_escape'        => null,
+            'preserves_safety'  => null,
+        ), $options);
+    }
+
+    public function setArguments($arguments)
+    {
+        $this->arguments = $arguments;
+    }
+
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+
+    public function needsEnvironment()
+    {
+        return $this->options['needs_environment'];
+    }
+
+    public function needsContext()
+    {
+        return $this->options['needs_context'];
+    }
+
+    public function getSafe(Twig_Node $filterArgs)
+    {
+        if (isset($this->options['is_safe'])) {
+            return $this->options['is_safe'];
+        }
+
+        if (isset($this->options['is_safe_callback'])) {
+            return call_user_func($this->options['is_safe_callback'], $filterArgs);
+        }
+
+        return null;
+    }
+
+    public function getPreservesSafety()
+    {
+        return $this->options['preserves_safety'];
+    }
+
+    public function getPreEscape()
+    {
+        return $this->options['pre_escape'];
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Function.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Function.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Function.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Function.php Sun May 27 19:59:46 2012
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a function template filter.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Filter_Function extends Twig_Filter
+{
+    protected $function;
+
+    public function __construct($function, array $options = array())
+    {
+        parent::__construct($options);
+
+        $this->function = $function;
+    }
+
+    public function compile()
+    {
+        return $this->function;
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Method.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Method.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Method.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Method.php Sun May 27 19:59:46 2012
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a method template filter.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Filter_Method extends Twig_Filter
+{
+    protected $extension;
+    protected $method;
+
+    public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
+    {
+        parent::__construct($options);
+
+        $this->extension = $extension;
+        $this->method = $method;
+    }
+
+    public function compile()
+    {
+        return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Node.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Node.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Node.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Filter/Node.php Sun May 27 19:59:46 2012
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template filter as a node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Filter_Node extends Twig_Filter
+{
+    protected $class;
+
+    public function __construct($class, array $options = array())
+    {
+        parent::__construct($options);
+
+        $this->class = $class;
+    }
+
+    public function getClass()
+    {
+        return $this->class;
+    }
+
+    public function compile()
+    {
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/FilterInterface.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/FilterInterface.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/FilterInterface.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/FilterInterface.php Sun May 27 19:59:46 2012
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template filter.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+interface Twig_FilterInterface
+{
+    /**
+     * Compiles a filter.
+     *
+     * @return string The PHP code for the filter
+     */
+    function compile();
+
+    function needsEnvironment();
+
+    function needsContext();
+
+    function getSafe(Twig_Node $filterArgs);
+
+    function getPreservesSafety();
+
+    function getPreEscape();
+
+    function setArguments($arguments);
+
+    function getArguments();
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function.php Sun May 27 19:59:46 2012
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template function.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+abstract class Twig_Function implements Twig_FunctionInterface
+{
+    protected $options;
+    protected $arguments = array();
+
+    public function __construct(array $options = array())
+    {
+        $this->options = array_merge(array(
+            'needs_environment' => false,
+            'needs_context'     => false,
+        ), $options);
+    }
+
+    public function setArguments($arguments)
+    {
+        $this->arguments = $arguments;
+    }
+
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+
+    public function needsEnvironment()
+    {
+        return $this->options['needs_environment'];
+    }
+
+    public function needsContext()
+    {
+        return $this->options['needs_context'];
+    }
+
+    public function getSafe(Twig_Node $functionArgs)
+    {
+        if (isset($this->options['is_safe'])) {
+            return $this->options['is_safe'];
+        }
+
+        if (isset($this->options['is_safe_callback'])) {
+            return call_user_func($this->options['is_safe_callback'], $functionArgs);
+        }
+
+        return array();
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Function.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Function.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Function.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Function.php Sun May 27 19:59:46 2012
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2010 Arnaud Le Blanc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a function template function.
+ *
+ * @package    twig
+ * @author     Arnaud Le Blanc <ar...@gmail.com>
+ */
+class Twig_Function_Function extends Twig_Function
+{
+    protected $function;
+
+    public function __construct($function, array $options = array())
+    {
+        parent::__construct($options);
+
+        $this->function = $function;
+    }
+
+    public function compile()
+    {
+        return $this->function;
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Method.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Method.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Method.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Method.php Sun May 27 19:59:46 2012
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ * (c) 2010 Arnaud Le Blanc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a method template function.
+ *
+ * @package    twig
+ * @author     Arnaud Le Blanc <ar...@gmail.com>
+ */
+class Twig_Function_Method extends Twig_Function
+{
+    protected $extension;
+    protected $method;
+
+    public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
+    {
+        parent::__construct($options);
+
+        $this->extension = $extension;
+        $this->method = $method;
+    }
+
+    public function compile()
+    {
+        return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Node.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Node.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Node.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/Function/Node.php Sun May 27 19:59:46 2012
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template function as a node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fa...@symfony.com>
+ */
+class Twig_Function_Node extends Twig_Filter
+{
+    protected $class;
+
+    public function __construct($class, array $options = array())
+    {
+        parent::__construct($options);
+
+        $this->class = $class;
+    }
+
+    public function getClass()
+    {
+        return $this->class;
+    }
+
+    public function compile()
+    {
+    }
+}

Added: logging/site/branches/cms/trunk/libs/Twig/lib/Twig/FunctionInterface.php
URL: http://svn.apache.org/viewvc/logging/site/branches/cms/trunk/libs/Twig/lib/Twig/FunctionInterface.php?rev=1343084&view=auto
==============================================================================
--- logging/site/branches/cms/trunk/libs/Twig/lib/Twig/FunctionInterface.php (added)
+++ logging/site/branches/cms/trunk/libs/Twig/lib/Twig/FunctionInterface.php Sun May 27 19:59:46 2012
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010 Fabien Potencier
+ * (c) 2010 Arnaud Le Blanc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template function.
+ *
+ * @package    twig
+ * @author     Arnaud Le Blanc <ar...@gmail.com>
+ */
+interface Twig_FunctionInterface
+{
+    /**
+     * Compiles a function.
+     *
+     * @return string The PHP code for the function
+     */
+    function compile();
+
+    function needsEnvironment();
+
+    function needsContext();
+
+    function getSafe(Twig_Node $filterArgs);
+
+    function setArguments($arguments);
+
+    function getArguments();
+}