From af1ca73aca00b61fe155b4c3f8a565d71312ab6e Mon Sep 17 00:00:00 2001
From: webchick <webchick@24967.no-reply.drupal.org>
Date: Fri, 17 Jan 2014 14:04:01 -0800
Subject: [PATCH] Issue #2172235 by joelpittet: Upgrade Twig to 1.15.* from
 1.12.*.

---
 composer.json                                 |   2 +-
 composer.lock                                 |  16 +-
 core/vendor/twig/twig/.travis.yml             |   1 +
 core/vendor/twig/twig/AUTHORS                 |   4 +
 core/vendor/twig/twig/CHANGELOG               |  56 ++++
 .../twig/twig/{README.markdown => README.rst} |   6 +-
 core/vendor/twig/twig/composer.json           |   4 +-
 core/vendor/twig/twig/doc/advanced.rst        | 114 +++++--
 core/vendor/twig/twig/doc/advanced_legacy.rst |   8 +-
 core/vendor/twig/twig/doc/api.rst             |  26 +-
 .../vendor/twig/twig/doc/coding_standards.rst |   2 +-
 core/vendor/twig/twig/doc/deprecated.rst      |   7 +-
 core/vendor/twig/twig/doc/filters/abs.rst     |   4 +-
 core/vendor/twig/twig/doc/filters/batch.rst   |  34 +-
 .../twig/doc/filters/convert_encoding.rst     |   4 +-
 core/vendor/twig/twig/doc/filters/date.rst    |  16 +-
 .../twig/twig/doc/filters/date_modify.rst     |   2 +-
 core/vendor/twig/twig/doc/filters/default.rst |   2 +-
 core/vendor/twig/twig/doc/filters/escape.rst  |  27 +-
 core/vendor/twig/twig/doc/filters/format.rst  |   6 +-
 core/vendor/twig/twig/doc/filters/index.rst   |   1 +
 core/vendor/twig/twig/doc/filters/join.rst    |   4 +-
 .../twig/twig/doc/filters/json_encode.rst     |   4 +-
 core/vendor/twig/twig/doc/filters/length.rst  |   1 -
 .../twig/twig/doc/filters/number_format.rst   |  12 +-
 core/vendor/twig/twig/doc/filters/raw.rst     |   2 +-
 core/vendor/twig/twig/doc/filters/replace.rst |   4 +-
 core/vendor/twig/twig/doc/filters/reverse.rst |  26 +-
 core/vendor/twig/twig/doc/filters/round.rst   |  37 +++
 core/vendor/twig/twig/doc/filters/slice.rst   |  20 +-
 core/vendor/twig/twig/doc/filters/split.rst   |   4 +-
 core/vendor/twig/twig/doc/filters/trim.rst    |   2 +-
 .../twig/twig/doc/filters/url_encode.rst      |   9 +-
 core/vendor/twig/twig/doc/functions/cycle.rst |   2 +-
 core/vendor/twig/twig/doc/functions/date.rst  |   8 +-
 core/vendor/twig/twig/doc/functions/dump.rst  |   2 +-
 .../twig/twig/doc/functions/include.rst       |  10 +-
 core/vendor/twig/twig/doc/functions/index.rst |   3 +
 core/vendor/twig/twig/doc/functions/max.rst   |  19 ++
 core/vendor/twig/twig/doc/functions/min.rst   |  19 ++
 .../vendor/twig/twig/doc/functions/random.rst |   4 +-
 core/vendor/twig/twig/doc/functions/range.rst |  10 +-
 .../vendor/twig/twig/doc/functions/source.rst |  21 ++
 .../doc/functions/template_from_string.rst    |   4 +-
 core/vendor/twig/twig/doc/index.rst           |   1 +
 core/vendor/twig/twig/doc/installation.rst    | 118 +++++++
 core/vendor/twig/twig/doc/internals.rst       |  24 +-
 core/vendor/twig/twig/doc/intro.rst           | 111 +------
 core/vendor/twig/twig/doc/recipes.rst         |   2 +-
 core/vendor/twig/twig/doc/tags/extends.rst    |   2 +-
 core/vendor/twig/twig/doc/tags/from.rst       |   2 +-
 core/vendor/twig/twig/doc/tags/if.rst         |   2 +-
 core/vendor/twig/twig/doc/tags/import.rst     |   2 +-
 core/vendor/twig/twig/doc/tags/include.rst    |   4 +-
 core/vendor/twig/twig/doc/tags/macro.rst      |   2 +-
 core/vendor/twig/twig/doc/tags/set.rst        |  60 +++-
 core/vendor/twig/twig/doc/tags/use.rst        |   2 +-
 core/vendor/twig/twig/doc/templates.rst       |  73 +++--
 core/vendor/twig/twig/doc/tests/constant.rst  |  11 +
 .../twig/twig/doc/tests/divisibleby.rst       |  12 +-
 core/vendor/twig/twig/doc/tests/sameas.rst    |  15 +-
 core/vendor/twig/twig/ext/twig/LICENSE        |  45 +--
 core/vendor/twig/twig/ext/twig/php_twig.h     |   4 +-
 core/vendor/twig/twig/ext/twig/twig.c         | 266 ++++++++-------
 core/vendor/twig/twig/lib/Twig/Autoloader.php |  11 +-
 core/vendor/twig/twig/lib/Twig/Compiler.php   |   7 +-
 .../vendor/twig/twig/lib/Twig/Environment.php |  85 +++--
 core/vendor/twig/twig/lib/Twig/Error.php      |  20 +-
 .../twig/lib/Twig/ExistsLoaderInterface.php   |   2 +-
 .../twig/twig/lib/Twig/ExpressionParser.php   |  46 ++-
 core/vendor/twig/twig/lib/Twig/Extension.php  |   2 +-
 .../twig/twig/lib/Twig/Extension/Core.php     | 302 ++++++++++++------
 .../twig/twig/lib/Twig/Extension/Debug.php    |   1 +
 .../twig/twig/lib/Twig/Extension/Escaper.php  |   2 +-
 .../twig/twig/lib/Twig/Extension/Sandbox.php  |   2 +-
 .../twig/lib/Twig/Extension/StringLoader.php  |  14 +-
 .../twig/twig/lib/Twig/ExtensionInterface.php |   2 +-
 core/vendor/twig/twig/lib/Twig/Filter.php     |   2 -
 core/vendor/twig/twig/lib/Twig/Lexer.php      |  19 +-
 .../twig/twig/lib/Twig/LexerInterface.php     |   2 +
 .../twig/twig/lib/Twig/Loader/Array.php       |   7 +-
 .../twig/twig/lib/Twig/Loader/Chain.php       |  11 +-
 .../twig/twig/lib/Twig/Loader/Filesystem.php  |  33 +-
 .../Twig/Node/Expression/Binary/EndsWith.php  |  30 ++
 .../Twig/Node/Expression/Binary/Matches.php   |  28 ++
 .../Node/Expression/Binary/StartsWith.php     |  28 ++
 .../twig/lib/Twig/Node/Expression/Call.php    |  11 +-
 .../twig/lib/Twig/Node/Expression/GetAttr.php |   4 +-
 .../Twig/Node/Expression/Test/Constant.php    |  11 +
 .../lib/Twig/Node/Expression/Test/Defined.php |   2 +-
 core/vendor/twig/twig/lib/Twig/Node/For.php   |   2 +-
 core/vendor/twig/twig/lib/Twig/Node/If.php    |   2 +-
 .../twig/twig/lib/Twig/NodeTraverser.php      |   6 +-
 .../twig/lib/Twig/NodeVisitor/Optimizer.php   |  12 +-
 .../lib/Twig/NodeVisitor/SafeAnalysis.php     |  20 +-
 core/vendor/twig/twig/lib/Twig/Parser.php     |  12 +-
 .../twig/twig/lib/Twig/ParserInterface.php    |   2 +
 .../twig/twig/lib/Twig/SimpleFilter.php       |   2 -
 core/vendor/twig/twig/lib/Twig/Template.php   |  71 ++--
 core/vendor/twig/twig/lib/Twig/Token.php      |   6 +-
 .../twig/twig/lib/Twig/TokenParser/Block.php  |   8 +-
 .../twig/lib/Twig/TokenParser/Extends.php     |   2 -
 .../twig/twig/lib/Twig/TokenParser/For.php    |   3 +-
 .../twig/twig/lib/Twig/TokenParser/From.php   |   8 +-
 .../twig/lib/Twig/TokenParser/Include.php     |  11 +-
 .../twig/twig/lib/Twig/TokenParser/Macro.php  |   6 +-
 .../twig/twig/lib/Twig/TokenParser/Set.php    |   3 +-
 .../twig/twig/lib/Twig/TokenParser/Use.php    |  14 +-
 .../twig/twig/lib/Twig/TokenParserBroker.php  |   2 -
 .../twig/lib/Twig/TokenParserInterface.php    |   2 +
 .../vendor/twig/twig/lib/Twig/TokenStream.php |  16 +-
 .../twig/test/Twig/Tests/CompilerTest.php     |   6 +-
 .../twig/test/Twig/Tests/EnvironmentTest.php  |  10 +-
 .../twig/twig/test/Twig/Tests/ErrorTest.php   | 147 ++++-----
 .../test/Twig/Tests/Extension/CoreTest.php    |  25 +-
 .../test/Twig/Tests/Extension/SandboxTest.php |   3 +
 .../Fixtures/expressions/divisibleby.test     |  21 ++
 .../Tests/Fixtures/expressions/ends_with.test |  12 +
 .../Tests/Fixtures/expressions/matches.test   |  12 +
 .../expressions/operators_as_variables.test   |  16 +
 .../Tests/Fixtures/expressions/sameas.test    |  21 ++
 .../Fixtures/expressions/starts_with.test     |  17 +
 .../two_word_operators_as_variables.test      |   8 +
 .../filters/batch_with_exact_elements.test    |  33 ++
 .../Fixtures/filters/date_immutable.test      |  35 ++
 .../Fixtures/filters/date_namedargs.test      |   2 -
 .../Fixtures/filters/escape_html_attr.test    |   8 +
 .../Twig/Tests/Fixtures/filters/first.test    |   2 +
 .../Twig/Tests/Fixtures/filters/last.test     |   2 +
 .../Twig/Tests/Fixtures/filters/round.test    |  22 ++
 .../Tests/Fixtures/filters/special_chars.test |   6 +-
 .../Twig/Tests/Fixtures/functions/date.test   |   2 -
 .../functions/include/assignment.test         |  13 +
 .../functions/include/autoescaping.test       |  10 +
 .../Twig/Tests/Fixtures/functions/max.test    |  12 +
 .../Twig/Tests/Fixtures/functions/min.test    |  12 +
 .../Twig/Tests/Fixtures/functions/source.test |  17 +
 .../Fixtures/functions/special_chars.test     |   6 +-
 .../functions/template_from_string.test       |   4 +
 .../Tests/Fixtures/regression/issue_1143.test |  23 ++
 .../regression/simple_xml_element.test        |   2 +-
 .../Fixtures/tags/block/special_chars.test    |  10 +-
 .../Tests/Fixtures/tags/embed/error_line.test |  16 +
 .../Fixtures/tags/macro/special_chars.test    |  10 +-
 .../Tests/Fixtures/tags/special_chars.test    |   6 +-
 .../Twig/Tests/Fixtures/tests/constant.test   |   4 +-
 .../twig/test/Twig/Tests/IntegrationTest.php  |  42 +--
 .../twig/twig/test/Twig/Tests/LexerTest.php   |  30 +-
 .../twig/test/Twig/Tests/Loader/ChainTest.php |  16 +
 .../test/Twig/Tests/Loader/FilesystemTest.php |  56 +++-
 .../Fixtures/themes/theme1/blocks.html.twig   |   3 +
 .../Fixtures/themes/theme2/blocks.html.twig   |   3 +
 .../test/Twig/Tests/NativeExtensionTest.php   |   6 +-
 .../Twig/Tests/Node/Expression/CallTest.php   |  67 ++++
 .../Tests/Node/Expression/FunctionTest.php    |   8 +-
 .../Tests/Node/Expression/GetAttrTest.php     |  10 +-
 .../twig/test/Twig/Tests/Node/ForTest.php     |   8 +-
 .../twig/test/Twig/Tests/Node/ModuleTest.php  |   6 +-
 .../Twig/Tests/Node/SandboxedModuleTest.php   |   4 +-
 .../twig/test/Twig/Tests/TemplateTest.php     | 118 ++++++-
 .../twig/test/Twig/Tests/escapingTest.php     |  12 +-
 core/vendor/twig/twig/test/bootstrap.php      |   2 +-
 162 files changed, 2243 insertions(+), 924 deletions(-)
 rename core/vendor/twig/twig/{README.markdown => README.rst} (64%)
 create mode 100644 core/vendor/twig/twig/doc/filters/round.rst
 create mode 100644 core/vendor/twig/twig/doc/functions/max.rst
 create mode 100644 core/vendor/twig/twig/doc/functions/min.rst
 create mode 100644 core/vendor/twig/twig/doc/functions/source.rst
 create mode 100644 core/vendor/twig/twig/doc/installation.rst
 create mode 100644 core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php
 create mode 100644 core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php
 create mode 100644 core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/divisibleby.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/matches.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/operators_as_variables.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/sameas.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/two_word_operators_as_variables.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_exact_elements.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_html_attr.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/round.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/assignment.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/autoescaping.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/max.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/min.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/source.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/issue_1143.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/error_line.test
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme1/blocks.html.twig
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme2/blocks.html.twig
 create mode 100644 core/vendor/twig/twig/test/Twig/Tests/Node/Expression/CallTest.php

diff --git a/composer.json b/composer.json
index 7d460ed48638..874c457f87b1 100644
--- a/composer.json
+++ b/composer.json
@@ -19,7 +19,7 @@
     "symfony/serializer": "2.3.*",
     "symfony/validator": "2.3.*",
     "symfony/yaml": "2.3.*",
-    "twig/twig": "1.12.*",
+    "twig/twig": "1.15.*",
     "doctrine/common": "dev-bmaster#99b44f52a1b844f9c4c34e618b160664d5c27daf",
     "doctrine/annotations": "dev-master#463d926a8dcc49271cb7db5a08364a70ed6e3cd3",
     "guzzle/http": "3.7.*",
diff --git a/composer.lock b/composer.lock
index 185081677568..59cdcd83545a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -3,7 +3,7 @@
         "This file locks the dependencies of your project to a known state",
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
     ],
-    "hash": "06006c1512fb829fcdb498b7e515901d",
+    "hash": "14b55ea7402f04abe36b677892e442f3",
     "packages": [
         {
             "name": "doctrine/annotations",
@@ -1877,16 +1877,16 @@
         },
         {
             "name": "twig/twig",
-            "version": "v1.12.3",
+            "version": "v1.15.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/fabpot/Twig.git",
-                "reference": "v1.12.3"
+                "reference": "85e4ff98000157ff753d934b9f13659a953f5666"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/fabpot/Twig/zipball/v1.12.3",
-                "reference": "v1.12.3",
+                "url": "https://api.github.com/repos/fabpot/Twig/zipball/85e4ff98000157ff753d934b9f13659a953f5666",
+                "reference": "85e4ff98000157ff753d934b9f13659a953f5666",
                 "shasum": ""
             },
             "require": {
@@ -1895,7 +1895,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.12-dev"
+                    "dev-master": "1.15-dev"
                 }
             },
             "autoload": {
@@ -1905,7 +1905,7 @@
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
-                "BSD-3"
+                "BSD-3-Clause"
             ],
             "authors": [
                 {
@@ -1922,7 +1922,7 @@
             "keywords": [
                 "templating"
             ],
-            "time": "2013-04-08 12:40:11"
+            "time": "2013-12-06 07:47:10"
         },
         {
             "name": "zendframework/zend-escaper",
diff --git a/core/vendor/twig/twig/.travis.yml b/core/vendor/twig/twig/.travis.yml
index e6d3b61cf41f..8569a3952adf 100644
--- a/core/vendor/twig/twig/.travis.yml
+++ b/core/vendor/twig/twig/.travis.yml
@@ -4,6 +4,7 @@ php:
   - 5.2
   - 5.3
   - 5.4
+  - 5.5
 
 env:
   - TWIG_EXT=no
diff --git a/core/vendor/twig/twig/AUTHORS b/core/vendor/twig/twig/AUTHORS
index eb5db0516b33..97571058841f 100644
--- a/core/vendor/twig/twig/AUTHORS
+++ b/core/vendor/twig/twig/AUTHORS
@@ -4,6 +4,10 @@ Lead Developer:
 
 - Fabien Potencier <fabien.potencier@symfony-project.org>
 
+C Extension Developer:
+
+- Derick Rethans <derick@derickrethans.nl>
+
 Project Founder:
 
 - Armin Ronacher <armin.ronacher@active-4.com>
diff --git a/core/vendor/twig/twig/CHANGELOG b/core/vendor/twig/twig/CHANGELOG
index 6b2af3e058c0..6c39f7dd46f4 100644
--- a/core/vendor/twig/twig/CHANGELOG
+++ b/core/vendor/twig/twig/CHANGELOG
@@ -1,3 +1,59 @@
+* 1.15.0 (2013-12-06)
+
+ * made ignoreStrictCheck in Template::getAttribute() works with __call() methods throwing BadMethodCallException
+ * added min and max functions
+ * added the round filter
+ * fixed a bug that prevented the optimizers to be enabled/disabled selectively
+ * fixed first and last filters for UTF-8 strings
+ * added a source function to include the content of a template without rendering it
+ * fixed the C extension sandbox behavior when get or set is prepend to method name
+
+* 1.14.2 (2013-10-30)
+
+ * fixed error filename/line when an error occurs in an included file
+ * allowed operators that contain whitespaces to have more than one whitespace
+ * allowed tests to be made of 1 or 2 words (like "same as" or "divisible by")
+
+* 1.14.1 (2013-10-15)
+
+ * made it possible to use named operators as variables
+ * fixed the possibility to have a variable named 'matches'
+ * added support for PHP 5.5 DateTimeInterface
+
+* 1.14.0 (2013-10-03)
+
+ * fixed usage of the html_attr escaping strategy to avoid double-escaping with the html strategy
+ * added new operators: ends with, starts with, and matches
+ * fixed some compatibility issues with HHVM
+ * added a way to add custom escaping strategies
+ * fixed the C extension compilation on Windows
+ * fixed the batch filter when using a fill argument with an exact match of elements to batch
+ * fixed the filesystem loader cache when a template name exists in several namespaces
+ * fixed template_from_string when the template includes or extends other ones
+ * fixed a crash of the C extension on an edge case
+
+* 1.13.2 (2013-08-03)
+
+ * fixed the error line number for an error occurs in and embedded template
+ * fixed crashes of the C extension on some edge cases
+
+* 1.13.1 (2013-06-06)
+
+ * added the possibility to ignore the filesystem constructor argument in Twig_Loader_Filesystem
+ * fixed Twig_Loader_Chain::exists() for a loader which implements Twig_ExistsLoaderInterface
+ * adjusted backtrace call to reduce memory usage when an error occurs
+ * added support for object instances as the second argument of the constant test
+ * fixed the include function when used in an assignment
+
+* 1.13.0 (2013-05-10)
+
+ * fixed getting a numeric-like item on a variable ('09' for instance)
+ * fixed getting a boolean or float key on an array, so it is consistent with PHP's array access:
+   `{{ array[false] }}` behaves the same as `echo $array[false];` (equals `$array[0]`)
+ * made the escape filter 20% faster for happy path (escaping string for html with UTF-8)
+ * changed ☃ to § in tests
+ * enforced usage of named arguments after positional ones
+
 * 1.12.3 (2013-04-08)
 
  * fixed a security issue in the filesystem loader where it was possible to include a template one
diff --git a/core/vendor/twig/twig/README.markdown b/core/vendor/twig/twig/README.rst
similarity index 64%
rename from core/vendor/twig/twig/README.markdown
rename to core/vendor/twig/twig/README.rst
index 88d6fabc0701..81737b0b2c2b 100644
--- a/core/vendor/twig/twig/README.markdown
+++ b/core/vendor/twig/twig/README.rst
@@ -1,8 +1,6 @@
 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).
 
@@ -12,6 +10,6 @@ inspired the Twig runtime environment.
 More Information
 ----------------
 
-Read the [documentation][1] for more information.
+Read the `documentation`_ for more information.
 
-[1]: http://twig.sensiolabs.org/documentation
+.. _documentation: http://twig.sensiolabs.org/documentation
diff --git a/core/vendor/twig/twig/composer.json b/core/vendor/twig/twig/composer.json
index 5530d282e524..799a3ebecc6f 100644
--- a/core/vendor/twig/twig/composer.json
+++ b/core/vendor/twig/twig/composer.json
@@ -4,7 +4,7 @@
     "description": "Twig, the flexible, fast, and secure template language for PHP",
     "keywords": ["templating"],
     "homepage": "http://twig.sensiolabs.org",
-    "license": "BSD-3",
+    "license": "BSD-3-Clause",
     "authors": [
         {
             "name": "Fabien Potencier",
@@ -25,7 +25,7 @@
     },
     "extra": {
         "branch-alias": {
-            "dev-master": "1.12-dev"
+            "dev-master": "1.15-dev"
         }
     }
 }
diff --git a/core/vendor/twig/twig/doc/advanced.rst b/core/vendor/twig/twig/doc/advanced.rst
index 06ad7711c098..ea82ce066efa 100644
--- a/core/vendor/twig/twig/doc/advanced.rst
+++ b/core/vendor/twig/twig/doc/advanced.rst
@@ -177,7 +177,7 @@ argument::
 
     $filter = new Twig_SimpleFilter('rot13', 'str_rot13', $options);
 
-Environment aware Filters
+Environment-aware Filters
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 If you want to access the current environment instance in your filter, set the
@@ -191,7 +191,7 @@ environment as the first argument to the filter call::
         return str_rot13($string);
     }, array('needs_environment' => true));
 
-Context aware Filters
+Context-aware Filters
 ~~~~~~~~~~~~~~~~~~~~~
 
 If you want to access the current context in your filter, set the
@@ -211,14 +211,14 @@ Automatic Escaping
 ~~~~~~~~~~~~~~~~~~
 
 If automatic escaping is enabled, the output of the filter may be escaped
-before printing. If your filter acts as an escaper (or explicitly outputs html
+before printing. If your filter acts as an escaper (or explicitly outputs HTML
 or JavaScript code), you will want the raw output to be printed. In such a
 case, set the ``is_safe`` option::
 
     $filter = new Twig_SimpleFilter('nl2br', 'nl2br', array('is_safe' => array('html')));
 
 Some filters may need to work on input that is already escaped or safe, for
-example when adding (safe) html tags to originally unsafe output. In such a
+example when adding (safe) HTML tags to originally unsafe output. In such a
 case, set the ``pre_escape`` option to escape the input data before it is run
 through your filter::
 
@@ -241,11 +241,11 @@ The following filters will be matched by the above defined dynamic filter:
 
 A dynamic filter can define more than one dynamic parts::
 
-    $filter = new Twig_SimpleFilter('*_path', function ($name, $suffix, $arguments) {
+    $filter = new Twig_SimpleFilter('*_path_*', function ($name, $suffix, $arguments) {
         // ...
     });
 
-The filter will receive all dynamic part values before the normal filters
+The filter will receive all dynamic part values before the normal filter
 arguments, but after the environment and the context. For instance, a call to
 ``'foo'|a_path_b()`` will result in the following arguments to be passed to
 the filter: ``('a', 'b', 'foo')``.
@@ -277,12 +277,64 @@ to create an instance of ``Twig_SimpleTest``::
     });
     $twig->addTest($test);
 
-Tests do not support any options.
+Tests allow you to create custom application specific logic for evaluating
+boolean conditions. As a simple example, let's create a Twig test that checks if
+objects are 'red'::
+
+    $twig = new Twig_Environment($loader)
+    $test = new Twig_SimpleTest('red', function ($value) {
+        if (isset($value->color) && $value->color == 'red') {
+            return true;
+        }
+        if (isset($value->paint) && $value->paint == 'red') {
+            return true;
+        }
+        return false;
+    });
+    $twig->addTest($test);
+
+Test functions should always return true/false.
+
+When creating tests you can use the ``node_class`` option to provide custom test
+compilation. This is useful if your test can be compiled into PHP primitives.
+This is used by many of the tests built into Twig::
+
+    $twig = new Twig_Environment($loader)
+    $test = new Twig_SimpleTest(
+        'odd',
+        null,
+        array('node_class' => 'Twig_Node_Expression_Test_Odd'));
+    $twig->addTest($test);
+
+    class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
+    {
+        public function compile(Twig_Compiler $compiler)
+        {
+            $compiler
+                ->raw('(')
+                ->subcompile($this->getNode('node'))
+                ->raw(' % 2 == 1')
+                ->raw(')')
+            ;
+        }
+    }
+
+The above example shows how you can create tests that use a node class. The
+node class has access to one sub-node called 'node'. This sub-node contains the
+value that is being tested. When the ``odd`` filter is used in code such as:
+
+.. code-block:: jinja
+
+    {% if my_value is odd %}
+
+The ``node`` sub-node will contain an expression of ``my_value``. Node-based
+tests also have access to the ``arguments`` node. This node will contain the
+various other arguments that have been provided to your test.
 
 Tags
 ----
 
-One of the most exciting feature of a template engine like Twig is the
+One of the most exciting features of a template engine like Twig is the
 possibility to define new language constructs. This is also the most complex
 feature as you need to understand how Twig's internals work.
 
@@ -330,14 +382,15 @@ Now, let's see the actual code of this class::
     {
         public function parse(Twig_Token $token)
         {
-            $lineno = $token->getLine();
-            $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue();
-            $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, '=');
-            $value = $this->parser->getExpressionParser()->parseExpression();
+            $parser = $this->parser;
+            $stream = $parser->getStream();
 
-            $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+            $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
+            $stream->expect(Twig_Token::OPERATOR_TYPE, '=');
+            $value = $parser->getExpressionParser()->parseExpression();
+            $stream->expect(Twig_Token::BLOCK_END_TYPE);
 
-            return new Project_Set_Node($name, $value, $lineno, $this->getTag());
+            return new Project_Set_Node($name, $value, $token->getLine(), $this->getTag());
         }
 
         public function getTag()
@@ -384,9 +437,9 @@ The ``Project_Set_Node`` class itself is rather simple::
 
     class Project_Set_Node extends Twig_Node
     {
-        public function __construct($name, Twig_Node_Expression $value, $lineno, $tag = null)
+        public function __construct($name, Twig_Node_Expression $value, $line, $tag = null)
         {
-            parent::__construct(array('value' => $value), array('name' => $name), $lineno, $tag);
+            parent::__construct(array('value' => $value), array('name' => $name), $line, $tag);
         }
 
         public function compile(Twig_Compiler $compiler)
@@ -640,7 +693,7 @@ responsible for parsing the tag and compiling it to PHP.
 Operators
 ~~~~~~~~~
 
-The ``getOperators()`` methods allows to add new operators. Here is how to add
+The ``getOperators()`` methods lets you add new operators. Here is how to add
 ``!``, ``||``, and ``&&`` operators::
 
     class Project_Twig_Extension extends Twig_Extension
@@ -664,7 +717,7 @@ The ``getOperators()`` methods allows to add new operators. Here is how to add
 Tests
 ~~~~~
 
-The ``getTests()`` methods allows to add new test functions::
+The ``getTests()`` method lets you add new test functions::
 
     class Project_Twig_Extension extends Twig_Extension
     {
@@ -682,16 +735,8 @@ Overloading
 -----------
 
 To overload an already defined filter, test, operator, global variable, or
-function, define it again **as late as possible**::
-
-    $twig = new Twig_Environment($loader);
-    $twig->addFilter(new Twig_SimpleFilter('date', function ($timestamp, $format = 'F j, Y H:i') {
-        // do something different from the built-in date filter
-    }));
-
-Here, we have overloaded the built-in ``date`` filter with a custom one.
-
-That also works with an extension::
+function, re-define it in an extension and register it **as late as
+possible** (order matters)::
 
     class MyCoreExtension extends Twig_Extension
     {
@@ -716,6 +761,19 @@ That also works with an extension::
     $twig = new Twig_Environment($loader);
     $twig->addExtension(new MyCoreExtension());
 
+Here, we have overloaded the built-in ``date`` filter with a custom one.
+
+If you do the same on the Twig_Environment itself, beware that it takes
+precedence over any other registered extensions::
+
+    $twig = new Twig_Environment($loader);
+    $twig->addFilter(new Twig_SimpleFilter('date', function ($timestamp, $format = 'F j, Y H:i') {
+        // do something different from the built-in date filter
+    }));
+    // the date filter will come from the above registration, not
+    // from the registered extension below
+    $twig->addExtension(new MyCoreExtension());
+
 .. caution::
 
     Note that overloading the built-in Twig elements is not recommended as it
diff --git a/core/vendor/twig/twig/doc/advanced_legacy.rst b/core/vendor/twig/twig/doc/advanced_legacy.rst
index 8dbc52519b60..2b3318020ad4 100644
--- a/core/vendor/twig/twig/doc/advanced_legacy.rst
+++ b/core/vendor/twig/twig/doc/advanced_legacy.rst
@@ -244,14 +244,14 @@ Automatic Escaping
 ~~~~~~~~~~~~~~~~~~
 
 If automatic escaping is enabled, the output of the filter may be escaped
-before printing. If your filter acts as an escaper (or explicitly outputs html
-or javascript code), you will want the raw output to be printed. In such a
+before printing. If your filter acts as an escaper (or explicitly outputs HTML
+or JavaScript code), you will want the raw output to be printed. In such a
 case, set the ``is_safe`` option::
 
     $filter = new Twig_Filter_Function('nl2br', array('is_safe' => array('html')));
 
 Some filters may need to work on input that is already escaped or safe, for
-example when adding (safe) html tags to originally unsafe output. In such a
+example when adding (safe) HTML tags to originally unsafe output. In such a
 case, set the ``pre_escape`` option to escape the input data before it is run
 through your filter::
 
@@ -266,7 +266,7 @@ Dynamic Filters
 A filter name containing the special ``*`` character is a dynamic filter as
 the ``*`` can be any string::
 
-    $twig->addFilter('*_path', new Twig_Filter_Function('twig_path'));
+    $twig->addFilter('*_path_*', new Twig_Filter_Function('twig_path'));
 
     function twig_path($name, $arguments)
     {
diff --git a/core/vendor/twig/twig/doc/api.rst b/core/vendor/twig/twig/doc/api.rst
index dbba7059ddf9..b00d61ea9cdc 100644
--- a/core/vendor/twig/twig/doc/api.rst
+++ b/core/vendor/twig/twig/doc/api.rst
@@ -348,10 +348,10 @@ tag, ``autoescape``, and a filter, ``raw``.
 When creating the escaper extension, you can switch on or off the global
 output escaping strategy::
 
-    $escaper = new Twig_Extension_Escaper(true);
+    $escaper = new Twig_Extension_Escaper('html');
     $twig->addExtension($escaper);
 
-If set to ``true``, all variables in templates are escaped (using the ``html``
+If set to ``html``, all variables in templates are escaped (using the ``html``
 escaping strategy), except those using the ``raw`` filter:
 
 .. code-block:: jinja
@@ -417,15 +417,15 @@ The escaping rules are implemented as follows:
         {{ var|upper|raw }} {# won't be escaped #}
 
 * Automatic escaping is not applied if the last filter in the chain is marked
-  safe for the current context (e.g. ``html`` or ``js``). ``escaper`` and
-  ``escaper('html')`` are marked safe for html, ``escaper('js')`` is marked
-  safe for javascript, ``raw`` is marked safe for everything.
+  safe for the current context (e.g. ``html`` or ``js``). ``escape`` and
+  ``escape('html')`` are marked safe for HTML, ``escape('js')`` is marked
+  safe for JavaScript, ``raw`` is marked safe for everything.
 
   .. code-block:: jinja
 
         {% autoescape 'js' %}
-            {{ var|escape('html') }} {# will be escaped for html and javascript #}
-            {{ var }} {# will be escaped for javascript #}
+            {{ var|escape('html') }} {# will be escaped for HTML and JavaScript #}
+            {{ var }} {# will be escaped for JavaScript #}
             {{ var|escape('js') }} {# won't be double-escaped #}
         {% endautoescape %}
 
@@ -499,16 +499,16 @@ to enable by passing them to the constructor::
 Twig supports the following optimizations:
 
 * ``Twig_NodeVisitor_Optimizer::OPTIMIZE_ALL``, enables all optimizations
-(this is the default value).
+  (this is the default value).
 * ``Twig_NodeVisitor_Optimizer::OPTIMIZE_NONE``, disables all optimizations.
-This reduces the compilation time, but it can increase the execution time
-and the consumed memory.
+  This reduces the compilation time, but it can increase the execution time
+  and the consumed memory.
 * ``Twig_NodeVisitor_Optimizer::OPTIMIZE_FOR``, optimizes the ``for`` tag by
-removing the ``loop`` variable creation whenever possible.
+  removing the ``loop`` variable creation whenever possible.
 * ``Twig_NodeVisitor_Optimizer::OPTIMIZE_RAW_FILTER``, removes the ``raw``
-filter whenever possible.
+  filter whenever possible.
 * ``Twig_NodeVisitor_Optimizer::OPTIMIZE_VAR_ACCESS``, simplifies the creation
-and access of variables in the compiled templates whenever possible.
+  and access of variables in the compiled templates whenever possible.
 
 Exceptions
 ----------
diff --git a/core/vendor/twig/twig/doc/coding_standards.rst b/core/vendor/twig/twig/doc/coding_standards.rst
index e0aab35eaa91..f435df490afd 100644
--- a/core/vendor/twig/twig/doc/coding_standards.rst
+++ b/core/vendor/twig/twig/doc/coding_standards.rst
@@ -90,7 +90,7 @@ standards:
      {% set foo_bar = 'foo' %}
 
 * Indent your code inside tags (use the same indentation as the one used for
-  the main language of the file):
+  the target language of the rendered template):
 
   .. code-block:: jinja
 
diff --git a/core/vendor/twig/twig/doc/deprecated.rst b/core/vendor/twig/twig/doc/deprecated.rst
index f0a3a0f0ef4c..61917a8d6a7c 100644
--- a/core/vendor/twig/twig/doc/deprecated.rst
+++ b/core/vendor/twig/twig/doc/deprecated.rst
@@ -77,6 +77,9 @@ Tests
   removed in Twig 3.x (use ``Twig_Test`` instead). In Twig 2.x,
   ``Twig_SimpleTest`` is just an alias for ``Twig_Test``.
 
+* The ``sameas`` and ``divisibleby`` tests are deprecated in favor of ``same
+  as`` and ``divisible by`` respectively.
+
 Interfaces
 ----------
 
@@ -88,7 +91,9 @@ Interfaces
 * ``Twig_NodeInterface``         (use ``Twig_Node`` instead)
 * ``Twig_ParserInterface``       (use ``Twig_Parser`` instead)
 * ``Twig_ExistsLoaderInterface`` (merged with ``Twig_LoaderInterface``)
-* ``Twig_TemplateInterface``     (use ``Twig_Template`` instead)
+* ``Twig_TemplateInterface``     (use ``Twig_Template`` instead, and use
+  those constants Twig_Template::ANY_CALL, Twig_Template::ARRAY_CALL,
+  Twig_Template::METHOD_CALL)
 
 Globals
 -------
diff --git a/core/vendor/twig/twig/doc/filters/abs.rst b/core/vendor/twig/twig/doc/filters/abs.rst
index 3a82f62e4a4c..22fa59d0369f 100644
--- a/core/vendor/twig/twig/doc/filters/abs.rst
+++ b/core/vendor/twig/twig/doc/filters/abs.rst
@@ -6,9 +6,9 @@ The ``abs`` filter returns the absolute value.
 .. code-block:: jinja
 
     {# number = -5 #}
-    
+
     {{ number|abs }}
-    
+
     {# outputs 5 #}
 
 .. note::
diff --git a/core/vendor/twig/twig/doc/filters/batch.rst b/core/vendor/twig/twig/doc/filters/batch.rst
index 4366b57b09ed..b0b9964eb98b 100644
--- a/core/vendor/twig/twig/doc/filters/batch.rst
+++ b/core/vendor/twig/twig/doc/filters/batch.rst
@@ -14,11 +14,11 @@ missing items:
 
     <table>
     {% for row in items|batch(3, 'No item') %}
-      <tr>
-      {% for column in row %}
-        <td>{{ column }}</td>
-      {% endfor %}
-      </tr>
+        <tr>
+            {% for column in row %}
+                <td>{{ column }}</td>
+            {% endfor %}
+        </tr>
     {% endfor %}
     </table>
 
@@ -27,19 +27,19 @@ The above example will be rendered as:
 .. code-block:: jinja
 
     <table>
-      <tr>
-          <td>a</td>
-          <td>b</td>
-          <td>c</td>
+        <tr>
+            <td>a</td>
+            <td>b</td>
+            <td>c</td>
         </tr>
-      <tr>
-          <td>d</td>
-          <td>e</td>
-          <td>f</td>
+        <tr>
+            <td>d</td>
+            <td>e</td>
+            <td>f</td>
         </tr>
-      <tr>
-          <td>g</td>
-          <td>No item</td>
-          <td>No item</td>
+        <tr>
+            <td>g</td>
+            <td>No item</td>
+            <td>No item</td>
         </tr>
     </table>
diff --git a/core/vendor/twig/twig/doc/filters/convert_encoding.rst b/core/vendor/twig/twig/doc/filters/convert_encoding.rst
index 1b0eb60c3ab4..c417e1287368 100644
--- a/core/vendor/twig/twig/doc/filters/convert_encoding.rst
+++ b/core/vendor/twig/twig/doc/filters/convert_encoding.rst
@@ -21,8 +21,8 @@ is the input charset:
 Arguments
 ---------
 
- * ``from``: The input charset
- * ``to``:   The output charset
+* ``from``: The input charset
+* ``to``:   The output charset
 
 .. _`iconv`:    http://php.net/iconv
 .. _`mbstring`: http://php.net/mbstring
diff --git a/core/vendor/twig/twig/doc/filters/date.rst b/core/vendor/twig/twig/doc/filters/date.rst
index 8e2f31faab91..c86d42bafc52 100644
--- a/core/vendor/twig/twig/doc/filters/date.rst
+++ b/core/vendor/twig/twig/doc/filters/date.rst
@@ -19,6 +19,10 @@ The ``date`` filter formats a date to a given format:
 
     {{ post.published_at|date("m/d/Y") }}
 
+The format specifier is the same as supported by `date`_,
+except when the filtered data is of type `DateInterval`_, when the format must conform to
+`DateInterval::format`_ instead.
+
 The ``date`` filter accepts strings (it must be in a format supported by the
 `strtotime`_ function), `DateTime`_ instances, or `DateInterval`_ instances. For
 instance, to display the current date, filter the word "now":
@@ -80,9 +84,11 @@ The default timezone can also be set globally by calling ``setTimezone()``:
 Arguments
 ---------
 
- * ``format``:   The date format
- * ``timezone``: The date timezone
+* ``format``:   The date format
+* ``timezone``: The date timezone
 
-.. _`strtotime`:    http://www.php.net/strtotime
-.. _`DateTime`:     http://www.php.net/DateTime
-.. _`DateInterval`: http://www.php.net/DateInterval
+.. _`strtotime`:            http://www.php.net/strtotime
+.. _`DateTime`:             http://www.php.net/DateTime
+.. _`DateInterval`:         http://www.php.net/DateInterval
+.. _`date`:                 http://www.php.net/date
+.. _`DateInterval::format`: http://www.php.net/DateInterval.format
diff --git a/core/vendor/twig/twig/doc/filters/date_modify.rst b/core/vendor/twig/twig/doc/filters/date_modify.rst
index 6a5c73d6bb20..add40b56b01c 100644
--- a/core/vendor/twig/twig/doc/filters/date_modify.rst
+++ b/core/vendor/twig/twig/doc/filters/date_modify.rst
@@ -17,7 +17,7 @@ it with the :doc:`date<date>` filter for formatting.
 Arguments
 ---------
 
- * ``modifier``: The modifier
+* ``modifier``: The modifier
 
 .. _`strtotime`: http://www.php.net/strtotime
 .. _`DateTime`:  http://www.php.net/DateTime
diff --git a/core/vendor/twig/twig/doc/filters/default.rst b/core/vendor/twig/twig/doc/filters/default.rst
index 46ed9636750d..641ac6e756fa 100644
--- a/core/vendor/twig/twig/doc/filters/default.rst
+++ b/core/vendor/twig/twig/doc/filters/default.rst
@@ -30,4 +30,4 @@ undefined:
 Arguments
 ---------
 
- * ``default``: The default value
+* ``default``: The default value
diff --git a/core/vendor/twig/twig/doc/filters/escape.rst b/core/vendor/twig/twig/doc/filters/escape.rst
index 5ade7d7484a7..fc9771acdfaf 100644
--- a/core/vendor/twig/twig/doc/filters/escape.rst
+++ b/core/vendor/twig/twig/doc/filters/escape.rst
@@ -5,6 +5,9 @@
     The ``css``, ``url``, and ``html_attr`` strategies were added in Twig
     1.9.0.
 
+.. versionadded:: 1.14.0
+    The ability to define custom escapers was added in Twig 1.14.0.
+
 The ``escape`` filter escapes a string for safe insertion into the final
 output. It supports different escaping strategies depending on the template
 context.
@@ -84,10 +87,30 @@ The ``escape`` filter supports the following escaping strategies:
             {{ var|escape(strategy)|raw }} {# won't be double-escaped #}
         {% endautoescape %}
 
+Custom Escapers
+---------------
+
+You can define custom escapers by calling the ``setEscaper()`` method on the
+``core`` extension instance. The first argument is the escaper name (to be
+used in the ``escape`` call) and the second one must be a valid PHP callable:
+
+.. code-block:: php
+
+    $twig = new Twig_Environment($loader);
+    $twig->getExtension('core')->setEscaper('csv', 'csv_escaper'));
+
+When called by Twig, the callable receives the Twig environment instance, the
+string to escape, and the charset.
+
+.. note::
+
+    Built-in escapers cannot be overridden mainly they should be considered as
+    the final implementation and also for better performance.
+
 Arguments
 ---------
 
- * ``strategy``: The escaping strategy
- * ``charset``:  The string charset
+* ``strategy``: The escaping strategy
+* ``charset``:  The string charset
 
 .. _`htmlspecialchars`: http://php.net/htmlspecialchars
diff --git a/core/vendor/twig/twig/doc/filters/format.rst b/core/vendor/twig/twig/doc/filters/format.rst
index fd5b18d0e068..f8effd9a9408 100644
--- a/core/vendor/twig/twig/doc/filters/format.rst
+++ b/core/vendor/twig/twig/doc/filters/format.rst
@@ -2,15 +2,15 @@
 ==========
 
 The ``format`` filter formats a given string by replacing the placeholders
-(placeholders follows the `printf`_ notation):
+(placeholders follows the `sprintf`_ notation):
 
 .. code-block:: jinja
 
     {{ "I like %s and %s."|format(foo, "bar") }}
 
-    {# returns I like foo and bar
+    {# outputs I like foo and bar
        if the foo parameter equals to the foo string. #}
 
-.. _`printf`: http://www.php.net/printf
+.. _`sprintf`: http://www.php.net/sprintf
 
 .. seealso:: :doc:`replace<replace>`
diff --git a/core/vendor/twig/twig/doc/filters/index.rst b/core/vendor/twig/twig/doc/filters/index.rst
index b0c6b38d05bc..3ed0952345e2 100644
--- a/core/vendor/twig/twig/doc/filters/index.rst
+++ b/core/vendor/twig/twig/doc/filters/index.rst
@@ -27,6 +27,7 @@ Filters
     raw
     replace
     reverse
+    round
     slice
     sort
     split
diff --git a/core/vendor/twig/twig/doc/filters/join.rst b/core/vendor/twig/twig/doc/filters/join.rst
index f49524217698..2fab94528ad0 100644
--- a/core/vendor/twig/twig/doc/filters/join.rst
+++ b/core/vendor/twig/twig/doc/filters/join.rst
@@ -15,9 +15,9 @@ define it with the optional first parameter:
 .. code-block:: jinja
 
     {{ [1, 2, 3]|join('|') }}
-    {# returns 1|2|3 #}
+    {# outputs 1|2|3 #}
 
 Arguments
 ---------
 
- * ``glue``: The separator
+* ``glue``: The separator
diff --git a/core/vendor/twig/twig/doc/filters/json_encode.rst b/core/vendor/twig/twig/doc/filters/json_encode.rst
index a33fef1b7301..9821b11eaa15 100644
--- a/core/vendor/twig/twig/doc/filters/json_encode.rst
+++ b/core/vendor/twig/twig/doc/filters/json_encode.rst
@@ -14,8 +14,8 @@ The ``json_encode`` filter returns the JSON representation of a string:
 Arguments
 ---------
 
- * ``options``: A bitmask of `json_encode options`_ (``{{
-   data|json_encode(constant(JSON_PRETTY_PRINT)) }}``)
+* ``options``: A bitmask of `json_encode options`_ (``{{
+  data|json_encode(constant('JSON_PRETTY_PRINT')) }}``)
 
 .. _`json_encode`: http://php.net/json_encode
 .. _`json_encode options`: http://www.php.net/manual/en/json.constants.php
diff --git a/core/vendor/twig/twig/doc/filters/length.rst b/core/vendor/twig/twig/doc/filters/length.rst
index f79b9bdfd396..5e0f73a43726 100644
--- a/core/vendor/twig/twig/doc/filters/length.rst
+++ b/core/vendor/twig/twig/doc/filters/length.rst
@@ -9,4 +9,3 @@ the length of a string:
     {% if users|length > 10 %}
         ...
     {% endif %}
-
diff --git a/core/vendor/twig/twig/doc/filters/number_format.rst b/core/vendor/twig/twig/doc/filters/number_format.rst
index fedacd9d7d89..3e60691f8191 100644
--- a/core/vendor/twig/twig/doc/filters/number_format.rst
+++ b/core/vendor/twig/twig/doc/filters/number_format.rst
@@ -21,9 +21,9 @@ separator using the additional arguments:
 If no formatting options are provided then Twig will use the default formatting
 options of:
 
-- 0 decimal places.
-- ``.`` as the decimal point.
-- ``,`` as the thousands separator.
+* 0 decimal places.
+* ``.`` as the decimal point.
+* ``,`` as the thousands separator.
 
 These defaults can be easily changed through the core extension:
 
@@ -38,8 +38,8 @@ additional parameters.
 Arguments
 ---------
 
- * ``decimal``:       The number of decimal points to display
- * ``decimal_point``: The character(s) to use for the decimal point
- * ``decimal_sep``:   The character(s) to use for the thousands separator
+* ``decimal``:       The number of decimal points to display
+* ``decimal_point``: The character(s) to use for the decimal point
+* ``thousand_sep``:   The character(s) to use for the thousands separator
 
 .. _`number_format`: http://php.net/number_format
diff --git a/core/vendor/twig/twig/doc/filters/raw.rst b/core/vendor/twig/twig/doc/filters/raw.rst
index 434dd246fe50..a9900c7bbcd3 100644
--- a/core/vendor/twig/twig/doc/filters/raw.rst
+++ b/core/vendor/twig/twig/doc/filters/raw.rst
@@ -7,6 +7,6 @@ if ``raw`` is the last filter applied to it:
 
 .. code-block:: jinja
 
-    {% autoescape true %}
+    {% autoescape %}
         {{ var|raw }} {# var won't be escaped #}
     {% endautoescape %}
diff --git a/core/vendor/twig/twig/doc/filters/replace.rst b/core/vendor/twig/twig/doc/filters/replace.rst
index e961f23d49b6..1227957b9d84 100644
--- a/core/vendor/twig/twig/doc/filters/replace.rst
+++ b/core/vendor/twig/twig/doc/filters/replace.rst
@@ -8,12 +8,12 @@ The ``replace`` filter formats a given string by replacing the placeholders
 
     {{ "I like %this% and %that%."|replace({'%this%': foo, '%that%': "bar"}) }}
 
-    {# returns I like foo and bar
+    {# outputs I like foo and bar
        if the foo parameter equals to the foo string. #}
 
 Arguments
 ---------
 
- * ``replace_pairs``: The placeholder values
+* ``replace_pairs``: The placeholder values
 
 .. seealso:: :doc:`format<format>`
diff --git a/core/vendor/twig/twig/doc/filters/reverse.rst b/core/vendor/twig/twig/doc/filters/reverse.rst
index 54fafb45d73f..76fd2c1abd8a 100644
--- a/core/vendor/twig/twig/doc/filters/reverse.rst
+++ b/core/vendor/twig/twig/doc/filters/reverse.rst
@@ -8,7 +8,7 @@ The ``reverse`` filter reverses a sequence, a mapping, or a string:
 
 .. code-block:: jinja
 
-    {% for use in users|reverse %}
+    {% for user in users|reverse %}
         ...
     {% endfor %}
 
@@ -16,8 +16,32 @@ The ``reverse`` filter reverses a sequence, a mapping, or a string:
 
     {# outputs 4321 #}
 
+.. tip::
+
+    For sequences and mappings, numeric keys are not preserved. To reverse
+    them as well, pass ``true`` as an argument to the ``reverse`` filter:
+
+    .. code-block:: jinja
+
+        {% for key, value in {1: "a", 2: "b", 3: "c"}|reverse %}
+            {{ key }}: {{ value }}
+        {%- endfor %}
+
+        {# output: 0: c    1: b    2: a #}
+
+        {% for key, value in {1: "a", 2: "b", 3: "c"}|reverse(true) %}
+            {{ key }}: {{ value }}
+        {%- endfor %}
+
+        {# output: 3: c    2: b    1: a #}
+
 .. note::
 
     It also works with objects implementing the `Traversable`_ interface.
 
+Arguments
+---------
+
+* ``preserve_keys``: Preserve keys when reversing a mapping or a sequence.
+
 .. _`Traversable`: http://php.net/Traversable
diff --git a/core/vendor/twig/twig/doc/filters/round.rst b/core/vendor/twig/twig/doc/filters/round.rst
new file mode 100644
index 000000000000..2521cf16aabc
--- /dev/null
+++ b/core/vendor/twig/twig/doc/filters/round.rst
@@ -0,0 +1,37 @@
+``round``
+=========
+
+.. versionadded:: 1.15.0
+    The ``round`` filter was added in Twig 1.15.0.
+
+The ``round`` filter rounds a number to a given precision:
+
+.. code-block:: jinja
+
+    {{ 42.55|round }}
+    {# outputs 43 #}
+
+    {{ 42.55|round(1, 'floor') }}
+    {# outputs 42.5 #}
+
+The ``round`` filter takes two optional arguments; the first one specifies the
+precision (default is ``0``) and the second the rounding method (default is
+``common``):
+
+* ``common`` rounds either up or down (rounds the value up to precision decimal
+  places away from zero, when it is half way there -- making 1.5 into 2 and
+  -1.5 into -2);
+
+* ``ceil`` always rounds up;
+
+* ``floor`` always rounds down.
+
+.. note::
+
+    The ``//`` operator is equivalent to ``|round(0, 'floor')``.
+
+Arguments
+---------
+
+* ``precision``: The rounding precision
+* ``method``: The rounding method
diff --git a/core/vendor/twig/twig/doc/filters/slice.rst b/core/vendor/twig/twig/doc/filters/slice.rst
index 7a9ada0256df..c76c61c11e0d 100644
--- a/core/vendor/twig/twig/doc/filters/slice.rst
+++ b/core/vendor/twig/twig/doc/filters/slice.rst
@@ -8,11 +8,11 @@ The ``slice`` filter extracts a slice of a sequence, a mapping, or a string:
 
 .. code-block:: jinja
 
-    {% for i in [1, 2, 3, 4]|slice(1, 2) %}
+    {% for i in [1, 2, 3, 4, 5]|slice(1, 2) %}
         {# will iterate over 2 and 3 #}
     {% endfor %}
 
-    {{ '1234'|slice(1, 2) }}
+    {{ '12345'|slice(1, 2) }}
 
     {# outputs 23 #}
 
@@ -20,7 +20,7 @@ You can use any valid expression for both the start and the length:
 
 .. code-block:: jinja
 
-    {% for i in [1, 2, 3, 4]|slice(start, length) %}
+    {% for i in [1, 2, 3, 4, 5]|slice(start, length) %}
         {# ... #}
     {% endfor %}
 
@@ -28,17 +28,17 @@ As syntactic sugar, you can also use the ``[]`` notation:
 
 .. code-block:: jinja
 
-    {% for i in [1, 2, 3, 4][start:length] %}
+    {% for i in [1, 2, 3, 4, 5][start:length] %}
         {# ... #}
     {% endfor %}
 
-    {{ '1234'[1:2] }}
+    {{ '12345'[1:2] }}
 
     {# you can omit the first argument -- which is the same as 0 #}
-    {{ '1234'[:2] }} {# will display "12" #}
+    {{ '12345'[:2] }} {# will display "12" #}
 
     {# you can omit the last argument -- which will select everything till the end #}
-    {{ '1234'[2:] }} {# will display "34 #}
+    {{ '12345'[2:] }} {# will display "345" #}
 
 The ``slice`` filter works as the `array_slice`_ PHP function for arrays and
 `substr`_ for strings.
@@ -61,9 +61,9 @@ up until the end of the variable.
 Arguments
 ---------
 
- * ``start``:         The start of the slice
- * ``length``:        The size of the slice
- * ``preserve_keys``: Whether to preserve key or not (when the input is an array)
+* ``start``:         The start of the slice
+* ``length``:        The size of the slice
+* ``preserve_keys``: Whether to preserve key or not (when the input is an array)
 
 .. _`Traversable`: http://php.net/manual/en/class.traversable.php
 .. _`array_slice`: http://php.net/array_slice
diff --git a/core/vendor/twig/twig/doc/filters/split.rst b/core/vendor/twig/twig/doc/filters/split.rst
index 7cd2ca5b8047..3db81411dec3 100644
--- a/core/vendor/twig/twig/doc/filters/split.rst
+++ b/core/vendor/twig/twig/doc/filters/split.rst
@@ -46,8 +46,8 @@ chunks. Length is set by the ``limit`` argument (one character by default).
 Arguments
 ---------
 
- * ``delimiter``: The delimiter
- * ``limit``:     The limit argument
+* ``delimiter``: The delimiter
+* ``limit``:     The limit argument
 
 .. _`explode`:   http://php.net/explode
 .. _`str_split`: http://php.net/str_split
diff --git a/core/vendor/twig/twig/doc/filters/trim.rst b/core/vendor/twig/twig/doc/filters/trim.rst
index f38afd55ad60..0c5b32edb3e9 100644
--- a/core/vendor/twig/twig/doc/filters/trim.rst
+++ b/core/vendor/twig/twig/doc/filters/trim.rst
@@ -24,6 +24,6 @@ and end of a string:
 Arguments
 ---------
 
- * ``character_mask``: The characters to strip
+* ``character_mask``: The characters to strip
 
 .. _`trim`: http://php.net/trim
diff --git a/core/vendor/twig/twig/doc/filters/url_encode.rst b/core/vendor/twig/twig/doc/filters/url_encode.rst
index d3a33fd45830..7a35ed152f64 100644
--- a/core/vendor/twig/twig/doc/filters/url_encode.rst
+++ b/core/vendor/twig/twig/doc/filters/url_encode.rst
@@ -12,12 +12,17 @@ or an array as query string:
     {{ "path-seg*ment"|url_encode }}
     {# outputs "path-seg%2Ament" #}
 
+    {{ "string with spaces"|url_encode(true) }}
+    {# outputs "string%20with%20spaces" #}
+
     {{ {'param': 'value', 'foo': 'bar'}|url_encode }}
     {# outputs "param=value&foo=bar" #}
 
 .. note::
 
-    Internally, Twig uses the PHP `urlencode`_ or the `http_build_query`_ function.
+    Internally, Twig uses the PHP `urlencode`_ (or `rawurlencode`_ if you pass
+    ``true`` as the first parameter) or the `http_build_query`_ function.
 
-.. _`urlencode`: http://php.net/urlencode
+.. _`urlencode`:        http://php.net/urlencode
+.. _`rawurlencode`:     http://php.net/rawurlencode
 .. _`http_build_query`: http://php.net/http_build_query
diff --git a/core/vendor/twig/twig/doc/functions/cycle.rst b/core/vendor/twig/twig/doc/functions/cycle.rst
index 0015cae1f9ad..94f700889523 100644
--- a/core/vendor/twig/twig/doc/functions/cycle.rst
+++ b/core/vendor/twig/twig/doc/functions/cycle.rst
@@ -22,4 +22,4 @@ The array can contain any number of values:
 Arguments
 ---------
 
- * ``position``: The cycle position
+* ``position``: The cycle position
diff --git a/core/vendor/twig/twig/doc/functions/date.rst b/core/vendor/twig/twig/doc/functions/date.rst
index fd67fc56c9d0..9442c39ff216 100644
--- a/core/vendor/twig/twig/doc/functions/date.rst
+++ b/core/vendor/twig/twig/doc/functions/date.rst
@@ -11,7 +11,7 @@ Converts an argument to a date to allow date comparison:
 
 .. code-block:: jinja
 
-    {% if date(user.created_at) < date('+2days') %}
+    {% if date(user.created_at) < date('-2days') %}
         {# do something #}
     {% endif %}
 
@@ -21,7 +21,7 @@ You can pass a timezone as the second argument:
 
 .. code-block:: jinja
 
-    {% if date(user.created_at) < date('+2days', 'Europe/Paris') %}
+    {% if date(user.created_at) < date('-2days', 'Europe/Paris') %}
         {# do something #}
     {% endif %}
 
@@ -46,7 +46,7 @@ If no argument is passed, the function returns the current date:
 Arguments
 ---------
 
- * ``date``:     The date
- * ``timezone``: The timezone
+* ``date``:     The date
+* ``timezone``: The timezone
 
 .. _`date`: http://www.php.net/date
diff --git a/core/vendor/twig/twig/doc/functions/dump.rst b/core/vendor/twig/twig/doc/functions/dump.rst
index 1500b0f4aa1d..54f8d4e1354a 100644
--- a/core/vendor/twig/twig/doc/functions/dump.rst
+++ b/core/vendor/twig/twig/doc/functions/dump.rst
@@ -63,7 +63,7 @@ dumped:
 Arguments
 ---------
 
- * ``context``: The context to dump
+* ``context``: The context to dump
 
 .. _`XDebug`:   http://xdebug.org/docs/display
 .. _`var_dump`: http://php.net/var_dump
diff --git a/core/vendor/twig/twig/doc/functions/include.rst b/core/vendor/twig/twig/doc/functions/include.rst
index eaddfe61b101..8feb0f179134 100644
--- a/core/vendor/twig/twig/doc/functions/include.rst
+++ b/core/vendor/twig/twig/doc/functions/include.rst
@@ -73,8 +73,8 @@ sandboxing it:
 Arguments
 ---------
 
- * ``template``:       The template to render
- * ``variables``:      The variables to pass to the template
- * ``with_context``:   Whether to pass the current context variables or not
- * ``ignore_missing``: Whether to ignore missing templates or not
- * ``sandboxed``:      Whether to sandbox the template or not
+* ``template``:       The template to render
+* ``variables``:      The variables to pass to the template
+* ``with_context``:   Whether to pass the current context variables or not
+* ``ignore_missing``: Whether to ignore missing templates or not
+* ``sandboxed``:      Whether to sandbox the template or not
diff --git a/core/vendor/twig/twig/doc/functions/index.rst b/core/vendor/twig/twig/doc/functions/index.rst
index 8650cbdba6f8..07214a76c182 100644
--- a/core/vendor/twig/twig/doc/functions/index.rst
+++ b/core/vendor/twig/twig/doc/functions/index.rst
@@ -11,7 +11,10 @@ Functions
     date
     dump
     include
+    max
+    min
     parent
     random
     range
+    source
     template_from_string
diff --git a/core/vendor/twig/twig/doc/functions/max.rst b/core/vendor/twig/twig/doc/functions/max.rst
new file mode 100644
index 000000000000..bdc5b753869a
--- /dev/null
+++ b/core/vendor/twig/twig/doc/functions/max.rst
@@ -0,0 +1,19 @@
+``max``
+=======
+
+.. versionadded:: 1.15
+    The ``max`` function was added in Twig 1.15.
+
+``max`` returns the biggest value of a sequence or a set of values:
+
+.. code-block:: jinja
+
+    {{ max(1, 3, 2) }}
+    {{ max([1, 3, 2]) }}
+
+When called with a mapping, max ignores keys and only compares values:
+
+.. code-block:: jinja
+
+    {{ max({2: "two", 1: "one", 3: "three", 5: "five", 4: "for"}) }}
+    {# return "two" #}
diff --git a/core/vendor/twig/twig/doc/functions/min.rst b/core/vendor/twig/twig/doc/functions/min.rst
new file mode 100644
index 000000000000..b924b0318dd0
--- /dev/null
+++ b/core/vendor/twig/twig/doc/functions/min.rst
@@ -0,0 +1,19 @@
+``min``
+=======
+
+.. versionadded:: 1.15
+    The ``min`` function was added in Twig 1.15.
+
+``min`` returns the lowest value of a sequence or a set of values:
+
+.. code-block:: jinja
+
+    {{ min(1, 3, 2) }}
+    {{ min([1, 3, 2]) }}
+
+When called with a mapping, min ignores keys and only compares values:
+
+.. code-block:: jinja
+
+    {{ min({2: "two", 1: "one", 3: "three", 5: "five", 4: "for"}) }}
+    {# return "five" #}
diff --git a/core/vendor/twig/twig/doc/functions/random.rst b/core/vendor/twig/twig/doc/functions/random.rst
index a5a916bbcd33..acbffe557fd4 100644
--- a/core/vendor/twig/twig/doc/functions/random.rst
+++ b/core/vendor/twig/twig/doc/functions/random.rst
@@ -18,12 +18,12 @@ parameter type:
 
     {{ random(['apple', 'orange', 'citrus']) }} {# example output: orange #}
     {{ random('ABC') }}                         {# example output: C #}
-    {{ random() }}                              {# example output: 15386094 (works as native PHP `mt_rand`_ function) #}
+    {{ random() }}                              {# example output: 15386094 (works as the native PHP mt_rand function) #}
     {{ random(5) }}                             {# example output: 3 #}
 
 Arguments
 ---------
 
- * ``values``: The values
+* ``values``: The values
 
 .. _`mt_rand`: http://php.net/mt_rand
diff --git a/core/vendor/twig/twig/doc/functions/range.rst b/core/vendor/twig/twig/doc/functions/range.rst
index b1fa54710c9a..b7cd01116c7c 100644
--- a/core/vendor/twig/twig/doc/functions/range.rst
+++ b/core/vendor/twig/twig/doc/functions/range.rst
@@ -9,7 +9,7 @@ Returns a list containing an arithmetic progression of integers:
         {{ i }},
     {% endfor %}
 
-    {# returns 0, 1, 2, 3 #}
+    {# outputs 0, 1, 2, 3, #}
 
 When step is given (as the third parameter), it specifies the increment (or
 decrement):
@@ -20,7 +20,7 @@ decrement):
         {{ i }},
     {% endfor %}
 
-    {# returns 0, 2, 4, 6 #}
+    {# outputs 0, 2, 4, 6, #}
 
 The Twig built-in ``..`` operator is just syntactic sugar for the ``range``
 function (with a step of 1):
@@ -38,8 +38,8 @@ function (with a step of 1):
 Arguments
 ---------
 
- * ``low``:  The first value of the sequence.
- * ``high``: The highest possible value of the sequence.
- * ``step``: The increment between elements of the sequence.
+* ``low``:  The first value of the sequence.
+* ``high``: The highest possible value of the sequence.
+* ``step``: The increment between elements of the sequence.
 
 .. _`range`: http://php.net/range
diff --git a/core/vendor/twig/twig/doc/functions/source.rst b/core/vendor/twig/twig/doc/functions/source.rst
new file mode 100644
index 000000000000..defa5fbc551f
--- /dev/null
+++ b/core/vendor/twig/twig/doc/functions/source.rst
@@ -0,0 +1,21 @@
+``source``
+==========
+
+.. versionadded:: 1.15
+    The source function was added in Twig 1.15.
+
+The ``source`` function returns the content of a template without rendering it:
+
+.. code-block:: jinja
+
+    {{ source('template.html') }}
+    {{ source(some_var) }}
+
+The function uses the same template loaders as the ones used to include
+templates. So, if you are using the filesystem loader, the templates are looked
+for in the paths defined by it.
+
+Arguments
+---------
+
+* ``name``: The name of the template to read
diff --git a/core/vendor/twig/twig/doc/functions/template_from_string.rst b/core/vendor/twig/twig/doc/functions/template_from_string.rst
index bbb06d8640d9..95d925631269 100644
--- a/core/vendor/twig/twig/doc/functions/template_from_string.rst
+++ b/core/vendor/twig/twig/doc/functions/template_from_string.rst
@@ -8,7 +8,7 @@ The ``template_from_string`` function loads a template from a string:
 
 .. code-block:: jinja
 
-    {{ include(template_from_string("Hello {{ name }}") }}
+    {{ include(template_from_string("Hello {{ name }}")) }}
     {{ include(template_from_string(page.template)) }}
 
 .. note::
@@ -29,4 +29,4 @@ The ``template_from_string`` function loads a template from a string:
 Arguments
 ---------
 
- * ``template``: The template
+* ``template``: The template
diff --git a/core/vendor/twig/twig/doc/index.rst b/core/vendor/twig/twig/doc/index.rst
index 3e5166c6e543..3109c730b6e8 100644
--- a/core/vendor/twig/twig/doc/index.rst
+++ b/core/vendor/twig/twig/doc/index.rst
@@ -15,4 +15,5 @@ Twig
     filters/index
     functions/index
     tests/index
+    installation
     deprecated
diff --git a/core/vendor/twig/twig/doc/installation.rst b/core/vendor/twig/twig/doc/installation.rst
new file mode 100644
index 000000000000..278ef61ca926
--- /dev/null
+++ b/core/vendor/twig/twig/doc/installation.rst
@@ -0,0 +1,118 @@
+Installation
+============
+
+You have multiple ways to install Twig.
+
+Installing the Twig PHP package
+-------------------------------
+
+Installing via Composer (recommended)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Install Composer in your project:
+
+.. code-block:: bash
+
+    curl -s http://getcomposer.org/installer | php
+
+2. Create a ``composer.json`` file in your project root:
+
+.. code-block:: javascript
+
+    {
+        "require": {
+            "twig/twig": "1.*"
+        }
+    }
+
+3. Install via Composer
+
+.. code-block:: bash
+
+    php composer.phar install
+
+.. note::
+    If you want to learn more about Composer, the ``composer.json`` file syntax
+    and its usage, you can read the `online documentation`_.
+
+Installing from the tarball release
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Download the most recent tarball from the `download page`_
+2. Unpack the tarball
+3. Move the files somewhere in your project
+
+Installing the development version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Install Git
+2. ``git clone git://github.com/fabpot/Twig.git``
+
+Installing the PEAR package
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Install PEAR
+2. ``pear channel-discover pear.twig-project.org``
+3. ``pear install twig/Twig`` (or ``pear install twig/Twig-beta``)
+
+Installing the C extension
+--------------------------
+
+.. versionadded:: 1.4
+    The C extension was added in Twig 1.4.
+
+Twig comes with a C extension that enhances the performance of the Twig
+runtime engine.
+
+You can install it via PEAR:
+
+1. Install PEAR
+2. ``pear channel-discover pear.twig-project.org``
+3. ``pear install twig/CTwig`` (or ``pear install twig/CTwig-beta``)
+
+Or manually like any other PHP extension:
+
+.. code-block:: bash
+
+    $ cd ext/twig
+    $ phpize
+    $ ./configure
+    $ make
+    $ make install
+
+For Windows:
+
+1. Setup the build environment following the `PHP documentation`_
+2. Put Twig's C extension source code into ``C:\php-sdk\phpdev\vcXX\x86\php-source-directory\ext\twig``
+3. Use the ``configure --disable-all --enable-cli --enable-twig=shared`` command instead of step 14
+4. ``nmake``
+5. Copy the ``C:\php-sdk\phpdev\vcXX\x86\php-source-directory\Release_TS\php_twig.dll`` file to your PHP setup.
+
+.. tip::
+
+    For Windows ZendServer, TS is not enabled as mentionned in `Zend Server
+    FAQ`_.
+
+    You have to use `configure --disable-all --disable-zts --enable-cli
+    --enable-twig=shared` to be able to build the twig C extension for
+    ZendServer.
+
+    The built DLL will be available in
+    C:\\php-sdk\\phpdev\\vcXX\\x86\\php-source-directory\\Release
+
+Finally, enable the extension in your ``php.ini`` configuration file:
+
+.. code-block:: ini
+
+    extension=twig.so #For Unix systems
+    extension=php_twig.dll #For Windows systems
+
+And from now on, Twig will automatically compile your templates to take
+advantage of the C extension. Note that this extension does not replace the
+PHP code but only provides an optimized version of the
+``Twig_Template::getAttribute()`` method.
+
+.. _`download page`: https://github.com/fabpot/Twig/tags
+.. _`online documentation`: http://getcomposer.org/doc
+.. _`PHP documentation`: https://wiki.php.net/internals/windows/stepbystepbuild
+.. _`Zend Server FAQ`: http://www.zend.com/en/products/server/faq#faqD6
diff --git a/core/vendor/twig/twig/doc/internals.rst b/core/vendor/twig/twig/doc/internals.rst
index 79a3c8d5ade4..16f425adec9e 100644
--- a/core/vendor/twig/twig/doc/internals.rst
+++ b/core/vendor/twig/twig/doc/internals.rst
@@ -3,11 +3,11 @@ Twig Internals
 
 Twig is very extensible and you can easily hack it. Keep in mind that you
 should probably try to create an extension before hacking the core, as most
-features and enhancements can be done with extensions. This chapter is also
+features and enhancements can be handled with extensions. This chapter is also
 useful for people who want to understand how Twig works under the hood.
 
-How Twig works?
----------------
+How does Twig work?
+-------------------
 
 The rendering of a Twig template can be summarized into four key steps:
 
@@ -18,7 +18,7 @@ The rendering of a Twig template can be summarized into four key steps:
     for easier processing;
   * Then, the **parser** converts the token stream into a meaningful tree
     of nodes (the Abstract Syntax Tree);
-  * Eventually, the *compiler* transforms the AST into PHP code;
+  * Eventually, the *compiler* transforms the AST into PHP code.
 
 * **Evaluate** the template: It basically means calling the ``display()``
   method of the compiled template and passing it the context.
@@ -42,7 +42,7 @@ an instance of ``Twig_Token``, and the stream is an instance of
 * ``Twig_Token::EOF_TYPE``: Ends of template.
 
 You can manually convert a source code into a token stream by calling the
-``tokenize()`` of an environment::
+``tokenize()`` method of an environment::
 
     $stream = $twig->tokenize($source, $identifier);
 
@@ -63,7 +63,7 @@ Here is the output for the ``Hello {{ name }}`` template:
 
 .. note::
 
-    You can change the default lexer use by Twig (``Twig_Lexer``) by calling
+    The default lexer (``Twig_Lexer``) can be changed by calling
     the ``setLexer()`` method::
 
         $twig->setLexer($lexer);
@@ -97,7 +97,7 @@ Here is the output for the ``Hello {{ name }}`` template:
 
 .. note::
 
-    The default parser (``Twig_TokenParser``) can be also changed by calling the
+    The default parser (``Twig_TokenParser``) can be changed by calling the
     ``setParser()`` method::
 
         $twig->setParser($parser);
@@ -108,13 +108,11 @@ The Compiler
 The last step is done by the compiler. It takes a node tree as an input and
 generates PHP code usable for runtime execution of the template.
 
-You can call the compiler by hand with the ``compile()`` method of an
-environment::
+You can manually compile a node tree to PHP code with the ``compile()`` method
+of an environment::
 
     $php = $twig->compile($nodes);
 
-The ``compile()`` method returns the PHP source code representing the node.
-
 The generated template for a ``Hello {{ name }}`` template reads as follows
 (the actual output can differ depending on the version of Twig you are
 using)::
@@ -134,7 +132,7 @@ using)::
 
 .. note::
 
-    As for the lexer and the parser, the default compiler (``Twig_Compiler``) can
-    be changed by calling the ``setCompiler()`` method::
+    The default compiler (``Twig_Compiler``) can be changed by calling the
+    ``setCompiler()`` method::
 
         $twig->setCompiler($compiler);
diff --git a/core/vendor/twig/twig/doc/intro.rst b/core/vendor/twig/twig/doc/intro.rst
index 57a4ca8d9d4b..9f0cdf02774d 100644
--- a/core/vendor/twig/twig/doc/intro.rst
+++ b/core/vendor/twig/twig/doc/intro.rst
@@ -29,115 +29,27 @@ Twig needs at least **PHP 5.2.4** to run.
 Installation
 ------------
 
-You have multiple ways to install Twig.
-
-Installing via Composer (recommended)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1. Install composer in your project:
-
-.. code-block:: bash
-
-    curl -s http://getcomposer.org/installer | php
-
-2. Create a ``composer.json`` file in your project root:
-
-.. code-block:: javascript
-
-    {
-        "require": {
-            "twig/twig": "1.*"
-        }
-    }
-
-3. Install via composer
+The recommended way to install Twig is via Composer:
 
 .. code-block:: bash
 
-    php composer.phar install
+    composer require twig/twig:1.*
 
 .. note::
-    If you want to learn more about Composer, the ``composer.json`` file syntax
-    and its usage, you can read the `online documentation`_.
-
-Installing from the tarball release
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1. Download the most recent tarball from the `download page`_
-2. Unpack the tarball
-3. Move the files somewhere in your project
-
-Installing the development version
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1. Install Git
-2. ``git clone git://github.com/fabpot/Twig.git``
-
-Installing the PEAR package
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1. Install PEAR
-2. ``pear channel-discover pear.twig-project.org``
-3. ``pear install twig/Twig`` (or ``pear install twig/Twig-beta``)
-
-
-Installing the C extension
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. versionadded:: 1.4
-    The C extension was added in Twig 1.4.
-
-Twig comes with a C extension that enhances the performance of the Twig
-runtime engine. You can install it like any other PHP extension:
-
-.. code-block:: bash
-
-    $ cd ext/twig
-    $ phpize
-    $ ./configure
-    $ make
-    $ make install
-
-Finally, enable the extension in your ``php.ini`` configuration file:
-
-.. code-block:: ini
-
-    extension=twig.so
 
-And from now on, Twig will automatically compile your templates to take
-advantage of the C extension. Note that this extension does not replace the
-PHP code but only provides an optimized version of the
-``Twig_Template::getAttribute()`` method.
-
-.. tip::
-
-    On Windows, you can also simply download and install a `pre-built DLL`_.
+    To learn more about the other installation methods, read the
+    :doc:`installation<installation>` chapter; it also explains how to install
+    the Twig C extension.
 
 Basic API Usage
 ---------------
 
 This section gives you a brief introduction to the PHP API for Twig.
 
-The first step to use Twig is to register its autoloader::
-
-    require_once '/path/to/lib/Twig/Autoloader.php';
-    Twig_Autoloader::register();
-
-Replace the ``/path/to/lib/`` path with the path you used for Twig
-installation.
-
-If you have installed Twig via Composer you can take advantage of Composer's
-autoload mechanism by replacing the previous snippet for::
-
-    require_once '/path/to/vendor/autoload.php'
-
-.. note::
-
-    Twig follows the PEAR convention names for its classes, which means you
-    can easily integrate Twig classes loading in your own autoloader.
-
 .. code-block:: php
 
+    require_once '/path/to/vendor/autoload.php';
+
     $loader = new Twig_Loader_String();
     $twig = new Twig_Environment($loader);
 
@@ -159,6 +71,9 @@ filesystem loader::
 
     echo $twig->render('index.html', array('name' => 'Fabien'));
 
-.. _`download page`: https://github.com/fabpot/Twig/tags
-.. _`online documentation`: http://getcomposer.org/doc
-.. _`pre-build DLL`: https://github.com/stealth35/stealth35.github.com/downloads
+.. tip::
+
+    If you are not using Composer, use the Twig built-in autoloader::
+
+        require_once '/path/to/lib/Twig/Autoloader.php';
+        Twig_Autoloader::register();
diff --git a/core/vendor/twig/twig/doc/recipes.rst b/core/vendor/twig/twig/doc/recipes.rst
index dfcc9205160e..bfdfc0d55ed6 100644
--- a/core/vendor/twig/twig/doc/recipes.rst
+++ b/core/vendor/twig/twig/doc/recipes.rst
@@ -335,7 +335,7 @@ you have some dynamic JavaScript files thanks to the ``autoescape`` tag:
 
 But if you have many HTML and JS files, and if your template names follow some
 conventions, you can instead determine the default escaping strategy to use
-based on the template name. Let's say that your template names always ends
+based on the template name. Let's say that your template names always end
 with ``.html`` for HTML files, ``.js`` for JavaScript ones, and ``.css`` for
 stylesheets, here is how you can configure Twig::
 
diff --git a/core/vendor/twig/twig/doc/tags/extends.rst b/core/vendor/twig/twig/doc/tags/extends.rst
index f995a5dcefab..d962a30fb60c 100644
--- a/core/vendor/twig/twig/doc/tags/extends.rst
+++ b/core/vendor/twig/twig/doc/tags/extends.rst
@@ -192,7 +192,7 @@ How blocks work?
 A block provides a way to change how a certain part of a template is rendered
 but it does not interfere in any way with the logic around it.
 
-Let's take the following example to illustrate how a block work and more
+Let's take the following example to illustrate how a block works and more
 importantly, how it does not work:
 
 .. code-block:: jinja
diff --git a/core/vendor/twig/twig/doc/tags/from.rst b/core/vendor/twig/twig/doc/tags/from.rst
index 5337a2355acd..39334fdde255 100644
--- a/core/vendor/twig/twig/doc/tags/from.rst
+++ b/core/vendor/twig/twig/doc/tags/from.rst
@@ -1,7 +1,7 @@
 ``from``
 ========
 
-The ``from`` tags import :doc:`macro<../tags/macro>` names into the current
+The ``from`` tag imports :doc:`macro<../tags/macro>` names into the current
 namespace. The tag is documented in detail in the documentation for the
 :doc:`import<../tags/import>` tag.
 
diff --git a/core/vendor/twig/twig/doc/tags/if.rst b/core/vendor/twig/twig/doc/tags/if.rst
index 14e12b1dfc76..d7a1451c4a76 100644
--- a/core/vendor/twig/twig/doc/tags/if.rst
+++ b/core/vendor/twig/twig/doc/tags/if.rst
@@ -37,7 +37,7 @@ more complex ``expressions`` there too:
     {% if kenny.sick %}
         Kenny is sick.
     {% elseif kenny.dead %}
-        You killed Kenny!  You bastard!!!
+        You killed Kenny! You bastard!!!
     {% else %}
         Kenny looks okay --- so far
     {% endif %}
diff --git a/core/vendor/twig/twig/doc/tags/import.rst b/core/vendor/twig/twig/doc/tags/import.rst
index f6bf718e4e27..21a1e19803b6 100644
--- a/core/vendor/twig/twig/doc/tags/import.rst
+++ b/core/vendor/twig/twig/doc/tags/import.rst
@@ -15,7 +15,7 @@ Imagine we have a helper module that renders forms (called ``forms.html``):
         <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
     {% endmacro %}
 
-    {% macro textarea(name, value, rows) %}
+    {% macro textarea(name, value, rows, cols) %}
         <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>
     {% endmacro %}
 
diff --git a/core/vendor/twig/twig/doc/tags/include.rst b/core/vendor/twig/twig/doc/tags/include.rst
index d83996869218..da18dc65ec4a 100644
--- a/core/vendor/twig/twig/doc/tags/include.rst
+++ b/core/vendor/twig/twig/doc/tags/include.rst
@@ -1,7 +1,7 @@
 ``include``
 ===========
 
-The ``include`` statement includes a template and return the rendered content
+The ``include`` statement includes a template and returns the rendered content
 of that file into the current namespace:
 
 .. code-block:: jinja
@@ -63,7 +63,7 @@ directly::
     The ``ignore missing`` feature has been added in Twig 1.2.
 
 You can mark an include with ``ignore missing`` in which case Twig will ignore
-the statement if the template to be ignored does not exist. It has to be
+the statement if the template to be included does not exist. It has to be
 placed just after the template name. Here some valid examples:
 
 .. code-block:: jinja
diff --git a/core/vendor/twig/twig/doc/tags/macro.rst b/core/vendor/twig/twig/doc/tags/macro.rst
index 155f7fe7b4fc..11c115a08190 100644
--- a/core/vendor/twig/twig/doc/tags/macro.rst
+++ b/core/vendor/twig/twig/doc/tags/macro.rst
@@ -20,7 +20,7 @@ Macros differs from native PHP functions in a few ways:
 
 * Arguments of a macro are always optional.
 
-But as PHP functions, macros don't have access to the current template
+But as with PHP functions, macros don't have access to the current template
 variables.
 
 .. tip::
diff --git a/core/vendor/twig/twig/doc/tags/set.rst b/core/vendor/twig/twig/doc/tags/set.rst
index 15090e7755c2..3eba239a9a77 100644
--- a/core/vendor/twig/twig/doc/tags/set.rst
+++ b/core/vendor/twig/twig/doc/tags/set.rst
@@ -2,31 +2,77 @@
 =======
 
 Inside code blocks you can also assign values to variables. Assignments use
-the ``set`` tag and can have multiple targets:
+the ``set`` tag and can have multiple targets.
+
+Here is how you can assign the ``bar`` value to the ``foo`` variable:
 
 .. code-block:: jinja
 
-    {% set foo = 'foo' %}
+    {% set foo = 'bar' %}
 
-    {% set foo = [1, 2] %}
+After the ``set`` call, the ``foo`` variable is available in the template like
+any other ones:
 
-    {% set foo = {'foo': 'bar'} %}
+.. code-block:: jinja
+
+    {# displays bar #}
+    {{ foo }}
+
+The assigned value can be any valid :ref:`Twig expressions
+<twig-expressions>`:
 
+.. code-block:: jinja
+
+    {% set foo = [1, 2] %}
+    {% set foo = {'foo': 'bar'} %}
     {% set foo = 'foo' ~ 'bar' %}
 
+Several variables can be assigned in one block:
+
+.. code-block:: jinja
+
     {% set foo, bar = 'foo', 'bar' %}
 
+    {# is equivalent to #}
+
+    {% set foo = 'foo' %}
+    {% set bar = 'bar' %}
+
 The ``set`` tag can also be used to 'capture' chunks of text:
 
 .. code-block:: jinja
 
     {% set foo %}
-      <div id="pagination">
-        ...
-      </div>
+        <div id="pagination">
+            ...
+        </div>
     {% endset %}
 
 .. caution::
 
     If you enable automatic output escaping, Twig will only consider the
     content to be safe when capturing chunks of text.
+
+.. note::
+
+    Note that loops are scoped in Twig; therefore a variable declared inside a
+    ``for`` loop is not accessible outside the loop itself:
+
+    .. code-block:: jinja
+
+        {% for item in list %}
+            {% set foo = item %}
+        {% endfor %}
+
+        {# foo is NOT available #}
+
+    If you want to access the variable, just declare it before the loop:
+
+    .. code-block:: jinja
+
+        {% set foo = "" %}
+        {% for item in list %}
+            {% set foo = item %}
+        {% endfor %}
+
+        {# foo is available #}
diff --git a/core/vendor/twig/twig/doc/tags/use.rst b/core/vendor/twig/twig/doc/tags/use.rst
index 085f916108e4..e403632dc7db 100644
--- a/core/vendor/twig/twig/doc/tags/use.rst
+++ b/core/vendor/twig/twig/doc/tags/use.rst
@@ -35,7 +35,7 @@ but without the associated complexity:
     {% block content %}{% endblock %}
 
 The ``use`` statement tells Twig to import the blocks defined in
-```blocks.html`` into the current template (it's like macros, but for blocks):
+``blocks.html`` into the current template (it's like macros, but for blocks):
 
 .. code-block:: jinja
 
diff --git a/core/vendor/twig/twig/doc/templates.rst b/core/vendor/twig/twig/doc/templates.rst
index 94eb9f9906ee..c0ea267430bf 100644
--- a/core/vendor/twig/twig/doc/templates.rst
+++ b/core/vendor/twig/twig/doc/templates.rst
@@ -47,7 +47,7 @@ IDEs Integration
 Many IDEs support syntax highlighting and auto-completion for Twig:
 
 * *Textmate* via the `Twig bundle`_
-* *Vim* via the `Jinja syntax plugin`_
+* *Vim* via the `Jinja syntax plugin`_ or the `vim-twig plugin`_
 * *Netbeans* via the `Twig syntax plugin`_ (until 7.1, native as of 7.2)
 * *PhpStorm* (native as of 2.1)
 * *Eclipse* via the `Twig plugin`_
@@ -167,7 +167,7 @@ To apply a filter on a section of code, wrap it with the
 .. code-block:: jinja
 
     {% filter upper %}
-      This text becomes uppercase
+        This text becomes uppercase
     {% endfilter %}
 
 Go to the :doc:`filters<filters/index>` page to learn more about the built-in
@@ -197,8 +197,6 @@ Named Arguments
 .. versionadded:: 1.12
     Support for named arguments was added in Twig 1.12.
 
-Arguments for filters and functions can also be passed as *named arguments*:
-
 .. code-block:: jinja
 
     {% for i in range(low=1, high=10, step=2) %}
@@ -227,14 +225,12 @@ to change the default value:
     {# or skip the format value by using a named argument for the timezone #}
     {{ "now"|date(timezone="Europe/Paris") }}
 
-You can also use both positional and named arguments in one call, which is not
-recommended as it can be confusing:
+You can also use both positional and named arguments in one call, in which
+case positional arguments must always come before named arguments:
 
 .. code-block:: jinja
 
-    {# both work #}
     {{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }}
-    {{ "now"|date(timezone="Europe/Paris", 'd/m/Y H:i') }}
 
 .. tip::
 
@@ -544,6 +540,8 @@ macro call:
         <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
     {% endmacro %}
 
+.. _twig-expressions:
+
 Expressions
 -----------
 
@@ -554,8 +552,19 @@ even if you're not working with PHP you should feel comfortable with it.
 
     The operator precedence is as follows, with the lowest-precedence
     operators listed first: ``b-and``, ``b-xor``, ``b-or``, ``or``, ``and``,
-    ``==``, ``!=``, ``<``, ``>``, ``>=``, ``<=``, ``in``, ``..``, ``+``,
-    ``-``, ``~``, ``*``, ``/``, ``//``, ``%``, ``is``, and ``**``.
+    ``==``, ``!=``, ``<``, ``>``, ``>=``, ``<=``, ``in``, ``matches``,
+    ``starts with``, ``ends with``, ``..``, ``+``, ``-``, ``~``, ``*``, ``/``,
+    ``//``, ``%``, ``is``, ``**``, ``|``, ``[]``, and ``.``:
+
+    .. code-block:: jinja
+
+        {% set greeting = 'Hello' %}
+        {% set name = 'Fabien' %}
+
+        {{ greeting ~ name|lower }}   {# Hello fabien #}
+
+        {# use parenthesis to change precedence #}
+        {{ (greeting ~ name)|lower }} {# hello fabien #}
 
 Literals
 ~~~~~~~~
@@ -632,8 +641,9 @@ but exists for completeness' sake. The following operators are supported:
 * ``%``: Calculates the remainder of an integer division. ``{{ 11 % 7 }}`` is
   ``4``.
 
-* ``//``: Divides two numbers and returns the truncated integer result. ``{{
-  20 // 7 }}`` is ``2``.
+* ``//``: Divides two numbers and returns the floored integer result. ``{{ 20
+  // 7 }}`` is ``2``, ``{{ -20  // 7 }}`` is ``-3``(this is just syntactic
+  sugar for the :doc:`round<filters/round>` filter).
 
 * ``*``: Multiplies the left operand with the right one. ``{{ 2 * 2 }}`` would
   return ``4``.
@@ -664,6 +674,27 @@ Comparisons
 The following comparison operators are supported in any expression: ``==``,
 ``!=``, ``<``, ``>``, ``>=``, and ``<=``.
 
+You can also check if a string ``starts with`` or ``ends with`` another
+string:
+
+.. code-block:: jinja
+
+    {% if 'Fabien' starts with 'F' %}
+    {% endif %}
+
+    {% if 'Fabien' ends with 'n' %}
+    {% endif %}
+
+.. note::
+
+    For complex string comparisons, the ``matches`` operator allows you to use
+    `regular expressions`_:
+
+    .. code-block:: jinja
+
+        {% if phone matches '{^[\d\.]+$}' %}
+        {% endif %}
+
 Containment Operator
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -709,16 +740,16 @@ Tests can accept arguments too:
 
 .. code-block:: jinja
 
-    {% if loop.index is divisibleby(3) %}
+    {% if post.status is constant('Post::PUBLISHED') %}
 
 Tests can be negated by using the ``is not`` operator:
 
 .. code-block:: jinja
 
-    {% if loop.index is not divisibleby(3) %}
+    {% if post.status is not constant('Post::PUBLISHED') %}
 
     {# is equivalent to #}
-    {% if not (loop.index is divisibleby(3)) %}
+    {% if not (post.status is constant('Post::PUBLISHED')) %}
 
 Go to the :doc:`tests<tests/index>` page to learn more about the built-in
 tests.
@@ -751,8 +782,8 @@ categories:
       {{ foo ? 'yes' : 'no' }}
 
       {# as of Twig 1.12.0 #}
-      {{ foo ?: 'no' }} == {{ foo ? foo : 'no' }}
-      {{ foo ? 'yes' }} == {{ foo ? 'yes' : '' }}
+      {{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }}
+      {{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}
 
 String Interpolation
 ~~~~~~~~~~~~~~~~~~~~
@@ -785,11 +816,11 @@ Use the ``spaceless`` tag to remove whitespace *between HTML tags*:
 
     {% spaceless %}
         <div>
-            <strong>foo</strong>
+            <strong>foo bar</strong>
         </div>
     {% endspaceless %}
 
-    {# output will be <div><strong>foo</strong></div> #}
+    {# output will be <div><strong>foo bar</strong></div> #}
 
 In addition to the spaceless tag you can also control whitespace on a per tag
 level. By using the whitespace control modifier on your tags, you can trim
@@ -829,7 +860,8 @@ If you want to create your own, read the :ref:`Creating an
 Extension<creating_extensions>` chapter.
 
 .. _`Twig bundle`:                https://github.com/Anomareh/PHP-Twig.tmbundle
-.. _`Jinja syntax plugin`:        http://jinja.pocoo.org/2/documentation/integration
+.. _`Jinja syntax plugin`:        http://jinja.pocoo.org/docs/integration/#vim
+.. _`vim-twig plugin`:            https://github.com/evidens/vim-twig
 .. _`Twig syntax plugin`:         http://plugins.netbeans.org/plugin/37069/php-twig
 .. _`Twig plugin`:                https://github.com/pulse00/Twig-Eclipse-Plugin
 .. _`Twig language definition`:   https://github.com/gabrielcorpse/gedit-twig-template-language
@@ -838,3 +870,4 @@ Extension<creating_extensions>` chapter.
 .. _`other Twig syntax mode`:     https://github.com/muxx/Twig-HTML.mode
 .. _`Notepad++ Twig Highlighter`: https://github.com/Banane9/notepadplusplus-twig
 .. _`web-mode.el`:                http://web-mode.org/
+.. _`regular expressions`:        http://php.net/manual/en/pcre.pattern.php
diff --git a/core/vendor/twig/twig/doc/tests/constant.rst b/core/vendor/twig/twig/doc/tests/constant.rst
index 79709335d759..8d0724a809da 100644
--- a/core/vendor/twig/twig/doc/tests/constant.rst
+++ b/core/vendor/twig/twig/doc/tests/constant.rst
@@ -1,6 +1,9 @@
 ``constant``
 ============
 
+.. versionadded: 1.13.1
+    constant now accepts object instances as the second argument.
+
 ``constant`` checks if a variable has the exact same value as a constant. You
 can use either global constants or class constants:
 
@@ -9,3 +12,11 @@ can use either global constants or class constants:
     {% if post.status is constant('Post::PUBLISHED') %}
         the status attribute is exactly the same as Post::PUBLISHED
     {% endif %}
+
+You can test constants from object instances as well:
+
+.. code-block:: jinja
+
+    {% if post.status is constant('PUBLISHED', post) %}
+        the status attribute is exactly the same as Post::PUBLISHED
+    {% endif %}
diff --git a/core/vendor/twig/twig/doc/tests/divisibleby.rst b/core/vendor/twig/twig/doc/tests/divisibleby.rst
index 9b0b96440ac4..6c693b2b47f0 100644
--- a/core/vendor/twig/twig/doc/tests/divisibleby.rst
+++ b/core/vendor/twig/twig/doc/tests/divisibleby.rst
@@ -1,10 +1,14 @@
-``divisibleby``
-===============
+``divisible by``
+================
 
-``divisibleby`` checks if a variable is divisible by a number:
+.. versionadded:: 1.14.2
+    The ``divisible by`` test was added in Twig 1.14.2 as an alias for
+    ``divisibleby``.
+
+``divisible by`` checks if a variable is divisible by a number:
 
 .. code-block:: jinja
 
-    {% if loop.index is divisibleby(3) %}
+    {% if loop.index is divisible by(3) %}
         ...
     {% endif %}
diff --git a/core/vendor/twig/twig/doc/tests/sameas.rst b/core/vendor/twig/twig/doc/tests/sameas.rst
index efb15c35ef08..6ed56d869600 100644
--- a/core/vendor/twig/twig/doc/tests/sameas.rst
+++ b/core/vendor/twig/twig/doc/tests/sameas.rst
@@ -1,11 +1,14 @@
-``sameas``
-==========
+``same as``
+===========
 
-``sameas`` checks if a variable points to the same memory address than another
-variable:
+.. versionadded:: 1.14.2
+    The ``same as`` test was added in Twig 1.14.2 as an alias for ``sameas``.
+
+``same as`` checks if a variable points to the same memory address than
+another variable:
 
 .. code-block:: jinja
 
-    {% if foo.attribute is sameas(false) %}
-        the foo attribute really is the ``false`` PHP value
+    {% if foo.attribute is same as(false) %}
+        the foo attribute really is the 'false' PHP value
     {% endif %}
diff --git a/core/vendor/twig/twig/ext/twig/LICENSE b/core/vendor/twig/twig/ext/twig/LICENSE
index 66b8bb4cbbc1..3384cc5589d5 100644
--- a/core/vendor/twig/twig/ext/twig/LICENSE
+++ b/core/vendor/twig/twig/ext/twig/LICENSE
@@ -1,22 +1,31 @@
-Copyright (c) 2011, Derick Rethans <derick@derickrethans.nl>
-All rights reserved.
+Copyright (c) 2009-2013 by the Twig Team, see AUTHORS for more details.
 
-Redistribution and use in source and binary forms, with or without 
-modification, are permitted provided that the following conditions are met:
+Some rights reserved.
 
-    * 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.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
 
-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 
+    * 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.
diff --git a/core/vendor/twig/twig/ext/twig/php_twig.h b/core/vendor/twig/twig/ext/twig/php_twig.h
index 0a11224744ad..6570967497f7 100644
--- a/core/vendor/twig/twig/ext/twig/php_twig.h
+++ b/core/vendor/twig/twig/ext/twig/php_twig.h
@@ -6,7 +6,7 @@
    +----------------------------------------------------------------------+
    | Redistribution and use in source and binary forms, with or without   |
    | modification, are permitted provided that the conditions mentioned   |
-   | in the accompanying LICENSE file are met (BSD, revised).             |
+   | in the accompanying LICENSE file are met (BSD-3-Clause).             |
    +----------------------------------------------------------------------+
    | Author: Derick Rethans <derick@derickrethans.nl>                     |
    +----------------------------------------------------------------------+
@@ -15,7 +15,7 @@
 #ifndef PHP_TWIG_H
 #define PHP_TWIG_H
 
-#define PHP_TWIG_VERSION "1.12.3"
+#define PHP_TWIG_VERSION "1.15.0"
 
 #include "php.h"
 
diff --git a/core/vendor/twig/twig/ext/twig/twig.c b/core/vendor/twig/twig/ext/twig/twig.c
index bb8a151fd329..6ad823d51c92 100644
--- a/core/vendor/twig/twig/ext/twig/twig.c
+++ b/core/vendor/twig/twig/ext/twig/twig.c
@@ -6,7 +6,7 @@
    +----------------------------------------------------------------------+
    | Redistribution and use in source and binary forms, with or without   |
    | modification, are permitted provided that the conditions mentioned   |
-   | in the accompanying LICENSE file are met (BSD, revised).             |
+   | in the accompanying LICENSE file are met (BSD-3-Clause).             |
    +----------------------------------------------------------------------+
    | Author: Derick Rethans <derick@derickrethans.nl>                     |
    +----------------------------------------------------------------------+
@@ -18,8 +18,10 @@
 
 #include "php.h"
 #include "php_twig.h"
+#include "ext/standard/php_var.h"
 #include "ext/standard/php_string.h"
 #include "ext/standard/php_smart_str.h"
+#include "ext/spl/spl_exceptions.h"
 
 #include "Zend/zend_object_handlers.h"
 #include "Zend/zend_interfaces.h"
@@ -76,12 +78,26 @@ zend_module_entry twig_module_entry = {
 ZEND_GET_MODULE(twig)
 #endif
 
-int TWIG_ARRAY_KEY_EXISTS(zval *array, char* key, int key_len)
+int TWIG_ARRAY_KEY_EXISTS(zval *array, zval *key)
 {
 	if (Z_TYPE_P(array) != IS_ARRAY) {
 		return 0;
 	}
-	return zend_symtable_exists(Z_ARRVAL_P(array), key, key_len + 1);
+
+	switch (Z_TYPE_P(key)) {
+		case IS_NULL:
+			return zend_hash_exists(Z_ARRVAL_P(array), "", 1);
+
+		case IS_BOOL:
+		case IS_DOUBLE:
+			convert_to_long(key);
+		case IS_LONG:
+			return zend_hash_index_exists(Z_ARRVAL_P(array), Z_LVAL_P(key));
+
+		default:
+			convert_to_string(key);
+			return zend_symtable_exists(Z_ARRVAL_P(array), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1);
+	}
 }
 
 int TWIG_INSTANCE_OF(zval *object, zend_class_entry *interface TSRMLS_DC)
@@ -106,23 +122,23 @@ int TWIG_INSTANCE_OF_USERLAND(zval *object, char *interface TSRMLS_DC)
 
 zval *TWIG_GET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
 {
-    zend_class_entry *ce = Z_OBJCE_P(object);
-    zval *retval;
+	zend_class_entry *ce = Z_OBJCE_P(object);
+	zval *retval;
 
 	if (Z_TYPE_P(object) == IS_OBJECT) {
 		SEPARATE_ARG_IF_REF(offset);
 		zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset);
 
-        zval_ptr_dtor(&offset);
+		zval_ptr_dtor(&offset);
 
-        if (!retval) {
-            if (!EG(exception)) {
-                zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
-            }
-            return NULL;
-        }
+		if (!retval) {
+			if (!EG(exception)) {
+				zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
+			}
+			return NULL;
+		}
 
-        return retval;
+		return retval;
 	}
 	return NULL;
 }
@@ -200,8 +216,8 @@ zval *TWIG_CALL_USER_FUNC_ARRAY(zval *object, char *function, zval *arguments TS
 	fci.no_separation = 0;
 
 	if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
-		FREE_DTOR(zfunction)
-		zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", zend_get_class_entry(object TSRMLS_CC)->name, function TSRMLS_CC);
+		ALLOC_INIT_ZVAL(retval_ptr);
+		ZVAL_BOOL(retval_ptr, 0);
 	}
 
 	if (args) {
@@ -243,9 +259,8 @@ zval *TWIG_GET_STATIC_PROPERTY(zval *class, char *prop_name TSRMLS_DC)
 zval *TWIG_GET_ARRAY_ELEMENT_ZVAL(zval *class, zval *prop_name TSRMLS_DC)
 {
 	zval **tmp_zval;
-	char *tmp_name;
 
-	if (class == NULL || Z_TYPE_P(class) != IS_ARRAY || Z_TYPE_P(prop_name) != IS_STRING) {
+	if (class == NULL || Z_TYPE_P(class) != IS_ARRAY) {
 		if (class != NULL && Z_TYPE_P(class) == IS_OBJECT && TWIG_INSTANCE_OF(class, zend_ce_arrayaccess TSRMLS_CC)) {
 			// array access object
 			return TWIG_GET_ARRAYOBJECT_ELEMENT(class, prop_name TSRMLS_CC);
@@ -253,11 +268,23 @@ zval *TWIG_GET_ARRAY_ELEMENT_ZVAL(zval *class, zval *prop_name TSRMLS_DC)
 		return NULL;
 	}
 
-	convert_to_string(prop_name);
-	tmp_name = Z_STRVAL_P(prop_name);
-	if (zend_symtable_find(HASH_OF(class), tmp_name, strlen(tmp_name)+1, (void**) &tmp_zval) == SUCCESS) {
-		return *tmp_zval;
+	switch(Z_TYPE_P(prop_name)) {
+		case IS_NULL:
+			zend_hash_find(HASH_OF(class), "", 1, (void**) &tmp_zval);
+			return *tmp_zval;
+
+		case IS_BOOL:
+		case IS_DOUBLE:
+			convert_to_long(prop_name);
+		case IS_LONG:
+			zend_hash_index_find(HASH_OF(class), Z_LVAL_P(prop_name), (void **) &tmp_zval);
+			return *tmp_zval;
+
+		case IS_STRING:
+			zend_symtable_find(HASH_OF(class), Z_STRVAL_P(prop_name), Z_STRLEN_P(prop_name) + 1, (void**) &tmp_zval);
+			return *tmp_zval;
 	}
+
 	return NULL;
 }
 
@@ -669,7 +696,7 @@ static int twig_add_property_to_class(void *pDest APPLY_TSRMLS_DC, int num_args,
 	zend_property_info *pptr = (zend_property_info *) pDest;
 	APPLY_TSRMLS_FETCH();
 
-	if (!(pptr->flags & ZEND_ACC_PUBLIC)) {
+	if (!(pptr->flags & ZEND_ACC_PUBLIC) || (pptr->flags & ZEND_ACC_STATIC)) {
 		return 0;
 	}
 
@@ -717,7 +744,7 @@ PHP_FUNCTION(twig_template_get_attributes)
 	zval *object;
 	char *item;
 	int  item_len;
-	zval  zitem;
+	zval *zitem, ztmpitem;
 	zval *arguments = NULL;
 	zval *ret = NULL;
 	char *type = NULL;
@@ -726,24 +753,21 @@ PHP_FUNCTION(twig_template_get_attributes)
 	zend_bool ignoreStrictCheck = 0;
 	int free_ret = 0;
 	zval *tmp_self_cache;
+	char *class_name = NULL;
+	zval *tmp_class;
+	char *type_name;
 
-
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ozs|asbb", &template, &object, &item, &item_len, &arguments, &type, &type_len, &isDefinedTest, &ignoreStrictCheck) == FAILURE) {
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ozz|asbb", &template, &object, &zitem, &arguments, &type, &type_len, &isDefinedTest, &ignoreStrictCheck) == FAILURE) {
 		return;
 	}
 
-	INIT_PZVAL(&zitem);
-	ZVAL_STRINGL(&zitem, item, item_len, 0);
-
-    switch (is_numeric_string(item, item_len, &Z_LVAL(zitem), &Z_DVAL(zitem), 0)) {
-    case IS_LONG:
-        Z_TYPE(zitem) = IS_LONG;
-        break;
-    case IS_DOUBLE:
-        Z_TYPE(zitem) = IS_DOUBLE;
-        convert_to_long(&zitem);
-        break;
-    }
+	// convert the item to a string
+	ztmpitem = *zitem;
+	zval_copy_ctor(&ztmpitem);
+	convert_to_string(&ztmpitem);
+	item_len = Z_STRLEN(ztmpitem);
+	item = estrndup(Z_STRVAL(ztmpitem), item_len);
+	zval_dtor(&ztmpitem);
 
 	if (!type) {
 		type = "any";
@@ -751,29 +775,32 @@ PHP_FUNCTION(twig_template_get_attributes)
 
 /*
 	// array
-	if (Twig_TemplateInterface::METHOD_CALL !== $type) {
-		if ((is_array($object) && array_key_exists($item, $object))
-			|| ($object instanceof ArrayAccess && isset($object[$item]))
+	if (Twig_Template::METHOD_CALL !== $type) {
+		$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
+
+		if ((is_array($object) && array_key_exists($arrayItem, $object))
+			|| ($object instanceof ArrayAccess && isset($object[$arrayItem]))
 		) {
 			if ($isDefinedTest) {
 				return true;
 			}
 
-			return $object[$item];
+			return $object[$arrayItem];
 		}
 */
+
+
 	if (strcmp("method", type) != 0) {
-//		printf("XXXmethod: %s\n", type);
-		if ((TWIG_ARRAY_KEY_EXISTS(object, item, item_len))
-			|| (TWIG_INSTANCE_OF(object, zend_ce_arrayaccess TSRMLS_CC) && TWIG_ISSET_ARRAYOBJECT_ELEMENT(object, &zitem TSRMLS_CC))
+		if ((TWIG_ARRAY_KEY_EXISTS(object, zitem))
+			|| (TWIG_INSTANCE_OF(object, zend_ce_arrayaccess TSRMLS_CC) && TWIG_ISSET_ARRAYOBJECT_ELEMENT(object, zitem TSRMLS_CC))
 		) {
-			zval *ret;
 
 			if (isDefinedTest) {
 				RETURN_TRUE;
 			}
 
-			ret = TWIG_GET_ARRAY_ELEMENT(object, item, item_len TSRMLS_CC);
+			ret = TWIG_GET_ARRAY_ELEMENT_ZVAL(object, zitem TSRMLS_CC);
+
 			if (!ret) {
 				ret = &EG(uninitialized_zval);
 			}
@@ -784,7 +811,7 @@ PHP_FUNCTION(twig_template_get_attributes)
 			return;
 		}
 /*
-		if (Twig_TemplateInterface::ARRAY_CALL === $type) {
+		if (Twig_Template::ARRAY_CALL === $type) {
 			if ($isDefinedTest) {
 				return false;
 			}
@@ -792,7 +819,7 @@ PHP_FUNCTION(twig_template_get_attributes)
 				return null;
 			}
 */
-		if (strcmp("array", type) == 0) {
+		if (strcmp("array", type) == 0 || Z_TYPE_P(object) != IS_OBJECT) {
 			if (isDefinedTest) {
 				RETURN_FALSE;
 			}
@@ -801,11 +828,13 @@ PHP_FUNCTION(twig_template_get_attributes)
 			}
 /*
 			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)), -1, $this->getTemplateName());
+				throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $arrayItem, 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))), -1, $this->getTemplateName());
+				throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))), -1, $this->getTemplateName());
+			} elseif (Twig_Template::ARRAY_CALL === $type) {
+				throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
 			} else {
-				throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a "%s" variable', $item, gettype($object)), -1, $this->getTemplateName());
+				throw new Twig_Error_Runtime(sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
 			}
 		}
 	}
@@ -815,7 +844,15 @@ PHP_FUNCTION(twig_template_get_attributes)
 			} else if (Z_TYPE_P(object) == IS_ARRAY) {
 				TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" for array with keys \"%s\" does not exist", item, TWIG_IMPLODE_ARRAY_KEYS(", ", object TSRMLS_CC));
 			} else {
-				TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to access a key (\"%s\") on a \"%s\" variable", item, zend_zval_type_name(object));
+				char *type_name = zend_zval_type_name(object);
+				Z_ADDREF_P(object);
+				convert_to_string(object);
+				TWIG_RUNTIME_ERROR(template TSRMLS_CC,
+					(strcmp("array", type) == 0)
+						? "Impossible to access a key (\"%s\") on a %s variable (\"%s\")"
+						: "Impossible to access an attribute (\"%s\") on a %s variable (\"%s\")",
+					item, type_name, Z_STRVAL_P(object));
+				zval_ptr_dtor(&object);
 			}
 			return;
 		}
@@ -836,58 +873,45 @@ PHP_FUNCTION(twig_template_get_attributes)
 		if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
 			return null;
 		}
-		throw new Twig_Error_Runtime(sprintf('Item "%s" for "%s" does not exist', $item, implode(', ', array_keys($object))));
+		throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
 	}
 */
 		if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
-			RETURN_FALSE;
-		}
-		if (Z_TYPE_P(object) == IS_ARRAY) {
-			TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Item \"%s\" for \"Array\" does not exist", item);
-		} else {
-			Z_ADDREF_P(object);
-			convert_to_string_ex(&object);
-			TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Item \"%s\" for \"%s\" does not exist", item, Z_STRVAL_P(object));
-			zval_ptr_dtor(&object);
+			return;
 		}
+
+		type_name = zend_zval_type_name(object);
+		Z_ADDREF_P(object);
+		convert_to_string_ex(&object);
+
+		TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable (\"%s\")", item, type_name, Z_STRVAL_P(object));
+
+		zval_ptr_dtor(&object);
+
 		return;
 	}
 /*
-	// get some information about the object
 	$class = get_class($object);
-	if (!isset(self::$cache[$class])) {
-		$r = new ReflectionClass($class);
-		self::$cache[$class] = array('methods' => array(), 'properties' => array());
-		foreach ($r->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
-			self::$cache[$class]['methods'][strtolower($method->getName())] = true;
-		}
-
-		foreach ($r->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
-			self::$cache[$class]['properties'][$property->getName()] = true;
-		}
-	}
 */
-	if (Z_TYPE_P(object) == IS_OBJECT) {
-		char *class_name = NULL;
 
-		class_name = TWIG_GET_CLASS_NAME(object TSRMLS_CC);
-		tmp_self_cache = TWIG_GET_STATIC_PROPERTY(template, "cache" TSRMLS_CC);
+	class_name = TWIG_GET_CLASS_NAME(object TSRMLS_CC);
+	tmp_self_cache = TWIG_GET_STATIC_PROPERTY(template, "cache" TSRMLS_CC);
+	tmp_class = TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC);
 
-		if (!TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC)) {
-			twig_add_class_to_cache(tmp_self_cache, object, class_name TSRMLS_CC);
-		}
-		efree(class_name);
+	if (!tmp_class) {
+		twig_add_class_to_cache(tmp_self_cache, object, class_name TSRMLS_CC);
+		tmp_class = TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC);
 	}
+	efree(class_name);
 
 /*
 	// object property
-	if (Twig_TemplateInterface::METHOD_CALL !== $type) {
-		if (isset(self::$cache[$class]['properties'][$item])
-			|| isset($object->$item) || array_key_exists($item, $object)
-		) {
+	if (Twig_Template::METHOD_CALL !== $type) {
+		if (isset($object->$item) || array_key_exists((string) $item, $object)) {
 			if ($isDefinedTest) {
 				return true;
 			}
+
 			if ($this->env->hasExtension('sandbox')) {
 				$this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
 			}
@@ -897,53 +921,54 @@ PHP_FUNCTION(twig_template_get_attributes)
 	}
 */
 	if (strcmp("method", type) != 0) {
-		zval *tmp_class, *tmp_properties, *tmp_item;
-		char *class_name = NULL;
+		zval *tmp_properties, *tmp_item;
 
-		class_name = TWIG_GET_CLASS_NAME(object TSRMLS_CC);
-		tmp_class = TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC);
 		tmp_properties = TWIG_GET_ARRAY_ELEMENT(tmp_class, "properties", strlen("properties") TSRMLS_CC);
 		tmp_item = TWIG_GET_ARRAY_ELEMENT(tmp_properties, item, item_len TSRMLS_CC);
 
-		efree(class_name);
-
-		if (tmp_item || TWIG_HAS_PROPERTY(object, &zitem TSRMLS_CC) || TWIG_HAS_DYNAMIC_PROPERTY(object, item, item_len TSRMLS_CC)) {
+		if (tmp_item || TWIG_HAS_PROPERTY(object, zitem TSRMLS_CC) || TWIG_HAS_DYNAMIC_PROPERTY(object, item, item_len TSRMLS_CC)) {
 			if (isDefinedTest) {
 				RETURN_TRUE;
 			}
 			if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "sandbox" TSRMLS_CC)) {
-				TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkPropertyAllowed", object, &zitem TSRMLS_CC);
+				TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkPropertyAllowed", object, zitem TSRMLS_CC);
 			}
 			if (EG(exception)) {
 				return;
 			}
 
-			ret = TWIG_PROPERTY(object, &zitem TSRMLS_CC);
+			ret = TWIG_PROPERTY(object, zitem TSRMLS_CC);
 			RETURN_ZVAL(ret, 1, 0);
 		}
 	}
 /*
 	// object method
+	if (!isset(self::$cache[$class]['methods'])) {
+		self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
+	}
+
+	$call = false;
 	$lcItem = strtolower($item);
 	if (isset(self::$cache[$class]['methods'][$lcItem])) {
-		$method = $item;
+		$method = (string) $item;
 	} elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
 		$method = 'get'.$item;
 	} elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
 		$method = 'is'.$item;
 	} elseif (isset(self::$cache[$class]['methods']['__call'])) {
-		$method = $item;
+		$method = (string) $item;
+		$call = true;
 */
 	{
+		int call = 0;
 		char *lcItem = TWIG_STRTOLOWER(item, item_len);
 		int   lcItem_length;
 		char *method = NULL;
 		char *tmp_method_name_get;
 		char *tmp_method_name_is;
-		zval *tmp_class, *tmp_methods;
-		char *class_name = NULL;
+		zval *zmethod;
+		zval *tmp_methods;
 
-		class_name = TWIG_GET_CLASS_NAME(object TSRMLS_CC);
 		lcItem_length = strlen(lcItem);
 		tmp_method_name_get = emalloc(4 + lcItem_length);
 		tmp_method_name_is  = emalloc(3 + lcItem_length);
@@ -951,9 +976,7 @@ PHP_FUNCTION(twig_template_get_attributes)
 		sprintf(tmp_method_name_get, "get%s", lcItem);
 		sprintf(tmp_method_name_is, "is%s", lcItem);
 
-		tmp_class = TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC);
 		tmp_methods = TWIG_GET_ARRAY_ELEMENT(tmp_class, "methods", strlen("methods") TSRMLS_CC);
-		efree(class_name);
 
 		if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, lcItem, lcItem_length TSRMLS_CC)) {
 			method = item;
@@ -963,16 +986,20 @@ PHP_FUNCTION(twig_template_get_attributes)
 			method = tmp_method_name_is;
 		} else if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, "__call", 6 TSRMLS_CC)) {
 			method = item;
+			call = 1;
 /*
 	} else {
 		if ($isDefinedTest) {
 			return false;
 		}
+
 		if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
 			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) {
 		return true;
 	}
@@ -1003,27 +1030,46 @@ PHP_FUNCTION(twig_template_get_attributes)
 		$this->env->getExtension('sandbox')->checkMethodAllowed($object, $method);
 	}
 */
+		MAKE_STD_ZVAL(zmethod);
+		ZVAL_STRING(zmethod, method, 1);
 		if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "sandbox" TSRMLS_CC)) {
-			TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkMethodAllowed", object, &zitem TSRMLS_CC);
+			TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkMethodAllowed", object, zmethod TSRMLS_CC);
 		}
 		if (EG(exception)) {
 			efree(tmp_method_name_get);
 			efree(tmp_method_name_is);
 			efree(lcItem);
+			zval_ptr_dtor(&zmethod);
 			return;
 		}
 /*
-	$ret = call_user_func_array(array($object, $method), $arguments);
+	// Some objects throw exceptions when they have __call, and the method we try
+	// to call is not supported. If ignoreStrictCheck is true, we should return null.
+	try {
+	    $ret = call_user_func_array(array($object, $method), $arguments);
+	} catch (BadMethodCallException $e) {
+	    if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
+	        return null;
+	    }
+	    throw $e;
+	}
 */
-		if (Z_TYPE_P(object) == IS_OBJECT) {
-			ret = TWIG_CALL_USER_FUNC_ARRAY(object, method, arguments TSRMLS_CC);
-			free_ret = 1;
+		ret = TWIG_CALL_USER_FUNC_ARRAY(object, method, arguments TSRMLS_CC);
+		if (EG(exception) && TWIG_INSTANCE_OF(EG(exception), spl_ce_BadMethodCallException TSRMLS_CC)) {
+			if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
+				zend_clear_exception(TSRMLS_C);
+				return;
+			}
 		}
+		free_ret = 1;
 		efree(tmp_method_name_get);
 		efree(tmp_method_name_is);
 		efree(lcItem);
+		zval_ptr_dtor(&zmethod);
 	}
 /*
+	// 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());
 	}
@@ -1033,9 +1079,7 @@ PHP_FUNCTION(twig_template_get_attributes)
 	// ret can be null, if e.g. the called method throws an exception
 	if (ret) {
 		if (TWIG_INSTANCE_OF_USERLAND(object, "Twig_TemplateInterface" TSRMLS_CC)) {
-			if (Z_STRLEN_P(ret) == 0) {
-				free_ret = 1;
-			} else {
+			if (Z_STRLEN_P(ret) != 0) {
 				zval *charset = TWIG_CALL_USER_FUNC_ARRAY(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getCharset", NULL TSRMLS_CC);
 				TWIG_NEW(return_value, "Twig_Markup", ret, charset TSRMLS_CC);
 				zval_ptr_dtor(&charset);
diff --git a/core/vendor/twig/twig/lib/Twig/Autoloader.php b/core/vendor/twig/twig/lib/Twig/Autoloader.php
index d1e005b11fc9..7007d3157c59 100644
--- a/core/vendor/twig/twig/lib/Twig/Autoloader.php
+++ b/core/vendor/twig/twig/lib/Twig/Autoloader.php
@@ -18,11 +18,16 @@ class Twig_Autoloader
 {
     /**
      * Registers Twig_Autoloader as an SPL autoloader.
+     *
+     * @param Boolean $prepend Whether to prepend the autoloader or not.
      */
-    public static function register()
+    public static function register($prepend = false)
     {
-        ini_set('unserialize_callback_func', 'spl_autoload_call');
-        spl_autoload_register(array(new self, 'autoload'));
+        if (version_compare(phpversion(), '5.3.0', '>=')) {
+            spl_autoload_register(array(new self, 'autoload'), true, $prepend);
+        } else {
+            spl_autoload_register(array(new self, 'autoload'));
+        }
     }
 
     /**
diff --git a/core/vendor/twig/twig/lib/Twig/Compiler.php b/core/vendor/twig/twig/lib/Twig/Compiler.php
index 99aecbcca57f..7a87cf88c500 100644
--- a/core/vendor/twig/twig/lib/Twig/Compiler.php
+++ b/core/vendor/twig/twig/lib/Twig/Compiler.php
@@ -180,11 +180,12 @@ public function repr($value)
             $this->raw($value ? 'true' : 'false');
         } elseif (is_array($value)) {
             $this->raw('array(');
-            $i = 0;
+            $first = true;
             foreach ($value as $key => $value) {
-                if ($i++) {
+                if (!$first) {
                     $this->raw(', ');
                 }
+                $first = false;
                 $this->repr($key);
                 $this->raw(' => ');
                 $this->repr($value);
@@ -252,6 +253,8 @@ public function indent($step = 1)
      * @param integer $step The number of indentation to remove
      *
      * @return Twig_Compiler The current compiler instance
+     *
+     * @throws LogicException When trying to outdent too much so the indentation would become negative
      */
     public function outdent($step = 1)
     {
diff --git a/core/vendor/twig/twig/lib/Twig/Environment.php b/core/vendor/twig/twig/lib/Twig/Environment.php
index 0a4ff32ef78c..3b25c5edc5c8 100644
--- a/core/vendor/twig/twig/lib/Twig/Environment.php
+++ b/core/vendor/twig/twig/lib/Twig/Environment.php
@@ -16,7 +16,7 @@
  */
 class Twig_Environment
 {
-    const VERSION = '1.12.3';
+    const VERSION = '1.15.0';
 
     protected $charset;
     protected $loader;
@@ -53,7 +53,7 @@ class Twig_Environment
      *  * 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).
+     *  * charset: The charset used by the templates (default to UTF-8).
      *
      *  * base_template_class: The base template class to use for generated
      *                         templates (default to Twig_Template).
@@ -61,9 +61,9 @@ class Twig_Environment
      *  * cache: An absolute path where to store the compiled templates, or
      *           false to disable compilation cache (default).
      *
-     *  * auto_reload: Whether to reload the template is the original source changed.
+     *  * auto_reload: Whether to reload the template if the original source changed.
      *                 If you don't provide the auto_reload option, it will be
-     *                 determined automatically base on the debug value.
+     *                 determined automatically based on the debug value.
      *
      *  * strict_variables: Whether to ignore invalid variables in templates
      *                      (default to false).
@@ -99,7 +99,7 @@ public function __construct(Twig_LoaderInterface $loader = null, $options = arra
         ), $options);
 
         $this->debug              = (bool) $options['debug'];
-        $this->charset            = $options['charset'];
+        $this->charset            = strtoupper($options['charset']);
         $this->baseTemplateClass  = $options['base_template_class'];
         $this->autoReload         = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
         $this->strictVariables    = (bool) $options['strict_variables'];
@@ -239,7 +239,7 @@ public function setCache($cache)
      *
      * @param string $name The template name
      *
-     * @return string The cache file name
+     * @return string|false The cache file name or false when caching is disabled
      */
     public function getCacheFilename($name)
     {
@@ -262,7 +262,7 @@ public function getCacheFilename($name)
      */
     public function getTemplateClass($name, $index = null)
     {
-        return $this->templateClassPrefix.md5($this->getLoader()->getCacheKey($name)).(null === $index ? '' : '_'.$index);
+        return $this->templateClassPrefix.hash('sha256', $this->getLoader()->getCacheKey($name)).(null === $index ? '' : '_'.$index);
     }
 
     /**
@@ -282,6 +282,10 @@ public function getTemplateClassPrefix()
      * @param array  $context An array of parameters to pass to the template
      *
      * @return string The rendered template
+     *
+     * @throws Twig_Error_Loader  When the template cannot be found
+     * @throws Twig_Error_Syntax  When an error occurred during compilation
+     * @throws Twig_Error_Runtime When an error occurred during rendering
      */
     public function render($name, array $context = array())
     {
@@ -293,6 +297,10 @@ public function render($name, array $context = array())
      *
      * @param string $name    The template name
      * @param array  $context An array of parameters to pass to the template
+     *
+     * @throws Twig_Error_Loader  When the template cannot be found
+     * @throws Twig_Error_Syntax  When an error occurred during compilation
+     * @throws Twig_Error_Runtime When an error occurred during rendering
      */
     public function display($name, array $context = array())
     {
@@ -306,6 +314,9 @@ public function display($name, array $context = array())
      * @param integer $index The index if it is an embedded template
      *
      * @return Twig_TemplateInterface A template instance representing the given template name
+     *
+     * @throws Twig_Error_Loader When the template cannot be found
+     * @throws Twig_Error_Syntax When an error occurred during compilation
      */
     public function loadTemplate($name, $index = null)
     {
@@ -358,6 +369,19 @@ public function isTemplateFresh($name, $time)
         return $this->getLoader()->isFresh($name, $time);
     }
 
+    /**
+     * Tries to load a template consecutively from an array.
+     *
+     * Similar to loadTemplate() but it also accepts Twig_TemplateInterface instances and an array
+     * of templates where each is tried to be loaded.
+     *
+     * @param string|Twig_Template|array $names A template or an array of templates to try consecutively
+     *
+     * @return Twig_Template
+     *
+     * @throws Twig_Error_Loader When none of the templates can be found
+     * @throws Twig_Error_Syntax When an error occurred during compilation
+     */
     public function resolveTemplate($names)
     {
         if (!is_array($names)) {
@@ -437,6 +461,8 @@ public function setLexer(Twig_LexerInterface $lexer)
      * @param string $name   The template name
      *
      * @return Twig_TokenStream A Twig_TokenStream instance
+     *
+     * @throws Twig_Error_Syntax When the code is syntactically wrong
      */
     public function tokenize($source, $name = null)
     {
@@ -468,15 +494,17 @@ public function setParser(Twig_ParserInterface $parser)
     }
 
     /**
-     * Parses a token stream.
+     * Converts a token stream to a node tree.
      *
-     * @param Twig_TokenStream $tokens A Twig_TokenStream instance
+     * @param Twig_TokenStream $stream A token stream instance
      *
-     * @return Twig_Node_Module A Node tree
+     * @return Twig_Node_Module A node tree
+     *
+     * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
      */
-    public function parse(Twig_TokenStream $tokens)
+    public function parse(Twig_TokenStream $stream)
     {
-        return $this->getParser()->parse($tokens);
+        return $this->getParser()->parse($stream);
     }
 
     /**
@@ -504,7 +532,7 @@ public function setCompiler(Twig_CompilerInterface $compiler)
     }
 
     /**
-     * Compiles a Node.
+     * Compiles a node and returns the PHP code.
      *
      * @param Twig_NodeInterface $node A Twig_NodeInterface instance
      *
@@ -522,6 +550,8 @@ public function compile(Twig_NodeInterface $node)
      * @param string $name   The template name
      *
      * @return string The compiled PHP source code
+     *
+     * @throws Twig_Error_Syntax When there was an error during tokenizing, parsing or compiling
      */
     public function compileSource($source, $name = null)
     {
@@ -531,7 +561,7 @@ public function compileSource($source, $name = null)
             $e->setTemplateFile($name);
             throw $e;
         } catch (Exception $e) {
-            throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $name, $e);
+            throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $name, $e);
         }
     }
 
@@ -566,7 +596,7 @@ public function getLoader()
      */
     public function setCharset($charset)
     {
-        $this->charset = $charset;
+        $this->charset = strtoupper($charset);
     }
 
     /**
@@ -728,7 +758,7 @@ public function getTags()
     public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
     {
         if ($this->extensionInitialized) {
-            throw new LogicException('Unable to add a node visitor as extensions have already been initialized.', $extension->getName());
+            throw new LogicException('Unable to add a node visitor as extensions have already been initialized.');
         }
 
         $this->staging->addNodeVisitor($visitor);
@@ -764,11 +794,11 @@ public function addFilter($name, $filter = null)
             $filter = $name;
             $name = $filter->getName();
         }
-        
+
         if ($this->extensionInitialized) {
             throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
         }
-        
+
         $this->staging->addFilter($name, $filter);
     }
 
@@ -853,7 +883,7 @@ public function addTest($name, $test = null)
             $test = $name;
             $name = $test->getName();
         }
-        
+
         if ($this->extensionInitialized) {
             throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
         }
@@ -911,11 +941,11 @@ public function addFunction($name, $function = null)
             $function = $name;
             $name = $function->getName();
         }
-        
+
         if ($this->extensionInitialized) {
             throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
         }
-        
+
         $this->staging->addFunction($name, $function);
     }
 
@@ -1099,10 +1129,17 @@ protected function initGlobals()
     {
         $globals = array();
         foreach ($this->extensions as $extension) {
-            $globals = array_merge($globals, $extension->getGlobals());
+            $extGlob = $extension->getGlobals();
+            if (!is_array($extGlob)) {
+                throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension)));
+            }
+
+            $globals[] = $extGlob;
         }
 
-        return array_merge($globals, $this->staging->getGlobals());
+        $globals[] = $this->staging->getGlobals();
+
+        return call_user_func_array('array_merge', $globals);
     }
 
     protected function initExtensions()
@@ -1202,7 +1239,7 @@ protected function writeCacheFile($file, $content)
             throw new RuntimeException(sprintf("Unable to write in the cache directory (%s).", $dir));
         }
 
-        $tmpFile = tempnam(dirname($file), basename($file));
+        $tmpFile = tempnam($dir, basename($file));
         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))) {
diff --git a/core/vendor/twig/twig/lib/Twig/Error.php b/core/vendor/twig/twig/lib/Twig/Error.php
index e77ec98d75d3..914b3ed30ebf 100644
--- a/core/vendor/twig/twig/lib/Twig/Error.php
+++ b/core/vendor/twig/twig/lib/Twig/Error.php
@@ -186,10 +186,21 @@ protected function updateRepr()
     protected function guessTemplateInfo()
     {
         $template = null;
-        foreach (debug_backtrace() as $trace) {
+        $templateClass = null;
+
+        if (version_compare(phpversion(), '5.3.6', '>=')) {
+            $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
+        } else {
+            $backtrace = debug_backtrace();
+        }
+
+        foreach ($backtrace as $trace) {
             if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
-                if (null === $this->filename || $this->filename == $trace['object']->getTemplateName()) {
+                $currentClass = get_class($trace['object']);
+                $isEmbedContainer = 0 === strpos($templateClass, $currentClass);
+                if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
                     $template = $trace['object'];
+                    $templateClass = get_class($trace['object']);
                 }
             }
         }
@@ -206,6 +217,11 @@ protected function guessTemplateInfo()
         $r = new ReflectionObject($template);
         $file = $r->getFileName();
 
+        // hhvm has a bug where eval'ed files comes out as the current directory
+        if (is_dir($file)) {
+            $file = '';
+        }
+
         $exceptions = array($e = $this);
         while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) {
             $exceptions[] = $e;
diff --git a/core/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php b/core/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php
index ce4347655076..da05a54eeb17 100644
--- a/core/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php
+++ b/core/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php
@@ -22,7 +22,7 @@ interface Twig_ExistsLoaderInterface
      *
      * @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
+     * @return Boolean If the template source code is handled by this loader or not
      */
     public function exists($name);
 }
diff --git a/core/vendor/twig/twig/lib/Twig/ExpressionParser.php b/core/vendor/twig/twig/lib/Twig/ExpressionParser.php
index 131c6c27d423..bd8ee4556354 100644
--- a/core/vendor/twig/twig/lib/Twig/ExpressionParser.php
+++ b/core/vendor/twig/twig/lib/Twig/ExpressionParser.php
@@ -86,18 +86,15 @@ protected function getPrimary()
 
     protected function parseConditionalExpression($expr)
     {
-        while ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '?')) {
-            $this->parser->getStream()->next();
-            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
+        while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) {
+            if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
                 $expr2 = $this->parseExpression();
-                if ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
-                    $this->parser->getStream()->next();
+                if ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
                     $expr3 = $this->parseExpression();
                 } else {
                     $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine());
                 }
             } else {
-                $this->parser->getStream()->next();
                 $expr2 = $expr;
                 $expr3 = $this->parseExpression();
             }
@@ -161,6 +158,14 @@ public function parsePrimaryExpression()
                 $node = $this->parseStringExpression();
                 break;
 
+            case Twig_Token::OPERATOR_TYPE:
+                if (preg_match(Twig_Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) {
+                    // in this context, string operators are variable names
+                    $this->parser->getStream()->next();
+                    $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
+                    break;
+                }
+
             default:
                 if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) {
                     $node = $this->parseArrayExpression();
@@ -182,12 +187,10 @@ public function parseStringExpression()
         // 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();
+            if ($nextCanBeString && $token = $stream->nextIf(Twig_Token::STRING_TYPE)) {
                 $nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
                 $nextCanBeString = false;
-            } elseif ($stream->test(Twig_Token::INTERPOLATION_START_TYPE)) {
-                $stream->next();
+            } elseif ($stream->nextIf(Twig_Token::INTERPOLATION_START_TYPE)) {
                 $nodes[] = $this->parseExpression();
                 $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
                 $nextCanBeString = true;
@@ -253,8 +256,7 @@ public function parseHashExpression()
             //  * 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();
+            if (($token = $stream->nextIf(Twig_Token::STRING_TYPE)) || ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) || $token = $stream->nextIf(Twig_Token::NUMBER_TYPE)) {
                 $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
             } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
                 $key = $this->parseExpression();
@@ -316,7 +318,7 @@ public function getFunctionNode($name, $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);
+                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_Template::ANY_CALL, $line);
             default:
                 if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
                     $arguments = new Twig_Node_Expression_Array(array(), $line);
@@ -343,7 +345,7 @@ public function parseSubscriptExpression($node)
         $token = $stream->next();
         $lineno = $token->getLine();
         $arguments = new Twig_Node_Expression_Array(array(), $lineno);
-        $type = Twig_TemplateInterface::ANY_CALL;
+        $type = Twig_Template::ANY_CALL;
         if ($token->getValue() == '.') {
             $token = $stream->next();
             if (
@@ -365,7 +367,7 @@ public function parseSubscriptExpression($node)
                 throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
             }
 
-            if ($node instanceof Twig_Node_Expression_Name && null !== $alias = $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
+            if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
                 if (!$arg instanceof Twig_Node_Expression_Constant) {
                     throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
                 }
@@ -376,7 +378,7 @@ public function parseSubscriptExpression($node)
                 return $node;
             }
         } else {
-            $type = Twig_TemplateInterface::ARRAY_CALL;
+            $type = Twig_Template::ARRAY_CALL;
 
             // slice?
             $slice = false;
@@ -387,9 +389,8 @@ public function parseSubscriptExpression($node)
                 $arg = $this->parseExpression();
             }
 
-            if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
+            if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
                 $slice = true;
-                $stream->next();
             }
 
             if ($slice) {
@@ -472,8 +473,7 @@ public function parseArguments($namedArguments = false, $definition = false)
             }
 
             $name = null;
-            if ($namedArguments && $stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
-                $token = $stream->next();
+            if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) {
                 if (!$value instanceof Twig_Node_Expression_Name) {
                     throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given', get_class($value)), $token->getLine(), $this->parser->getFilename());
                 }
@@ -519,10 +519,9 @@ public function parseAssignmentExpression()
             }
             $targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine());
 
-            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
+            if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
                 break;
             }
-            $this->parser->getStream()->next();
         }
 
         return new Twig_Node($targets);
@@ -533,10 +532,9 @@ public function parseMultitargetExpression()
         $targets = array();
         while (true) {
             $targets[] = $this->parseExpression();
-            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
+            if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
                 break;
             }
-            $this->parser->getStream()->next();
         }
 
         return new Twig_Node($targets);
diff --git a/core/vendor/twig/twig/lib/Twig/Extension.php b/core/vendor/twig/twig/lib/Twig/Extension.php
index 931fc0338ca5..5c8ad5c96cda 100644
--- a/core/vendor/twig/twig/lib/Twig/Extension.php
+++ b/core/vendor/twig/twig/lib/Twig/Extension.php
@@ -34,7 +34,7 @@ public function getTokenParsers()
     /**
      * Returns the node visitor instances to add to the existing list.
      *
-     * @return array An array of Twig_NodeVisitorInterface instances
+     * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
      */
     public function getNodeVisitors()
     {
diff --git a/core/vendor/twig/twig/lib/Twig/Extension/Core.php b/core/vendor/twig/twig/lib/Twig/Extension/Core.php
index 26e7017d1243..4e80c67a2259 100644
--- a/core/vendor/twig/twig/lib/Twig/Extension/Core.php
+++ b/core/vendor/twig/twig/lib/Twig/Extension/Core.php
@@ -1,7 +1,8 @@
 <?php
 
 if (!defined('ENT_SUBSTITUTE')) {
-    define('ENT_SUBSTITUTE', 8);
+    // use 0 as hhvm does not support several flags yet
+    define('ENT_SUBSTITUTE', 0);
 }
 
 /*
@@ -17,6 +18,28 @@ class Twig_Extension_Core extends Twig_Extension
     protected $dateFormats = array('F j, Y H:i', '%d days');
     protected $numberFormat = array(0, '.', ',');
     protected $timezone = null;
+    protected $escapers = array();
+
+    /**
+     * Defines a new escaper to be used via the escape filter.
+     *
+     * @param string   $strategy The strategy name that should be used as a strategy in the escape call
+     * @param callable $callable A valid PHP callable
+     */
+    public function setEscaper($strategy, $callable)
+    {
+        $this->escapers[$strategy] = $callable;
+    }
+
+    /**
+     * Gets all defined escapers.
+     *
+     * @return array An array of escapers
+     */
+    public function getEscapers()
+    {
+        return $this->escapers;
+    }
 
     /**
      * Sets the default format to be used by the date filter.
@@ -94,7 +117,7 @@ public function getNumberFormat()
     /**
      * Returns the token parser instance to add to the existing list.
      *
-     * @return array An array of Twig_TokenParser instances
+     * @return Twig_TokenParser[] An array of Twig_TokenParser instances
      */
     public function getTokenParsers()
     {
@@ -132,6 +155,7 @@ public function getFilters()
             new Twig_SimpleFilter('replace', 'strtr'),
             new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)),
             new Twig_SimpleFilter('abs', 'abs'),
+            new Twig_SimpleFilter('round', 'twig_round'),
 
             // encoding
             new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'),
@@ -186,12 +210,15 @@ public function getFilters()
     public function getFunctions()
     {
         return array(
+            new Twig_SimpleFunction('max', 'max'),
+            new Twig_SimpleFunction('min', 'min'),
             new Twig_SimpleFunction('range', 'range'),
             new Twig_SimpleFunction('constant', 'twig_constant'),
             new Twig_SimpleFunction('cycle', 'twig_cycle'),
             new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)),
             new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)),
-            new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true)),
+            new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true, 'is_safe' => array('all'))),
+            new Twig_SimpleFunction('source', 'twig_source', array('needs_environment' => true, 'is_safe' => array('all'))),
         );
     }
 
@@ -207,9 +234,11 @@ public function getTests()
             new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')),
             new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')),
             new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
+            new Twig_SimpleTest('same as', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
             new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
             new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
             new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
+            new Twig_SimpleTest('divisible by', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
             new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')),
             new Twig_SimpleTest('empty', 'twig_test_empty'),
             new Twig_SimpleTest('iterable', 'twig_test_iterable'),
@@ -230,50 +259,52 @@ public function getOperators()
                 '+'   => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'),
             ),
             array(
-                '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),
-                '>'      => 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),
+                '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),
+                '>'           => 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),
+                'matches'     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                'starts with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
+                'ends with'   => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', '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)
+    public function parseNotTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
     {
         return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine());
     }
 
-    public function parseTestExpression(Twig_Parser $parser, $node)
+    public function parseTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
     {
         $stream = $parser->getStream();
         $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
+        $class = $this->getTestNodeClass($parser, $name, $node->getLine());
         $arguments = null;
         if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
             $arguments = $parser->getExpressionParser()->parseArguments(true);
         }
 
-        $class = $this->getTestNodeClass($parser, $name, $node->getLine());
-
         return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
     }
 
@@ -281,7 +312,21 @@ protected function getTestNodeClass(Twig_Parser $parser, $name, $line)
     {
         $env = $parser->getEnvironment();
         $testMap = $env->getTests();
-        if (!isset($testMap[$name])) {
+        $testName = null;
+        if (isset($testMap[$name])) {
+            $testName = $name;
+        } elseif ($parser->getStream()->test(Twig_Token::NAME_TYPE)) {
+            // try 2-words tests
+            $name = $name.' '.$parser->getCurrentToken()->getValue();
+
+            if (isset($testMap[$name])) {
+                $parser->getStream()->next();
+
+                $testName = $name;
+            }
+        }
+
+        if (null === $testName) {
             $message = sprintf('The test "%s" does not exist', $name);
             if ($alternatives = $env->computeAlternatives($name, array_keys($env->getTests()))) {
                 $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
@@ -348,7 +393,7 @@ function twig_random(Twig_Environment $env, $values = null)
         return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values);
     }
 
-    if ($values instanceof Traversable) {
+    if (is_object($values) && $values instanceof Traversable) {
         $values = iterator_to_array($values);
     } elseif (is_string($values)) {
         if ('' === $values) {
@@ -459,13 +504,15 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
         $defaultTimezone = $timezone;
     }
 
-    if ($date instanceof DateTime) {
-        $date = clone $date;
+    if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
+        $returningDate = new DateTime($date->format('c'));
         if (false !== $timezone) {
-            $date->setTimezone($defaultTimezone);
+            $returningDate->setTimezone($defaultTimezone);
+        } else {
+            $returningDate->setTimezone($date->getTimezone());
         }
 
-        return $date;
+        return $returningDate;
     }
 
     $asString = (string) $date;
@@ -481,6 +528,28 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
     return $date;
 }
 
+/**
+ * Rounds a number.
+ *
+ * @param integer|float $value     The value to round
+ * @param integer|float $precision The rounding precision
+ * @param string        $method    The method to use for rounding
+ *
+ * @return integer|float The rounded number
+ */
+function twig_round($value, $precision = 0, $method = 'common')
+{
+    if ('common' == $method) {
+        return round($value, $precision);
+    }
+
+    if ('ceil' != $method && 'floor' != $method) {
+        throw new Twig_Error_Runtime('The round filter only supports the "common", "ceil", and "floor" methods.');
+    }
+
+    return $method($value * pow(10, $precision)) / pow(10, $precision);
+}
+
 /**
  * Number format filter.
  *
@@ -518,7 +587,7 @@ function twig_number_format_filter(Twig_Environment $env, $number, $decimal = nu
  * URL encodes a string as a path segment or an array as a query string.
  *
  * @param string|array $url A URL or an array of query parameters
- * @param bool         $raw true to use rawurlencode() instead of urlencode
+ * @param Boolean      $raw true to use rawurlencode() instead of urlencode
  *
  * @return string The URL encoded value
  */
@@ -620,7 +689,7 @@ function twig_array_merge($arr1, $arr2)
  */
 function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
 {
-    if ($item instanceof Traversable) {
+    if (is_object($item) && $item instanceof Traversable) {
         $item = iterator_to_array($item, false);
     }
 
@@ -649,7 +718,7 @@ function twig_first(Twig_Environment $env, $item)
 {
     $elements = twig_slice($env, $item, 0, 1, false);
 
-    return is_string($elements) ? $elements[0] : current($elements);
+    return is_string($elements) ? $elements : current($elements);
 }
 
 /**
@@ -664,7 +733,7 @@ function twig_last(Twig_Environment $env, $item)
 {
     $elements = twig_slice($env, $item, -1, 1, false);
 
-    return is_string($elements) ? $elements[0] : current($elements);
+    return is_string($elements) ? $elements : current($elements);
 }
 
 /**
@@ -687,7 +756,7 @@ function twig_last(Twig_Environment $env, $item)
  */
 function twig_join_filter($value, $glue = '')
 {
-    if ($value instanceof Traversable) {
+    if (is_object($value) && $value instanceof Traversable) {
         $value = iterator_to_array($value, false);
     }
 
@@ -829,7 +898,7 @@ function twig_in_filter($value, $compare)
         }
 
         return false !== strpos($compare, (string) $value);
-    } elseif ($compare instanceof Traversable) {
+    } elseif (is_object($compare) && $compare instanceof Traversable) {
         return in_array($value, iterator_to_array($compare, false), is_object($value));
     }
 
@@ -847,21 +916,70 @@ function twig_in_filter($value, $compare)
  */
 function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
 {
-    if ($autoescape && is_object($string) && $string instanceof Twig_Markup) {
+    if ($autoescape && $string instanceof Twig_Markup) {
         return $string;
     }
 
-    if (!is_string($string) && !(is_object($string) && method_exists($string, '__toString'))) {
-        return $string;
+    if (!is_string($string)) {
+        if (is_object($string) && method_exists($string, '__toString')) {
+            $string = (string) $string;
+        } else {
+            return $string;
+        }
     }
 
     if (null === $charset) {
         $charset = $env->getCharset();
     }
 
-    $string = (string) $string;
-
     switch ($strategy) {
+        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;
+
+            if (null === $htmlspecialcharsCharsets) {
+                if ('hiphop' === substr(PHP_VERSION, -6)) {
+                    $htmlspecialcharsCharsets = array('utf-8' => true, 'UTF-8' => true);
+                } else {
+                    $htmlspecialcharsCharsets = array(
+                        'ISO-8859-1' => true, 'ISO8859-1' => true,
+                        'ISO-8859-15' => true, 'ISO8859-15' => true,
+                        'utf-8' => 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[$charset])) {
+                return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
+            }
+
+            if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
+                // cache the lowercase variant for future iterations
+                $htmlspecialcharsCharsets[$charset] = true;
+
+                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');
+
         case 'js':
             // escape all non-alphanumeric characters
             // into their \xHH or \uHHHH representations
@@ -915,47 +1033,29 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
 
             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');
-
         case 'url':
-            if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+            // hackish test to avoid version_compare that is much slower, this works unless PHP releases a 5.10.*
+            // at that point however PHP 5.2.* support can be removed
+            if (PHP_VERSION < '5.3.0') {
                 return str_replace('%7E', '~', rawurlencode($string));
             }
 
             return rawurlencode($string);
 
         default:
-            throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: html, js, url, css, and html_attr).', $strategy));
+            static $escapers;
+
+            if (null === $escapers) {
+                $escapers = $env->getExtension('core')->getEscapers();
+            }
+
+            if (isset($escapers[$strategy])) {
+                return call_user_func($escapers[$strategy], $env, $string, $charset);
+            }
+
+            $validStrategies = implode(', ', array_merge(array('html', 'js', 'url', 'css', 'html_attr'), array_keys($escapers)));
+
+            throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies));
     }
 }
 
@@ -1262,11 +1362,11 @@ function twig_test_iterable($value)
 /**
  * Renders a template.
  *
- * @param string  template       The template to render
- * @param array   variables      The variables to pass to the template
- * @param Boolean with_context   Whether to pass the current context variables or not
- * @param Boolean ignore_missing Whether to ignore missing templates or not
- * @param Boolean sandboxed      Whether to sandbox the template or not
+ * @param string|array $template       The template to render or an array of templates to try consecutively
+ * @param array        $variables      The variables to pass to the template
+ * @param Boolean      $with_context   Whether to pass the current context variables or not
+ * @param Boolean      $ignore_missing Whether to ignore missing templates or not
+ * @param Boolean      $sandboxed      Whether to sandbox the template or not
  *
  * @return string The rendered template
  */
@@ -1284,7 +1384,7 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
     }
 
     try {
-        return $env->resolveTemplate($template)->display($variables);
+        return $env->resolveTemplate($template)->render($variables);
     } catch (Twig_Error_Loader $e) {
         if (!$ignoreMissing) {
             throw $e;
@@ -1296,6 +1396,18 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
     }
 }
 
+/**
+ * Returns a template content without rendering it.
+ *
+ * @param string $name The template name
+ *
+ * @return string The template source
+ */
+function twig_source(Twig_Environment $env, $name)
+{
+    return $env->getLoader()->getSource($name);
+}
+
 /**
  * Provides the ability to get constants from instances as well as class/global constants.
  *
@@ -1318,13 +1430,13 @@ function twig_constant($constant, $object = null)
  *
  * @param array   $items An array of items
  * @param integer $size  The size of the batch
- * @param string  $fill  A string to fill missing items
+ * @param mixed   $fill  A value used to fill missing items
  *
  * @return array
  */
 function twig_array_batch($items, $size, $fill = null)
 {
-    if ($items instanceof Traversable) {
+    if (is_object($items) && $items instanceof Traversable) {
         $items = iterator_to_array($items, false);
     }
 
@@ -1334,10 +1446,12 @@ function twig_array_batch($items, $size, $fill = null)
 
     if (null !== $fill) {
         $last = count($result) - 1;
-        $result[$last] = array_merge(
-            $result[$last],
-            array_fill(0, $size - count($result[$last]), $fill)
-        );
+        if ($fillCount = $size - count($result[$last])) {
+            $result[$last] = array_merge(
+                $result[$last],
+                array_fill(0, $fillCount, $fill)
+            );
+        }
     }
 
     return $result;
diff --git a/core/vendor/twig/twig/lib/Twig/Extension/Debug.php b/core/vendor/twig/twig/lib/Twig/Extension/Debug.php
index 97007fb1dbef..e3a85bfe8e21 100644
--- a/core/vendor/twig/twig/lib/Twig/Extension/Debug.php
+++ b/core/vendor/twig/twig/lib/Twig/Extension/Debug.php
@@ -24,6 +24,7 @@ public function getFunctions()
             // 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'))
+            || 'cli' === php_sapi_name()
         ;
 
         return array(
diff --git a/core/vendor/twig/twig/lib/Twig/Extension/Escaper.php b/core/vendor/twig/twig/lib/Twig/Extension/Escaper.php
index c9a7f68e783e..d3e5ad0ec572 100644
--- a/core/vendor/twig/twig/lib/Twig/Extension/Escaper.php
+++ b/core/vendor/twig/twig/lib/Twig/Extension/Escaper.php
@@ -30,7 +30,7 @@ public function getTokenParsers()
     /**
      * Returns the node visitor instances to add to the existing list.
      *
-     * @return array An array of Twig_NodeVisitorInterface instances
+     * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
      */
     public function getNodeVisitors()
     {
diff --git a/core/vendor/twig/twig/lib/Twig/Extension/Sandbox.php b/core/vendor/twig/twig/lib/Twig/Extension/Sandbox.php
index bf76c11a9851..c59609f61df6 100644
--- a/core/vendor/twig/twig/lib/Twig/Extension/Sandbox.php
+++ b/core/vendor/twig/twig/lib/Twig/Extension/Sandbox.php
@@ -33,7 +33,7 @@ public function getTokenParsers()
     /**
      * Returns the node visitor instances to add to the existing list.
      *
-     * @return array An array of Twig_NodeVisitorInterface instances
+     * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
      */
     public function getNodeVisitors()
     {
diff --git a/core/vendor/twig/twig/lib/Twig/Extension/StringLoader.php b/core/vendor/twig/twig/lib/Twig/Extension/StringLoader.php
index d5b881bf2bd7..5e1a60d0a364 100644
--- a/core/vendor/twig/twig/lib/Twig/Extension/StringLoader.php
+++ b/core/vendor/twig/twig/lib/Twig/Extension/StringLoader.php
@@ -33,7 +33,7 @@ public function getName()
  * Loads a template from a string.
  *
  * <pre>
- * {% include template_from_string("Hello {{ name }}") }}
+ * {{ include(template_from_string("Hello {{ name }}")) }}
  * </pre>
  *
  * @param Twig_Environment $env      A Twig_Environment instance
@@ -43,16 +43,16 @@ public function getName()
  */
 function twig_template_from_string(Twig_Environment $env, $template)
 {
-    static $loader;
+    $name = sprintf('__string_template__%s', hash('sha256', uniqid(mt_rand(), true), false));
 
-    if (null === $loader) {
-        $loader = new Twig_Loader_String();
-    }
+    $loader = new Twig_Loader_Chain(array(
+        new Twig_Loader_Array(array($name => $template)),
+        $current = $env->getLoader(),
+    ));
 
-    $current = $env->getLoader();
     $env->setLoader($loader);
     try {
-        $template = $env->loadTemplate($template);
+        $template = $env->loadTemplate($name);
     } catch (Exception $e) {
         $env->setLoader($current);
 
diff --git a/core/vendor/twig/twig/lib/Twig/ExtensionInterface.php b/core/vendor/twig/twig/lib/Twig/ExtensionInterface.php
index f189e9d9d09e..49541b02e3e1 100644
--- a/core/vendor/twig/twig/lib/Twig/ExtensionInterface.php
+++ b/core/vendor/twig/twig/lib/Twig/ExtensionInterface.php
@@ -35,7 +35,7 @@ public function getTokenParsers();
     /**
      * Returns the node visitor instances to add to the existing list.
      *
-     * @return array An array of Twig_NodeVisitorInterface instances
+     * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
      */
     public function getNodeVisitors();
 
diff --git a/core/vendor/twig/twig/lib/Twig/Filter.php b/core/vendor/twig/twig/lib/Twig/Filter.php
index 189178851bb4..5cfbb6625a60 100644
--- a/core/vendor/twig/twig/lib/Twig/Filter.php
+++ b/core/vendor/twig/twig/lib/Twig/Filter.php
@@ -62,8 +62,6 @@ public function getSafe(Twig_Node $filterArgs)
         if (isset($this->options['is_safe_callback'])) {
             return call_user_func($this->options['is_safe_callback'], $filterArgs);
         }
-
-        return null;
     }
 
     public function getPreservesSafety()
diff --git a/core/vendor/twig/twig/lib/Twig/Lexer.php b/core/vendor/twig/twig/lib/Twig/Lexer.php
index 000b038e60e8..8955fca6da79 100644
--- a/core/vendor/twig/twig/lib/Twig/Lexer.php
+++ b/core/vendor/twig/twig/lib/Twig/Lexer.php
@@ -73,12 +73,7 @@ public function __construct(Twig_Environment $env, array $options = array())
     }
 
     /**
-     * Tokenizes a 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
+     * {@inheritdoc}
      */
     public function tokenize($code, $filename = null)
     {
@@ -233,7 +228,7 @@ protected function lexExpression()
 
         // operators
         if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) {
-            $this->pushToken(Twig_Token::OPERATOR_TYPE, $match[0]);
+            $this->pushToken(Twig_Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0]));
             $this->moveCursor($match[0]);
         }
         // names
@@ -326,7 +321,6 @@ protected function lexString()
             $this->moveCursor($match[0]);
 
         } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
-
             list($expect, $lineno) = array_pop($this->brackets);
             if ($this->code[$this->cursor] != '"') {
                 throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
@@ -382,10 +376,15 @@ protected function getOperatorRegex()
             // an operator that ends with a character must be followed by
             // a whitespace or a parenthesis
             if (ctype_alpha($operator[$length - 1])) {
-                $regex[] = preg_quote($operator, '/').'(?=[\s()])';
+                $r = preg_quote($operator, '/').'(?=[\s()])';
             } else {
-                $regex[] = preg_quote($operator, '/');
+                $r = preg_quote($operator, '/');
             }
+
+            // an operator with a space can be any amount of whitespaces
+            $r = preg_replace('/\s+/', '\s+', $r);
+
+            $regex[] = $r;
         }
 
         return '/'.implode('|', $regex).'/A';
diff --git a/core/vendor/twig/twig/lib/Twig/LexerInterface.php b/core/vendor/twig/twig/lib/Twig/LexerInterface.php
index 4b83f81b0f9b..dd51caeee7ba 100644
--- a/core/vendor/twig/twig/lib/Twig/LexerInterface.php
+++ b/core/vendor/twig/twig/lib/Twig/LexerInterface.php
@@ -24,6 +24,8 @@ interface Twig_LexerInterface
      * @param string $filename A unique identifier for the source code
      *
      * @return Twig_TokenStream A token stream instance
+     *
+     * @throws Twig_Error_Syntax When the code is syntactically wrong
      */
     public function tokenize($code, $filename = null);
 }
diff --git a/core/vendor/twig/twig/lib/Twig/Loader/Array.php b/core/vendor/twig/twig/lib/Twig/Loader/Array.php
index 89087aeabf73..ac561048578f 100644
--- a/core/vendor/twig/twig/lib/Twig/Loader/Array.php
+++ b/core/vendor/twig/twig/lib/Twig/Loader/Array.php
@@ -21,7 +21,7 @@
  */
 class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
 {
-    protected $templates;
+    protected $templates = array();
 
     /**
      * Constructor.
@@ -32,10 +32,7 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
      */
     public function __construct(array $templates)
     {
-        $this->templates = array();
-        foreach ($templates as $name => $template) {
-            $this->templates[$name] = $template;
-        }
+        $this->templates = $templates;
     }
 
     /**
diff --git a/core/vendor/twig/twig/lib/Twig/Loader/Chain.php b/core/vendor/twig/twig/lib/Twig/Loader/Chain.php
index cd64b051da72..7919eda627bd 100644
--- a/core/vendor/twig/twig/lib/Twig/Loader/Chain.php
+++ b/core/vendor/twig/twig/lib/Twig/Loader/Chain.php
@@ -17,7 +17,7 @@
 class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
 {
     private $hasSourceCache = array();
-    protected $loaders;
+    protected $loaders = array();
 
     /**
      * Constructor.
@@ -26,7 +26,6 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
      */
     public function __construct(array $loaders = array())
     {
-        $this->loaders = array();
         foreach ($loaders as $loader) {
             $this->addLoader($loader);
         }
@@ -76,8 +75,12 @@ public function exists($name)
         }
 
         foreach ($this->loaders as $loader) {
-            if ($loader instanceof Twig_ExistsLoaderInterface && $loader->exists($name)) {
-                return $this->hasSourceCache[$name] = true;
+            if ($loader instanceof Twig_ExistsLoaderInterface) {
+                if ($loader->exists($name)) {
+                    return $this->hasSourceCache[$name] = true;
+                }
+
+                continue;
             }
 
             try {
diff --git a/core/vendor/twig/twig/lib/Twig/Loader/Filesystem.php b/core/vendor/twig/twig/lib/Twig/Loader/Filesystem.php
index 84a5e03aef59..23bac47d705b 100644
--- a/core/vendor/twig/twig/lib/Twig/Loader/Filesystem.php
+++ b/core/vendor/twig/twig/lib/Twig/Loader/Filesystem.php
@@ -16,17 +16,22 @@
  */
 class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
 {
-    protected $paths;
-    protected $cache;
+    /** Identifier of the main namespace. */
+    const MAIN_NAMESPACE = '__main__';
+
+    protected $paths = array();
+    protected $cache = array();
 
     /**
      * Constructor.
      *
      * @param string|array $paths A path or an array of paths where to look for templates
      */
-    public function __construct($paths)
+    public function __construct($paths = array())
     {
-        $this->setPaths($paths);
+        if ($paths) {
+            $this->setPaths($paths);
+        }
     }
 
     /**
@@ -36,7 +41,7 @@ public function __construct($paths)
      *
      * @return array The array of paths where to look for templates
      */
-    public function getPaths($namespace = '__main__')
+    public function getPaths($namespace = self::MAIN_NAMESPACE)
     {
         return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array();
     }
@@ -44,7 +49,7 @@ public function getPaths($namespace = '__main__')
     /**
      * Returns the path namespaces.
      *
-     * The "__main__" namespace is always defined.
+     * The main namespace is always defined.
      *
      * @return array The array of defined namespaces
      */
@@ -59,7 +64,7 @@ public function getNamespaces()
      * @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, $namespace = '__main__')
+    public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
     {
         if (!is_array($paths)) {
             $paths = array($paths);
@@ -79,7 +84,7 @@ public function setPaths($paths, $namespace = '__main__')
      *
      * @throws Twig_Error_Loader
      */
-    public function addPath($path, $namespace = '__main__')
+    public function addPath($path, $namespace = self::MAIN_NAMESPACE)
     {
         // invalidate the cache
         $this->cache = array();
@@ -99,7 +104,7 @@ public function addPath($path, $namespace = '__main__')
      *
      * @throws Twig_Error_Loader
      */
-    public function prependPath($path, $namespace = '__main__')
+    public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
     {
         // invalidate the cache
         $this->cache = array();
@@ -173,15 +178,15 @@ protected function findTemplate($name)
 
         $this->validateName($name);
 
-        $namespace = '__main__';
+        $namespace = self::MAIN_NAMESPACE;
+        $shortname = $name;
         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);
+            $shortname = substr($name, $pos + 1);
         }
 
         if (!isset($this->paths[$namespace])) {
@@ -189,8 +194,8 @@ protected function findTemplate($name)
         }
 
         foreach ($this->paths[$namespace] as $path) {
-            if (is_file($path.'/'.$name)) {
-                return $this->cache[$name] = $path.'/'.$name;
+            if (is_file($path.'/'.$shortname)) {
+                return $this->cache[$name] = $path.'/'.$shortname;
             }
         }
 
diff --git a/core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php b/core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php
new file mode 100644
index 000000000000..5de6c72d21e4
--- /dev/null
+++ b/core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2013 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary
+{
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->raw('(0 === substr_compare(')
+            ->subcompile($this->getNode('left'))
+            ->raw(', ')
+            ->subcompile($this->getNode('right'))
+            ->raw(', -strlen(')
+            ->subcompile($this->getNode('right'))
+            ->raw(')))')
+        ;
+    }
+
+    public function operator(Twig_Compiler $compiler)
+    {
+        return $compiler->raw('');
+    }
+}
diff --git a/core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php b/core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php
new file mode 100644
index 000000000000..93bb292051eb
--- /dev/null
+++ b/core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2013 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary
+{
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->raw('preg_match(')
+            ->subcompile($this->getNode('right'))
+            ->raw(', ')
+            ->subcompile($this->getNode('left'))
+            ->raw(')')
+        ;
+    }
+
+    public function operator(Twig_Compiler $compiler)
+    {
+        return $compiler->raw('');
+    }
+}
diff --git a/core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php b/core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php
new file mode 100644
index 000000000000..eb8c107cb1a2
--- /dev/null
+++ b/core/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2013 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary
+{
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler
+            ->raw('(0 === strpos(')
+            ->subcompile($this->getNode('left'))
+            ->raw(', ')
+            ->subcompile($this->getNode('right'))
+            ->raw('))')
+        ;
+    }
+
+    public function operator(Twig_Compiler $compiler)
+    {
+        return $compiler->raw('');
+    }
+}
diff --git a/core/vendor/twig/twig/lib/Twig/Node/Expression/Call.php b/core/vendor/twig/twig/lib/Twig/Node/Expression/Call.php
index a97b3b572c59..dba9b0e6272b 100644
--- a/core/vendor/twig/twig/lib/Twig/Node/Expression/Call.php
+++ b/core/vendor/twig/twig/lib/Twig/Node/Expression/Call.php
@@ -98,7 +98,10 @@ protected function getArguments($callable, $arguments)
             if (!is_int($name)) {
                 $named = true;
                 $name = $this->normalizeName($name);
+            } elseif ($named) {
+                throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
             }
+
             $parameters[$name] = $node;
         }
 
@@ -142,6 +145,10 @@ protected function getArguments($callable, $arguments)
             $name = $this->normalizeName($param->name);
 
             if (array_key_exists($name, $parameters)) {
+                if (array_key_exists($pos, $parameters)) {
+                    throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
+                }
+
                 $arguments[] = $parameters[$name];
                 unset($parameters[$name]);
             } elseif (array_key_exists($pos, $parameters)) {
@@ -157,8 +164,8 @@ protected function getArguments($callable, $arguments)
             }
         }
 
-        foreach (array_keys($parameters) as $name) {
-            throw new Twig_Error_Syntax(sprintf('Unknown argument "%s" for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
+        if (!empty($parameters)) {
+            throw new Twig_Error_Syntax(sprintf('Unknown argument%s "%s" for %s "%s".', count($parameters) > 1 ? 's' : '' , implode('", "', array_keys($parameters)), $this->getAttribute('type'), $this->getAttribute('name')));
         }
 
         return $arguments;
diff --git a/core/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php b/core/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php
index 81a9b137abd1..55d9fcc32043 100644
--- a/core/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php
+++ b/core/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php
@@ -32,10 +32,10 @@ public function compile(Twig_Compiler $compiler)
 
         $compiler->raw(', ')->subcompile($this->getNode('attribute'));
 
-        if (count($this->getNode('arguments')) || Twig_TemplateInterface::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
+        if (count($this->getNode('arguments')) || Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
             $compiler->raw(', ')->subcompile($this->getNode('arguments'));
 
-            if (Twig_TemplateInterface::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
+            if (Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
                 $compiler->raw(', ')->repr($this->getAttribute('type'));
             }
 
diff --git a/core/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php b/core/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php
index 45b1e5da5aaa..de55f5f55db1 100644
--- a/core/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php
+++ b/core/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php
@@ -28,6 +28,17 @@ public function compile(Twig_Compiler $compiler)
             ->raw('(')
             ->subcompile($this->getNode('node'))
             ->raw(' === constant(')
+        ;
+
+        if ($this->getNode('arguments')->hasNode(1)) {
+            $compiler
+                ->raw('get_class(')
+                ->subcompile($this->getNode('arguments')->getNode(1))
+                ->raw(')."::".')
+            ;
+        }
+
+        $compiler
             ->subcompile($this->getNode('arguments')->getNode(0))
             ->raw('))')
         ;
diff --git a/core/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php b/core/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php
index 85b07f59a5cf..247b2e23a539 100644
--- a/core/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php
+++ b/core/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php
@@ -34,7 +34,7 @@ public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface
 
             $this->changeIgnoreStrictCheck($node);
         } else {
-            throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine(), $compiler->getFilename());
+            throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine());
         }
     }
 
diff --git a/core/vendor/twig/twig/lib/Twig/Node/For.php b/core/vendor/twig/twig/lib/Twig/Node/For.php
index 20e543c251a5..d1ff371da1bd 100644
--- a/core/vendor/twig/twig/lib/Twig/Node/For.php
+++ b/core/vendor/twig/twig/lib/Twig/Node/For.php
@@ -107,6 +107,6 @@ public function compile(Twig_Compiler $compiler)
         $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
 
         // keep the values set in the inner context for variables defined in the outer context
-        $compiler->write("\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));\n");
+        $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n");
     }
 }
diff --git a/core/vendor/twig/twig/lib/Twig/Node/If.php b/core/vendor/twig/twig/lib/Twig/Node/If.php
index 4296a8d678fb..b42d10755504 100644
--- a/core/vendor/twig/twig/lib/Twig/Node/If.php
+++ b/core/vendor/twig/twig/lib/Twig/Node/If.php
@@ -30,7 +30,7 @@ public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else
     public function compile(Twig_Compiler $compiler)
     {
         $compiler->addDebugInfo($this);
-        for ($i = 0; $i < count($this->getNode('tests')); $i += 2) {
+        for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) {
             if ($i > 0) {
                 $compiler
                     ->outdent()
diff --git a/core/vendor/twig/twig/lib/Twig/NodeTraverser.php b/core/vendor/twig/twig/lib/Twig/NodeTraverser.php
index 28cba1ad57be..aacaf2938cd9 100644
--- a/core/vendor/twig/twig/lib/Twig/NodeTraverser.php
+++ b/core/vendor/twig/twig/lib/Twig/NodeTraverser.php
@@ -12,7 +12,7 @@
 /**
  * Twig_NodeTraverser is a node traverser.
  *
- * It visits all nodes and their children and call the given visitor for each.
+ * It visits all nodes and their children and calls the given visitor for each.
  *
  * @author Fabien Potencier <fabien@symfony.com>
  */
@@ -24,8 +24,8 @@ class Twig_NodeTraverser
     /**
      * Constructor.
      *
-     * @param Twig_Environment $env      A Twig_Environment instance
-     * @param array            $visitors An array of Twig_NodeVisitorInterface instances
+     * @param Twig_Environment            $env      A Twig_Environment instance
+     * @param Twig_NodeVisitorInterface[] $visitors An array of Twig_NodeVisitorInterface instances
      */
     public function __construct(Twig_Environment $env, array $visitors = array())
     {
diff --git a/core/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php b/core/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
index a254def75be6..5bf8eb0c596c 100644
--- a/core/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
+++ b/core/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
@@ -39,7 +39,7 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
      */
     public function __construct($optimizers = -1)
     {
-        if (!is_int($optimizers) || $optimizers > 2) {
+        if (!is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) {
             throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers));
         }
 
@@ -108,7 +108,7 @@ public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
         return $node;
     }
 
-    protected function optimizeVariables($node, $env)
+    protected function optimizeVariables(Twig_NodeInterface $node, Twig_Environment $env)
     {
         if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) {
             $this->prependedNodes[0][] = $node->getAttribute('name');
@@ -129,7 +129,7 @@ protected function optimizeVariables($node, $env)
      * @param Twig_NodeInterface $node A Node
      * @param Twig_Environment   $env  The current Twig environment
      */
-    protected function optimizePrintNode($node, $env)
+    protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env)
     {
         if (!$node instanceof Twig_Node_Print) {
             return $node;
@@ -153,7 +153,7 @@ protected function optimizePrintNode($node, $env)
      * @param Twig_NodeInterface $node A Node
      * @param Twig_Environment   $env  The current Twig environment
      */
-    protected function optimizeRawFilter($node, $env)
+    protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env)
     {
         if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) {
             return $node->getNode('node');
@@ -168,7 +168,7 @@ protected function optimizeRawFilter($node, $env)
      * @param Twig_NodeInterface $node A Node
      * @param Twig_Environment   $env  The current Twig environment
      */
-    protected function enterOptimizeFor($node, $env)
+    protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
     {
         if ($node instanceof Twig_Node_For) {
             // disable the loop variable by default
@@ -217,7 +217,7 @@ protected function enterOptimizeFor($node, $env)
      * @param Twig_NodeInterface $node A Node
      * @param Twig_Environment   $env  The current Twig environment
      */
-    protected function leaveOptimizeFor($node, $env)
+    protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
     {
         if ($node instanceof Twig_Node_For) {
             array_shift($this->loops);
diff --git a/core/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php b/core/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php
index 7dc65c0e6888..a5d06de2ca03 100644
--- a/core/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php
+++ b/core/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php
@@ -13,15 +13,21 @@ public function setSafeVars($safeVars)
     public function getSafe(Twig_NodeInterface $node)
     {
         $hash = spl_object_hash($node);
-        if (isset($this->data[$hash])) {
-            foreach ($this->data[$hash] as $bucket) {
-                if ($bucket['key'] === $node) {
-                    return $bucket['value'];
-                }
-            }
+        if (!isset($this->data[$hash])) {
+            return;
         }
 
-        return null;
+        foreach ($this->data[$hash] as $bucket) {
+            if ($bucket['key'] !== $node) {
+                continue;
+            }
+
+            if (in_array('html_attr', $bucket['value'])) {
+                $bucket['value'][] = 'html';
+            }
+
+            return $bucket['value'];
+        }
     }
 
     protected function setSafe(Twig_NodeInterface $node, array $safe)
diff --git a/core/vendor/twig/twig/lib/Twig/Parser.php b/core/vendor/twig/twig/lib/Twig/Parser.php
index 958e46b3dfa5..549ce2bdf404 100644
--- a/core/vendor/twig/twig/lib/Twig/Parser.php
+++ b/core/vendor/twig/twig/lib/Twig/Parser.php
@@ -49,7 +49,7 @@ public function getEnvironment()
 
     public function getVarName()
     {
-        return sprintf('__internal_%s', hash('sha1', uniqid(mt_rand(), true), false));
+        return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
     }
 
     public function getFilename()
@@ -58,11 +58,7 @@ public function getFilename()
     }
 
     /**
-     * Converts a token stream to a node tree.
-     *
-     * @param Twig_TokenStream $stream A token stream instance
-     *
-     * @return Twig_Node_Module A node tree
+     * {@inheritdoc}
      */
     public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false)
     {
@@ -246,7 +242,7 @@ public function getBlock($name)
         return $this->blocks[$name];
     }
 
-    public function setBlock($name, $value)
+    public function setBlock($name, Twig_Node_Block $value)
     {
         $this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->getLine());
     }
@@ -384,7 +380,7 @@ protected function filterBodyNodes(Twig_NodeInterface $node)
         }
 
         foreach ($node as $k => $n) {
-            if (null !== $n && null === $n = $this->filterBodyNodes($n)) {
+            if (null !== $n && null === $this->filterBodyNodes($n)) {
                 $node->removeNode($k);
             }
         }
diff --git a/core/vendor/twig/twig/lib/Twig/ParserInterface.php b/core/vendor/twig/twig/lib/Twig/ParserInterface.php
index f0d790097ecd..bfe60a36131e 100644
--- a/core/vendor/twig/twig/lib/Twig/ParserInterface.php
+++ b/core/vendor/twig/twig/lib/Twig/ParserInterface.php
@@ -23,6 +23,8 @@ interface Twig_ParserInterface
      * @param Twig_TokenStream $stream A token stream instance
      *
      * @return Twig_Node_Module A node tree
+     *
+     * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
      */
     public function parse(Twig_TokenStream $stream);
 }
diff --git a/core/vendor/twig/twig/lib/Twig/SimpleFilter.php b/core/vendor/twig/twig/lib/Twig/SimpleFilter.php
index a6bf60f80c55..d35c563346d9 100644
--- a/core/vendor/twig/twig/lib/Twig/SimpleFilter.php
+++ b/core/vendor/twig/twig/lib/Twig/SimpleFilter.php
@@ -80,8 +80,6 @@ public function getSafe(Twig_Node $filterArgs)
         if (null !== $this->options['is_safe_callback']) {
             return call_user_func($this->options['is_safe_callback'], $filterArgs);
         }
-
-        return null;
     }
 
     public function getPreservesSafety()
diff --git a/core/vendor/twig/twig/lib/Twig/Template.php b/core/vendor/twig/twig/lib/Twig/Template.php
index abc3400ee69b..4ae5968a57c8 100644
--- a/core/vendor/twig/twig/lib/Twig/Template.php
+++ b/core/vendor/twig/twig/lib/Twig/Template.php
@@ -127,12 +127,24 @@ public function displayBlock($name, array $context, array $blocks = array())
     {
         $name = (string) $name;
 
+        $template = null;
         if (isset($blocks[$name])) {
-            $b = $blocks;
-            unset($b[$name]);
-            call_user_func($blocks[$name], $context, $b);
+            $template = $blocks[$name][0];
+            $block = $blocks[$name][1];
+            unset($blocks[$name]);
         } elseif (isset($this->blocks[$name])) {
-            call_user_func($this->blocks[$name], $context, $blocks);
+            $template = $this->blocks[$name][0];
+            $block = $this->blocks[$name][1];
+        }
+
+        if (null !== $template) {
+            try {
+                $template->$block($context, $blocks);
+            } catch (Twig_Error $e) {
+                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, $template->getTemplateName(), $e);
+            }
         } elseif (false !== $parent = $this->getParent($context)) {
             $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks));
         }
@@ -276,7 +288,7 @@ protected function displayWithErrorHandling(array $context, array $blocks = arra
 
             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);
+            throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getTemplateName(), $e);
         }
     }
 
@@ -326,7 +338,7 @@ final protected function getContext($context, $item, $ignoreStrictCheck = false)
      * @param mixed   $object            The object or array from where to get the item
      * @param mixed   $item              The item to get from the array or object
      * @param array   $arguments         An array of arguments to pass if the item is an object method
-     * @param string  $type              The type of attribute (@see Twig_TemplateInterface)
+     * @param string  $type              The type of attribute (@see Twig_Template constants)
      * @param Boolean $isDefinedTest     Whether this is only a defined check
      * @param Boolean $ignoreStrictCheck Whether to ignore the strict attribute check or not
      *
@@ -334,23 +346,23 @@ final protected function getContext($context, $item, $ignoreStrictCheck = false)
      *
      * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
      */
-    protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_TemplateInterface::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
+    protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
     {
-        $item = ctype_digit((string) $item) ? (int) $item : (string) $item;
-
         // array
-        if (Twig_TemplateInterface::METHOD_CALL !== $type) {
-            if ((is_array($object) && array_key_exists($item, $object))
-                || ($object instanceof ArrayAccess && isset($object[$item]))
+        if (Twig_Template::METHOD_CALL !== $type) {
+            $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
+
+            if ((is_array($object) && array_key_exists($arrayItem, $object))
+                || ($object instanceof ArrayAccess && isset($object[$arrayItem]))
             ) {
                 if ($isDefinedTest) {
                     return true;
                 }
 
-                return $object[$item];
+                return $object[$arrayItem];
             }
 
-            if (Twig_TemplateInterface::ARRAY_CALL === $type) {
+            if (Twig_Template::ARRAY_CALL === $type || !is_object($object)) {
                 if ($isDefinedTest) {
                     return false;
                 }
@@ -360,11 +372,13 @@ protected function getAttribute($object, $item, array $arguments = array(), $typ
                 }
 
                 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)), -1, $this->getTemplateName());
+                    throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $arrayItem, 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))), -1, $this->getTemplateName());
+                    throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))), -1, $this->getTemplateName());
+                } elseif (Twig_Template::ARRAY_CALL === $type) {
+                    throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
                 } else {
-                    throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a "%s" variable', $item, gettype($object)), -1, $this->getTemplateName());
+                    throw new Twig_Error_Runtime(sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
                 }
             }
         }
@@ -378,14 +392,14 @@ protected function getAttribute($object, $item, array $arguments = array(), $typ
                 return null;
             }
 
-            throw new Twig_Error_Runtime(sprintf('Item "%s" for "%s" does not exist', $item, is_array($object) ? 'Array' : $object), -1, $this->getTemplateName());
+            throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
         }
 
         $class = get_class($object);
 
         // object property
-        if (Twig_TemplateInterface::METHOD_CALL !== $type) {
-            if (isset($object->$item) || array_key_exists($item, $object)) {
+        if (Twig_Template::METHOD_CALL !== $type) {
+            if (isset($object->$item) || array_key_exists((string) $item, $object)) {
                 if ($isDefinedTest) {
                     return true;
                 }
@@ -403,15 +417,17 @@ protected function getAttribute($object, $item, array $arguments = array(), $typ
             self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
         }
 
+        $call = false;
         $lcItem = strtolower($item);
         if (isset(self::$cache[$class]['methods'][$lcItem])) {
-            $method = $item;
+            $method = (string) $item;
         } elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
             $method = 'get'.$item;
         } elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
             $method = 'is'.$item;
         } elseif (isset(self::$cache[$class]['methods']['__call'])) {
-            $method = $item;
+            $method = (string) $item;
+            $call = true;
         } else {
             if ($isDefinedTest) {
                 return false;
@@ -432,7 +448,16 @@ protected function getAttribute($object, $item, array $arguments = array(), $typ
             $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method);
         }
 
-        $ret = call_user_func_array(array($object, $method), $arguments);
+        // Some objects throw exceptions when they have __call, and the method we try
+        // to call is not supported. If ignoreStrictCheck is true, we should return null.
+        try {
+            $ret = call_user_func_array(array($object, $method), $arguments);
+        } catch (BadMethodCallException $e) {
+            if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
+                return null;
+            }
+            throw $e;
+        }
 
         // useful when calling a template method from a template
         // this is not supported but unfortunately heavily used in the Symfony profiler
diff --git a/core/vendor/twig/twig/lib/Twig/Token.php b/core/vendor/twig/twig/lib/Twig/Token.php
index bbca90dbbfdc..f3e3501942f2 100644
--- a/core/vendor/twig/twig/lib/Twig/Token.php
+++ b/core/vendor/twig/twig/lib/Twig/Token.php
@@ -121,11 +121,10 @@ public function getValue()
      *
      * @param integer $type  The type as an integer
      * @param Boolean $short Whether to return a short representation or not
-     * @param integer $line  The code line
      *
      * @return string The string representation
      */
-    public static function typeToString($type, $short = false, $line = -1)
+    public static function typeToString($type, $short = false)
     {
         switch ($type) {
             case self::EOF_TYPE:
@@ -178,11 +177,10 @@ public static function typeToString($type, $short = false, $line = -1)
      * Returns the english representation of a given type.
      *
      * @param integer $type The type as an integer
-     * @param integer $line The code line
      *
      * @return string The string representation
      */
-    public static function typeToEnglish($type, $line = -1)
+    public static function typeToEnglish($type)
     {
         switch ($type) {
             case self::EOF_TYPE:
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParser/Block.php b/core/vendor/twig/twig/lib/Twig/TokenParser/Block.php
index a2e017f3e884..81e6b1cffd29 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParser/Block.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParser/Block.php
@@ -41,12 +41,10 @@ public function parse(Twig_Token $token)
         $this->parser->pushLocalScope();
         $this->parser->pushBlockStack($name);
 
-        if ($stream->test(Twig_Token::BLOCK_END_TYPE)) {
-            $stream->next();
-
+        if ($stream->nextIf(Twig_Token::BLOCK_END_TYPE)) {
             $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
-            if ($stream->test(Twig_Token::NAME_TYPE)) {
-                $value = $stream->next()->getValue();
+            if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) {
+                $value = $token->getValue();
 
                 if ($value != $name) {
                     throw new Twig_Error_Syntax(sprintf("Expected endblock for block '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParser/Extends.php b/core/vendor/twig/twig/lib/Twig/TokenParser/Extends.php
index 110bc8b458ef..f5ecee21408b 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParser/Extends.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParser/Extends.php
@@ -38,8 +38,6 @@ public function parse(Twig_Token $token)
         $this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
 
         $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
-
-        return null;
     }
 
     /**
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParser/For.php b/core/vendor/twig/twig/lib/Twig/TokenParser/For.php
index 98a6d079d169..5c07d6395b57 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParser/For.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParser/For.php
@@ -39,8 +39,7 @@ public function parse(Twig_Token $token)
         $seq = $this->parser->getExpressionParser()->parseExpression();
 
         $ifexpr = null;
-        if ($stream->test(Twig_Token::NAME_TYPE, 'if')) {
-            $stream->next();
+        if ($stream->nextIf(Twig_Token::NAME_TYPE, 'if')) {
             $ifexpr = $this->parser->getExpressionParser()->parseExpression();
         }
 
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParser/From.php b/core/vendor/twig/twig/lib/Twig/TokenParser/From.php
index a54054dbc942..dd73f99089e3 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParser/From.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParser/From.php
@@ -36,19 +36,15 @@ public function parse(Twig_Token $token)
             $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
 
             $alias = $name;
-            if ($stream->test('as')) {
-                $stream->next();
-
+            if ($stream->nextIf('as')) {
                 $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
             }
 
             $targets[$name] = $alias;
 
-            if (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
+            if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
                 break;
             }
-
-            $stream->next();
         } while (true);
 
         $stream->expect(Twig_Token::BLOCK_END_TYPE);
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParser/Include.php b/core/vendor/twig/twig/lib/Twig/TokenParser/Include.php
index 4a317868f3e3..9c3099a68de4 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParser/Include.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParser/Include.php
@@ -42,24 +42,19 @@ protected function parseArguments()
         $stream = $this->parser->getStream();
 
         $ignoreMissing = false;
-        if ($stream->test(Twig_Token::NAME_TYPE, 'ignore')) {
-            $stream->next();
+        if ($stream->nextIf(Twig_Token::NAME_TYPE, 'ignore')) {
             $stream->expect(Twig_Token::NAME_TYPE, 'missing');
 
             $ignoreMissing = true;
         }
 
         $variables = null;
-        if ($stream->test(Twig_Token::NAME_TYPE, 'with')) {
-            $stream->next();
-
+        if ($stream->nextIf(Twig_Token::NAME_TYPE, 'with')) {
             $variables = $this->parser->getExpressionParser()->parseExpression();
         }
 
         $only = false;
-        if ($stream->test(Twig_Token::NAME_TYPE, 'only')) {
-            $stream->next();
-
+        if ($stream->nextIf(Twig_Token::NAME_TYPE, 'only')) {
             $only = true;
         }
 
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParser/Macro.php b/core/vendor/twig/twig/lib/Twig/TokenParser/Macro.php
index c2a033608d32..87a299d821b5 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParser/Macro.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParser/Macro.php
@@ -38,8 +38,8 @@ public function parse(Twig_Token $token)
         $stream->expect(Twig_Token::BLOCK_END_TYPE);
         $this->parser->pushLocalScope();
         $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
-        if ($stream->test(Twig_Token::NAME_TYPE)) {
-            $value = $stream->next()->getValue();
+        if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) {
+            $value = $token->getValue();
 
             if ($value != $name) {
                 throw new Twig_Error_Syntax(sprintf("Expected endmacro for macro '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
@@ -49,8 +49,6 @@ public function parse(Twig_Token $token)
         $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()));
-
-        return null;
     }
 
     public function decideBlockEnd(Twig_Token $token)
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParser/Set.php b/core/vendor/twig/twig/lib/Twig/TokenParser/Set.php
index 70e0b41baeee..84f7e94cb313 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParser/Set.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParser/Set.php
@@ -42,8 +42,7 @@ public function parse(Twig_Token $token)
         $names = $this->parser->getExpressionParser()->parseAssignmentExpression();
 
         $capture = false;
-        if ($stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
-            $stream->next();
+        if ($stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) {
             $values = $this->parser->getExpressionParser()->parseMultitargetExpression();
 
             $stream->expect(Twig_Token::BLOCK_END_TYPE);
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParser/Use.php b/core/vendor/twig/twig/lib/Twig/TokenParser/Use.php
index 85f084a52836..3ea68b1a50be 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParser/Use.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParser/Use.php
@@ -42,34 +42,26 @@ public function parse(Twig_Token $token)
         }
 
         $targets = array();
-        if ($stream->test('with')) {
-            $stream->next();
-
+        if ($stream->nextIf('with')) {
             do {
                 $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
 
                 $alias = $name;
-                if ($stream->test('as')) {
-                    $stream->next();
-
+                if ($stream->nextIf('as')) {
                     $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
                 }
 
                 $targets[$name] = new Twig_Node_Expression_Constant($alias, -1);
 
-                if (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
+                if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
                     break;
                 }
-
-                $stream->next();
             } while (true);
         }
 
         $stream->expect(Twig_Token::BLOCK_END_TYPE);
 
         $this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets))));
-
-        return null;
     }
 
     /**
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParserBroker.php b/core/vendor/twig/twig/lib/Twig/TokenParserBroker.php
index 9518c7c8a2af..ec3fba674804 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParserBroker.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParserBroker.php
@@ -111,8 +111,6 @@ public function getTokenParser($tag)
             }
             $broker = prev($this->brokers);
         }
-
-        return null;
     }
 
     public function getParsers()
diff --git a/core/vendor/twig/twig/lib/Twig/TokenParserInterface.php b/core/vendor/twig/twig/lib/Twig/TokenParserInterface.php
index bbde77141030..31e8d5d5e3cd 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenParserInterface.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenParserInterface.php
@@ -29,6 +29,8 @@ public function setParser(Twig_Parser $parser);
      * @param Twig_Token $token A Twig_Token instance
      *
      * @return Twig_NodeInterface A Twig_NodeInterface instance
+     *
+     * @throws Twig_Error_Syntax
      */
     public function parse(Twig_Token $token);
 
diff --git a/core/vendor/twig/twig/lib/Twig/TokenStream.php b/core/vendor/twig/twig/lib/Twig/TokenStream.php
index a78189f667a6..f3c3cbbdf632 100644
--- a/core/vendor/twig/twig/lib/Twig/TokenStream.php
+++ b/core/vendor/twig/twig/lib/Twig/TokenStream.php
@@ -63,6 +63,18 @@ public function next()
         return $this->tokens[$this->current - 1];
     }
 
+    /**
+     * Tests a token, sets the pointer to the next one and returns it or throws a syntax error.
+     *
+     * @return Twig_Token|null The next token if the condition is true, null otherwise
+     */
+    public function nextIf($primary, $secondary = null)
+    {
+        if ($this->tokens[$this->current]->test($primary, $secondary)) {
+            return $this->next();
+        }
+    }
+
     /**
      * Tests a token and returns it or throws a syntax error.
      *
@@ -105,7 +117,7 @@ public function look($number = 1)
     /**
      * Tests the current token
      *
-     * @return bool
+     * @return Boolean
      */
     public function test($primary, $secondary = null)
     {
@@ -115,7 +127,7 @@ public function test($primary, $secondary = null)
     /**
      * Checks if end of stream was reached
      *
-     * @return bool
+     * @return Boolean
      */
     public function isEOF()
     {
diff --git a/core/vendor/twig/twig/test/Twig/Tests/CompilerTest.php b/core/vendor/twig/twig/test/Twig/Tests/CompilerTest.php
index ebe79aef593b..e24b0b5e6d14 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/CompilerTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/CompilerTest.php
@@ -21,13 +21,13 @@ public function testReprNumericValueWithLocale()
         }
 
         $required_locales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252');
-        if (false === setlocale(LC_ALL, $required_locales)) {
-            $this->markTestSkipped('Could not set any of required locales: ' . implode(", ", $required_locales));
+        if (false === setlocale(LC_NUMERIC, $required_locales)) {
+            $this->markTestSkipped('Could not set any of required locales: '.implode(", ", $required_locales));
         }
 
         $this->assertEquals('1.2', $compiler->repr(1.2)->getSource());
         $this->assertContains('fr', strtolower(setlocale(LC_NUMERIC, 0)));
 
-        setlocale(LC_ALL, $locale);
+        setlocale(LC_NUMERIC, $locale);
     }
 }
diff --git a/core/vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php b/core/vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php
index 664e98039361..a5fc87887fb4 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php
@@ -186,7 +186,7 @@ public function testRemoveExtension()
     {
         $twig = new Twig_Environment(new Twig_Loader_String());
         $twig->addExtension(new Twig_Tests_EnvironmentTest_Extension());
-        $twig->removeExtension('test');
+        $twig->removeExtension('environment_test');
 
         $this->assertFalse(array_key_exists('test', $twig->getTags()));
         $this->assertFalse(array_key_exists('foo_filter', $twig->getFilters()));
@@ -218,21 +218,21 @@ public function getNodeVisitors()
     public function getFilters()
     {
         return array(
-            'foo_filter' => new Twig_Filter_Function('foo_filter'),
+            new Twig_SimpleFilter('foo_filter', 'foo_filter'),
         );
     }
 
     public function getTests()
     {
         return array(
-            'foo_test' => new Twig_Test_Function('foo_test'),
+            new Twig_SimpleTest('foo_test', 'foo_test'),
         );
     }
 
     public function getFunctions()
     {
         return array(
-            'foo_function' => new Twig_Function_Function('foo_function'),
+            new Twig_SimpleFunction('foo_function', 'foo_function'),
         );
     }
 
@@ -253,7 +253,7 @@ public function getGlobals()
 
     public function getName()
     {
-        return 'test';
+        return 'environment_test';
     }
 }
 
diff --git a/core/vendor/twig/twig/test/Twig/Tests/ErrorTest.php b/core/vendor/twig/twig/test/Twig/Tests/ErrorTest.php
index 9b286974d621..719a6a78fa8a 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/ErrorTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/ErrorTest.php
@@ -27,65 +27,51 @@ public function testErrorWithArrayFilename()
         $this->assertEquals('foo in {"foo":"bar"}', $error->getMessage());
     }
 
-    public function testTwigExceptionAddsFileAndLineWhenMissing()
+    public function testTwigExceptionAddsFileAndLineWhenMissingWithInheritanceOnDisk()
     {
-        $loader = new Twig_Loader_Array(array('index' => "\n\n{{ foo.bar }}\n\n\n{{ 'foo' }}"));
+        $loader = new Twig_Loader_Filesystem(dirname(__FILE__).'/Fixtures/errors');
         $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
 
-        $template = $twig->loadTemplate('index');
-
+        $template = $twig->loadTemplate('index.html');
         try {
             $template->render(array());
 
             $this->fail();
         } catch (Twig_Error_Runtime $e) {
-            $this->assertEquals('Variable "foo" does not exist in "index" at line 3', $e->getMessage());
+            $this->assertEquals('Variable "foo" does not exist in "index.html" at line 3', $e->getMessage());
             $this->assertEquals(3, $e->getTemplateLine());
-            $this->assertEquals('index', $e->getTemplateFile());
+            $this->assertEquals('index.html', $e->getTemplateFile());
         }
-    }
-
-    public function testRenderWrapsExceptions()
-    {
-        $loader = new Twig_Loader_Array(array('index' => "\n\n\n{{ foo.bar }}\n\n\n\n{{ 'foo' }}"));
-        $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
-
-        $template = $twig->loadTemplate('index');
 
         try {
             $template->render(array('foo' => new Twig_Tests_ErrorTest_Foo()));
 
             $this->fail();
         } catch (Twig_Error_Runtime $e) {
-            $this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index" at line 4.', $e->getMessage());
-            $this->assertEquals(4, $e->getTemplateLine());
-            $this->assertEquals('index', $e->getTemplateFile());
+            $this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index.html" at line 3.', $e->getMessage());
+            $this->assertEquals(3, $e->getTemplateLine());
+            $this->assertEquals('index.html', $e->getTemplateFile());
         }
     }
 
-    public function testTwigExceptionAddsFileAndLineWhenMissingWithInheritance()
+    /**
+     * @dataProvider getErroredTemplates
+     */
+    public function testTwigExceptionAddsFileAndLine($templates, $name, $line)
     {
-        $loader = new Twig_Loader_Array(array(
-            'index' => "{% extends 'base' %}
-            {% block content %}
-                {{ foo.bar }}
-            {% endblock %}
-            {% block foo %}
-                {{ foo.bar }}
-            {% endblock %}",
-            'base' => '{% block content %}{% endblock %}'
-        ));
+        $loader = new Twig_Loader_Array($templates);
         $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
 
         $template = $twig->loadTemplate('index');
+
         try {
             $template->render(array());
 
             $this->fail();
         } catch (Twig_Error_Runtime $e) {
-            $this->assertEquals('Variable "foo" does not exist in "index" at line 3', $e->getMessage());
-            $this->assertEquals(3, $e->getTemplateLine());
-            $this->assertEquals('index', $e->getTemplateFile());
+            $this->assertEquals(sprintf('Variable "foo" does not exist in "%s" at line %d', $name, $line), $e->getMessage());
+            $this->assertEquals($line, $e->getTemplateLine());
+            $this->assertEquals($name, $e->getTemplateFile());
         }
 
         try {
@@ -93,60 +79,59 @@ public function testTwigExceptionAddsFileAndLineWhenMissingWithInheritance()
 
             $this->fail();
         } catch (Twig_Error_Runtime $e) {
-            $this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index" at line 3.', $e->getMessage());
-            $this->assertEquals(3, $e->getTemplateLine());
-            $this->assertEquals('index', $e->getTemplateFile());
+            $this->assertEquals(sprintf('An exception has been thrown during the rendering of a template ("Runtime error...") in "%s" at line %d.', $name, $line), $e->getMessage());
+            $this->assertEquals($line, $e->getTemplateLine());
+            $this->assertEquals($name, $e->getTemplateFile());
         }
     }
 
-    public function testTwigExceptionAddsFileAndLineWhenMissingWithInheritanceAgain()
+    public function getErroredTemplates()
     {
-        $loader = new Twig_Loader_Array(array(
-            'index' => "{% extends 'base' %}
-            {% block content %}
-                {{ parent() }}
-            {% endblock %}",
-            'base' => '{% block content %}{{ foo }}{% endblock %}'
-        ));
-        $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
-
-        $template = $twig->loadTemplate('index');
-        try {
-            $template->render(array());
-
-            $this->fail();
-        } catch (Twig_Error_Runtime $e) {
-            $this->assertEquals('Variable "foo" does not exist in "base" at line 1', $e->getMessage());
-            $this->assertEquals(1, $e->getTemplateLine());
-            $this->assertEquals('base', $e->getTemplateFile());
-        }
-    }
-
-    public function testTwigExceptionAddsFileAndLineWhenMissingWithInheritanceOnDisk()
-    {
-        $loader = new Twig_Loader_Filesystem(dirname(__FILE__).'/Fixtures/errors');
-        $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false));
-
-        $template = $twig->loadTemplate('index.html');
-        try {
-            $template->render(array());
-
-            $this->fail();
-        } catch (Twig_Error_Runtime $e) {
-            $this->assertEquals('Variable "foo" does not exist in "index.html" at line 3', $e->getMessage());
-            $this->assertEquals(3, $e->getTemplateLine());
-            $this->assertEquals('index.html', $e->getTemplateFile());
-        }
-
-        try {
-            $template->render(array('foo' => new Twig_Tests_ErrorTest_Foo()));
-
-            $this->fail();
-        } catch (Twig_Error_Runtime $e) {
-            $this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index.html" at line 3.', $e->getMessage());
-            $this->assertEquals(3, $e->getTemplateLine());
-            $this->assertEquals('index.html', $e->getTemplateFile());
-        }
+        return array(
+            // error occurs in a template
+            array(
+                array(
+                    'index' => "\n\n{{ foo.bar }}\n\n\n{{ 'foo' }}",
+                ),
+                'index', 3,
+            ),
+
+            // error occurs in an included template
+            array(
+                array(
+                    'index'   => "{% include 'partial' %}",
+                    'partial' => '{{ foo.bar }}',
+                ),
+                'partial', 1,
+            ),
+
+            // error occurs in a parent block when called via parent()
+            array(
+                array(
+                    'index' => "{% extends 'base' %}
+                    {% block content %}
+                        {{ parent() }}
+                    {% endblock %}",
+                    'base' => '{% block content %}{{ foo.bar }}{% endblock %}'
+                ),
+                'base', 1,
+            ),
+
+            // error occurs in a block from the child
+            array(
+                array(
+                    'index' => "{% extends 'base' %}
+                    {% block content %}
+                        {{ foo.bar }}
+                    {% endblock %}
+                    {% block foo %}
+                        {{ foo.bar }}
+                    {% endblock %}",
+                    'base' => '{% block content %}{% endblock %}'
+                ),
+                'index', 3,
+            ),
+        );
     }
 }
 
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php b/core/vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php
index 77a8101293ab..5f3da18d5e94 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php
@@ -16,8 +16,10 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
      */
     public function testRandomFunction($value, $expectedInArray)
     {
+        $env = new Twig_Environment();
+
         for ($i = 0; $i < 100; $i++) {
-            $this->assertTrue(in_array(twig_random(new Twig_Environment(), $value), $expectedInArray, true)); // assertContains() would not consider the type
+            $this->assertTrue(in_array(twig_random($env, $value), $expectedInArray, true)); // assertContains() would not consider the type
         }
     }
 
@@ -112,4 +114,25 @@ public function testReverseFilterOnNonUTF8String()
 
         $this->assertEquals($output, 'éÄ');
     }
+
+    public function testCustomEscaper()
+    {
+        $twig = new Twig_Environment();
+        $twig->getExtension('core')->setEscaper('foo', 'foo_escaper_for_test');
+
+        $this->assertEquals('fooUTF-8', twig_escape_filter($twig, 'foo', 'foo'));
+    }
+
+    /**
+     * @expectedException Twig_Error_Runtime
+     */
+    public function testUnknownCustomEscaper()
+    {
+        twig_escape_filter(new Twig_Environment(), 'foo', 'bar');
+    }
+}
+
+function foo_escaper_for_test(Twig_Environment $env, $string, $charset)
+{
+    return $string.$charset;
 }
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php b/core/vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
index 72253c88134f..e4746cb30b70 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
@@ -30,6 +30,7 @@ public function setUp()
             '1_basic6' => '{{ arr.obj }}',
             '1_basic7' => '{{ cycle(["foo","bar"], 1) }}',
             '1_basic8' => '{{ obj.getfoobar }}{{ obj.getFooBar }}',
+            '1_basic9' => '{{ obj.foobar }}{{ obj.fooBar }}',
             '1_basic'  => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
             '1_layout' => '{% block content %}{% endblock %}',
             '1_child'  => '{% extends "1_layout" %}{% block content %}{{ "a"|json_encode }}{% endblock %}',
@@ -127,6 +128,8 @@ public function testSandboxGloballySet()
             FooObject::reset();
             $this->assertEquals('foobarfoobar', $twig->loadTemplate('1_basic8')->render(self::$params), 'Sandbox allow methods in a case-insensitive way');
             $this->assertEquals(2, FooObject::$called['getFooBar'], 'Sandbox only calls method once');
+
+            $this->assertEquals('foobarfoobar', $twig->loadTemplate('1_basic9')->render(self::$params), 'Sandbox allow methods via shortcut names (ie. without get/set)');
         }
     }
 
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/divisibleby.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/divisibleby.test
new file mode 100644
index 000000000000..14ee5e4d3a30
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/divisibleby.test
@@ -0,0 +1,21 @@
+--TEST--
+Twig supports the "divisible by" operator
+--TEMPLATE--
+{{ 8 is divisibleby(2) ? 'OK' }}
+{{ 8 is not divisibleby(3) ? 'OK' }}
+{{ 8 is divisible by(2) ? 'OK' }}
+{{ 8 is not divisible by(3) ? 'OK' }}
+{{ 8 is    divisible   by   (2) ? 'OK' }}
+{{ 8 is not
+   divisible
+   by
+   (3) ? 'OK' }}
+--DATA--
+return array()
+--EXPECT--
+OK
+OK
+OK
+OK
+OK
+OK
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test
new file mode 100644
index 000000000000..d259d1189d17
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test
@@ -0,0 +1,12 @@
+--TEST--
+Twig supports the "ends with" operator
+--TEMPLATE--
+{{ 'foo' ends with 'o' ? 'OK' : 'KO' }}
+{{ not ('foo' ends with 'f') ? 'OK' : 'KO' }}
+{{ not ('foo' ends with 'foowaytoolong') ? 'OK' : 'KO' }}
+--DATA--
+return array()
+--EXPECT--
+OK
+OK
+OK
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/matches.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/matches.test
new file mode 100644
index 000000000000..b6c771657a7c
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/matches.test
@@ -0,0 +1,12 @@
+--TEST--
+Twig supports the "matches" operator
+--TEMPLATE--
+{{ 'foo' matches '/o/' ? 'OK' : 'KO' }}
+{{ 'foo' matches '/^fo/' ? 'OK' : 'KO' }}
+{{ 'foo' matches '/O/i' ? 'OK' : 'KO' }}
+--DATA--
+return array()
+--EXPECT--
+OK
+OK
+OK
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/operators_as_variables.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/operators_as_variables.test
new file mode 100644
index 000000000000..fe29d08bbf72
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/operators_as_variables.test
@@ -0,0 +1,16 @@
+--TEST--
+Twig allows to use named operators as variable names
+--TEMPLATE--
+{% for match in matches %}
+    {{- match }}
+{% endfor %}
+{{ in }}
+{{ is }}
+--DATA--
+return array('matches' => array(1, 2, 3), 'in' => 'in', 'is' => 'is')
+--EXPECT--
+1
+2
+3
+in
+is
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/sameas.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/sameas.test
new file mode 100644
index 000000000000..9e8514fbe956
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/sameas.test
@@ -0,0 +1,21 @@
+--TEST--
+Twig supports the "same as" operator
+--TEMPLATE--
+{{ 1 is sameas(1) ? 'OK' }}
+{{ 1 is not sameas(true) ? 'OK' }}
+{{ 1 is same as(1) ? 'OK' }}
+{{ 1 is not same as(true) ? 'OK' }}
+{{ 1 is   same    as   (1) ? 'OK' }}
+{{ 1 is not
+    same
+    as
+    (true) ? 'OK' }}
+--DATA--
+return array()
+--EXPECT--
+OK
+OK
+OK
+OK
+OK
+OK
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test
new file mode 100644
index 000000000000..1ae4f86efceb
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test
@@ -0,0 +1,17 @@
+--TEST--
+Twig supports the "starts with" operator
+--TEMPLATE--
+{{ 'foo' starts with 'f' ? 'OK' : 'KO' }}
+{{ not ('foo' starts with 'oo') ? 'OK' : 'KO' }}
+{{ not ('foo' starts with 'foowaytoolong') ? 'OK' : 'KO' }}
+{{ 'foo' starts      with 'f' ? 'OK' : 'KO' }}
+{{ 'foo' starts
+with 'f' ? 'OK' : 'KO' }}
+--DATA--
+return array()
+--EXPECT--
+OK
+OK
+OK
+OK
+OK
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/two_word_operators_as_variables.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/two_word_operators_as_variables.test
new file mode 100644
index 000000000000..47f37e45019d
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/two_word_operators_as_variables.test
@@ -0,0 +1,8 @@
+--TEST--
+Twig does not allow to use two-word named operators as variable names
+--TEMPLATE--
+{{ starts with }}
+--DATA--
+return array()
+--EXCEPTION--
+Twig_Error_Syntax: Unexpected token "operator" of value "starts with" in "index.twig" at line 2
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_exact_elements.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_exact_elements.test
new file mode 100644
index 000000000000..72483f4b5a44
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_exact_elements.test
@@ -0,0 +1,33 @@
+--TEST--
+"batch" filter
+--TEMPLATE--
+{% for row in items|batch(3, 'fill') %}
+  <div class=row>
+  {% for column in row %}
+    <div class=item>{{ column }}</div>
+  {% endfor %}
+  </div>
+{% endfor %}
+--DATA--
+return array('items' => array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'))
+--EXPECT--
+<div class=row>
+      <div class=item>a</div>
+      <div class=item>b</div>
+      <div class=item>c</div>
+    </div>
+  <div class=row>
+      <div class=item>d</div>
+      <div class=item>e</div>
+      <div class=item>f</div>
+    </div>
+  <div class=row>
+      <div class=item>g</div>
+      <div class=item>h</div>
+      <div class=item>i</div>
+    </div>
+  <div class=row>
+      <div class=item>j</div>
+      <div class=item>k</div>
+      <div class=item>l</div>
+    </div>
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test
new file mode 100644
index 000000000000..b89ceb309422
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test
@@ -0,0 +1,35 @@
+--TEST--
+"date" filter
+--CONDITION--
+version_compare(phpversion(), '5.5.0', '>=')
+--TEMPLATE--
+{{ date1|date }}
+{{ date1|date('d/m/Y') }}
+{{ date1|date('d/m/Y H:i:s', 'Asia/Hong_Kong') }}
+{{ date1|date('d/m/Y H:i:s', timezone1) }}
+{{ date1|date('d/m/Y H:i:s') }}
+
+{{ date2|date('d/m/Y H:i:s P', 'Europe/Paris') }}
+{{ date2|date('d/m/Y H:i:s P', 'Asia/Hong_Kong') }}
+{{ date2|date('d/m/Y H:i:s P', false) }}
+{{ date2|date('e', 'Europe/Paris') }}
+{{ date2|date('e', false) }}
+--DATA--
+date_default_timezone_set('Europe/Paris');
+return array(
+    'date1' => new DateTimeImmutable('2010-10-04 13:45'),
+    'date2' => new DateTimeImmutable('2010-10-04 13:45', new DateTimeZone('America/New_York')),
+    'timezone1' => new DateTimeZone('America/New_York'),
+)
+--EXPECT--
+October 4, 2010 13:45
+04/10/2010
+04/10/2010 19:45:00
+04/10/2010 07:45:00
+04/10/2010 13:45:00
+
+04/10/2010 19:45:00 +02:00
+05/10/2010 01:45:00 +08:00
+04/10/2010 13:45:00 -04:00
+Europe/Paris
+America/New_York
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_namedargs.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_namedargs.test
index 6ca2049ddec4..4ecde8a185c7 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_namedargs.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_namedargs.test
@@ -3,7 +3,6 @@
 --TEMPLATE--
 {{ date|date(format='d/m/Y H:i:s P', timezone='America/Chicago') }}
 {{ date|date(timezone='America/Chicago', format='d/m/Y H:i:s P') }}
-{{ date|date(timezone='America/Chicago', 'd/m/Y H:i:s P') }}
 {{ date|date('d/m/Y H:i:s P', timezone='America/Chicago') }}
 --DATA--
 date_default_timezone_set('UTC');
@@ -12,4 +11,3 @@ return array('date' => mktime(13, 45, 0, 10, 4, 2010))
 04/10/2010 08:45:00 -05:00
 04/10/2010 08:45:00 -05:00
 04/10/2010 08:45:00 -05:00
-04/10/2010 08:45:00 -05:00
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_html_attr.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_html_attr.test
new file mode 100644
index 000000000000..009a24532fd9
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_html_attr.test
@@ -0,0 +1,8 @@
+--TEST--
+"escape" filter does not escape with the html strategy when using the html_attr strategy
+--TEMPLATE--
+{{ '<br />'|escape('html_attr') }}
+--DATA--
+return array()
+--EXPECT--
+&lt;br&#x20;&#x2F;&gt;
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/first.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/first.test
index 853465b62b43..90f49271f214 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/first.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/first.test
@@ -5,6 +5,7 @@
 {{ {a: 1, b: 2, c: 3, d: 4}|first }}
 {{ '1234'|first }}
 {{ arr|first }}
+{{ 'Ä€é'|first }}
 --DATA--
 return array('arr' => new ArrayObject(array(1, 2, 3, 4)))
 --EXPECT--
@@ -12,3 +13,4 @@ return array('arr' => new ArrayObject(array(1, 2, 3, 4)))
 1
 1
 1
+Ä
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/last.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/last.test
index ca3ac0cf8ead..018fdad89549 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/last.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/last.test
@@ -5,6 +5,7 @@
 {{ {a: 1, b: 2, c: 3, d: 4}|last }}
 {{ '1234'|last }}
 {{ arr|last }}
+{{ 'Ä€é'|last }}
 --DATA--
 return array('arr' => new ArrayObject(array(1, 2, 3, 4)))
 --EXPECT--
@@ -12,3 +13,4 @@ return array('arr' => new ArrayObject(array(1, 2, 3, 4)))
 4
 4
 4
+é
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/round.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/round.test
new file mode 100644
index 000000000000..57806b619717
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/round.test
@@ -0,0 +1,22 @@
+--TEST--
+"round" filter
+--TEMPLATE--
+{{ 2.7|round }}
+{{ 2.1|round }}
+{{ 2.1234|round(3, 'floor') }}
+{{ 2.1|round(0, 'ceil') }}
+
+{{ 21.3|round(-1)}}
+{{ 21.3|round(-1, 'ceil')}}
+{{ 21.3|round(-1, 'floor')}}
+--DATA--
+return array()
+--EXPECT--
+3
+2
+2.123
+3
+
+20
+30
+20
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/special_chars.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/special_chars.test
index cc919000cae2..dbaf7dc979bf 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/special_chars.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/special_chars.test
@@ -1,8 +1,8 @@
 --TEST--
-"☃" custom filter
+"§" custom filter
 --TEMPLATE--
-{{ 'foo'|☃ }}
+{{ 'foo'|§ }}
 --DATA--
 return array()
 --EXPECT--
-☃foo☃
+§foo§
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date.test
index a4c97167d3cf..8be9c0c405da 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date.test
@@ -2,7 +2,6 @@
 "date" function
 --TEMPLATE--
 {{ date() == date('now') ? 'OK' : 'KO' }}
-{{ date() > date('-1day') ? 'OK' : 'KO' }}
 {{ date(date1) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
 {{ date(date2) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
 {{ date(date3) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
@@ -24,4 +23,3 @@ OK
 OK
 OK
 OK
-OK
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/assignment.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/assignment.test
new file mode 100644
index 000000000000..b7653b4ef683
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/assignment.test
@@ -0,0 +1,13 @@
+--TEST--
+"include" function
+--TEMPLATE--
+{% set tmp = include("foo.twig") %}
+
+FOO{{ tmp }}BAR
+--TEMPLATE(foo.twig)--
+FOOBAR
+--DATA--
+return array()
+--EXPECT--
+FOO
+FOOBARBAR
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/autoescaping.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/autoescaping.test
new file mode 100644
index 000000000000..56f8f3b5a33c
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/autoescaping.test
@@ -0,0 +1,10 @@
+--TEST--
+"include" function is safe for auto-escaping
+--TEMPLATE--
+{{ include("foo.twig") }}
+--TEMPLATE(foo.twig)--
+<p>Test</p>
+--DATA--
+return array()
+--EXPECT--
+<p>Test</p>
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/max.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/max.test
new file mode 100644
index 000000000000..e6c94af635b4
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/max.test
@@ -0,0 +1,12 @@
+--TEST--
+"max" function
+--TEMPLATE--
+{{ max([2, 1, 3, 5, 4]) }}
+{{ max(2, 1, 3, 5, 4) }}
+{{ max({2:"two", 1:"one", 3:"three", 5:"five", 4:"for"}) }}
+--DATA--
+return array()
+--EXPECT--
+5
+5
+two
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/min.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/min.test
new file mode 100644
index 000000000000..660471c0007a
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/min.test
@@ -0,0 +1,12 @@
+--TEST--
+"min" function
+--TEMPLATE--
+{{ min(2, 1, 3, 5, 4) }}
+{{ min([2, 1, 3, 5, 4]) }}
+{{ min({2:"two", 1:"one", 3:"three", 5:"five", 4:"for"}) }}
+--DATA--
+return array()
+--EXPECT--
+1
+1
+five
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/source.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/source.test
new file mode 100644
index 000000000000..0e094c3b2e17
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/source.test
@@ -0,0 +1,17 @@
+--TEST--
+"source" function
+--TEMPLATE--
+FOO
+{{ source("foo.twig") }}
+
+BAR
+--TEMPLATE(foo.twig)--
+{{ foo }}<br />
+--DATA--
+return array()
+--EXPECT--
+FOO
+
+{{ foo }}<br />
+
+BAR
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/special_chars.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/special_chars.test
index f602b0df6c5d..30c3df516801 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/special_chars.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/special_chars.test
@@ -1,8 +1,8 @@
 --TEST--
-"☃" custom function
+"§" custom function
 --TEMPLATE--
-{{ ☃('foo') }}
+{{ §('foo') }}
 --DATA--
 return array()
 --EXPECT--
-☃foo☃
+§foo§
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/template_from_string.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/template_from_string.test
index 41428da190a9..3d3b9587453c 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/template_from_string.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/template_from_string.test
@@ -4,8 +4,12 @@
 {% include template_from_string(template) %}
 
 {% include template_from_string("Hello {{ name }}") %}
+{% include template_from_string('{% extends "parent.twig" %}{% block content %}Hello {{ name }}{% endblock %}') %}
+--TEMPLATE(parent.twig)--
+{% block content %}{% endblock %}
 --DATA--
 return array('name' => 'Fabien', 'template' => "Hello {{ name }}")
 --EXPECT--
 Hello Fabien
 Hello Fabien
+Hello Fabien
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/issue_1143.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/issue_1143.test
new file mode 100644
index 000000000000..ff7c8bb70454
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/issue_1143.test
@@ -0,0 +1,23 @@
+--TEST--
+error in twig extension
+--TEMPLATE--
+{{ object.region is not null ? object.regionChoices[object.region] }}
+--DATA--
+class House
+{
+    const REGION_S = 1;
+    const REGION_P = 2;
+
+    public static $regionChoices = array(self::REGION_S => 'house.region.s', self::REGION_P => 'house.region.p');
+
+    public function getRegionChoices()
+    {
+        return self::$regionChoices;
+    }
+}
+
+$object = new House();
+$object->region = 1;
+return array('object' => $object)
+--EXPECT--
+house.region.s
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/simple_xml_element.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/simple_xml_element.test
index 110aef82313c..61babef45e58 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/simple_xml_element.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/simple_xml_element.test
@@ -4,7 +4,7 @@ Twig is able to deal with SimpleXMLElement instances as variables
 version_compare(phpversion(), '5.3.0', '>=')
 --TEMPLATE--
 Hello '{{ images.image.0.group }}'!
-{{ images.children().count() }}
+{{ images.children().image.count() }}
 {% for image in images %}
     - {{ image.group }}
 {% endfor %}
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/special_chars.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/special_chars.test
index 441570cddc4e..be17fedf3721 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/special_chars.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/special_chars.test
@@ -1,10 +1,10 @@
 --TEST--
-"☃" special chars in a block name
+"§" special chars in a block name
 --TEMPLATE--
-{% block ☃ %}
-☃
-{% endblock ☃ %}
+{% block § %}
+§
+{% endblock § %}
 --DATA--
 return array()
 --EXPECT--
-☃
+§
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/error_line.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/error_line.test
new file mode 100644
index 000000000000..71ab2e018a45
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/error_line.test
@@ -0,0 +1,16 @@
+--TEST--
+"embed" tag
+--TEMPLATE(index.twig)--
+FOO
+{% embed "foo.twig" %}
+    {% block c1 %}
+        {{ nothing }}
+    {% endblock %}
+{% endembed %}
+BAR
+--TEMPLATE(foo.twig)--
+{% block c1 %}{% endblock %}
+--DATA--
+return array()
+--EXCEPTION--
+Twig_Error_Runtime: Variable "nothing" does not exist in "index.twig" at line 5
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/special_chars.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/special_chars.test
index 099995110374..3721770730d0 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/special_chars.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/special_chars.test
@@ -1,14 +1,14 @@
 --TEST--
-"☃" as a macro name
+"§" as a macro name
 --TEMPLATE--
 {% import _self as macros %}
 
-{{ macros.☃('foo') }}
+{{ macros.§('foo') }}
 
-{% macro ☃(foo) %}
-  ☃{{ foo }}☃
+{% macro §(foo) %}
+  §{{ foo }}§
 {% endmacro %}
 --DATA--
 return array()
 --EXPECT--
-☃foo☃
+§foo§
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/special_chars.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/special_chars.test
index d584d9ed64b3..789b4ba8052f 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/special_chars.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/special_chars.test
@@ -1,8 +1,8 @@
 --TEST--
-"☃" custom tag
+"§" custom tag
 --TEMPLATE--
-{% ☃ %}
+{% § %}
 --DATA--
 return array()
 --EXPECT--
-☃
+§
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/constant.test b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/constant.test
index c8adb15b15ae..60218ac04c0c 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/constant.test
+++ b/core/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/constant.test
@@ -4,9 +4,11 @@
 {{ 8 is constant('E_NOTICE') ? 'ok' : 'no' }}
 {{ 'bar' is constant('TwigTestFoo::BAR_NAME') ? 'ok' : 'no' }}
 {{ value is constant('TwigTestFoo::BAR_NAME') ? 'ok' : 'no' }}
+{{ 2 is constant('ARRAY_AS_PROPS', object) ? 'ok' : 'no' }}
 --DATA--
-return array('value' => 'bar');
+return array('value' => 'bar', 'object' => new ArrayObject(array('hi')));
 --EXPECT--
 ok
 ok
+ok
 ok
\ No newline at end of file
diff --git a/core/vendor/twig/twig/test/Twig/Tests/IntegrationTest.php b/core/vendor/twig/twig/test/Twig/Tests/IntegrationTest.php
index 3b053cdc8411..ea00b0245d93 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/IntegrationTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/IntegrationTest.php
@@ -109,18 +109,18 @@ public function valid()
     }
 }
 
-class TwigTestTokenParser_☃ extends Twig_TokenParser
+class TwigTestTokenParser_§ extends Twig_TokenParser
 {
     public function parse(Twig_Token $token)
     {
         $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
 
-        return new Twig_Node_Print(new Twig_Node_Expression_Constant('☃', -1), -1);
+        return new Twig_Node_Print(new Twig_Node_Expression_Constant('§', -1), -1);
     }
 
     public function getTag()
     {
-        return '☃';
+        return '§';
     }
 }
 
@@ -129,42 +129,42 @@ class TwigTestExtension extends Twig_Extension
     public function getTokenParsers()
     {
         return array(
-            new TwigTestTokenParser_☃(),
+            new TwigTestTokenParser_§(),
         );
     }
 
     public function getFilters()
     {
         return array(
-            '☃'                => new Twig_Filter_Method($this, '☃Filter'),
-            'escape_and_nl2br' => new Twig_Filter_Method($this, 'escape_and_nl2br', array('needs_environment' => true, 'is_safe' => array('html'))),
-            'nl2br'            => new Twig_Filter_Method($this, 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),
-            'escape_something' => new Twig_Filter_Method($this, 'escape_something', array('is_safe' => array('something'))),
-            'preserves_safety' => new Twig_Filter_Method($this, 'preserves_safety', array('preserves_safety' => array('html'))),
-            '*_path'           => new Twig_Filter_Method($this, 'dynamic_path'),
-            '*_foo_*_bar'      => new Twig_Filter_Method($this, 'dynamic_foo'),
+            new Twig_SimpleFilter('§', array($this, '§Filter')),
+            new Twig_SimpleFilter('escape_and_nl2br', array($this, 'escape_and_nl2br'), array('needs_environment' => true, 'is_safe' => array('html'))),
+            new Twig_SimpleFilter('nl2br', array($this, 'nl2br'), array('pre_escape' => 'html', 'is_safe' => array('html'))),
+            new Twig_SimpleFilter('escape_something', array($this, 'escape_something'), array('is_safe' => array('something'))),
+            new Twig_SimpleFilter('preserves_safety', array($this, 'preserves_safety'), array('preserves_safety' => array('html'))),
+            new Twig_SimpleFilter('*_path', array($this, 'dynamic_path')),
+            new Twig_SimpleFilter('*_foo_*_bar', array($this, 'dynamic_foo')),
         );
     }
 
     public function getFunctions()
     {
         return array(
-            '☃'           => new Twig_Function_Method($this, '☃Function'),
-            'safe_br'     => new Twig_Function_Method($this, 'br', array('is_safe' => array('html'))),
-            'unsafe_br'   => new Twig_Function_Method($this, 'br'),
-            '*_path'      => new Twig_Function_Method($this, 'dynamic_path'),
-            '*_foo_*_bar' => new Twig_Function_Method($this, 'dynamic_foo'),
+            new Twig_SimpleFunction('§', array($this, '§Function')),
+            new Twig_SimpleFunction('safe_br', array($this, 'br'), array('is_safe' => array('html'))),
+            new Twig_SimpleFunction('unsafe_br', array($this, 'br')),
+            new Twig_SimpleFunction('*_path', array($this, 'dynamic_path')),
+            new Twig_SimpleFunction('*_foo_*_bar', array($this, 'dynamic_foo')),
         );
     }
 
-    public function ☃Filter($value)
+    public function §Filter($value)
     {
-        return "☃{$value}☃";
+        return "§{$value}§";
     }
 
-    public function ☃Function($value)
+    public function §Function($value)
     {
-        return "☃{$value}☃";
+        return "§{$value}§";
     }
 
     /**
@@ -212,6 +212,6 @@ public function br()
 
     public function getName()
     {
-        return 'test';
+        return 'integration_test';
     }
 }
diff --git a/core/vendor/twig/twig/test/Twig/Tests/LexerTest.php b/core/vendor/twig/twig/test/Twig/Tests/LexerTest.php
index 34ed74fed739..ab104f4b0c6a 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/LexerTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/LexerTest.php
@@ -12,24 +12,24 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
 {
     public function testNameLabelForTag()
     {
-        $template = '{% ☃ %}';
+        $template = '{% § %}';
 
         $lexer = new Twig_Lexer(new Twig_Environment());
         $stream = $lexer->tokenize($template);
 
         $stream->expect(Twig_Token::BLOCK_START_TYPE);
-        $this->assertSame('☃', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
+        $this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
     }
 
     public function testNameLabelForFunction()
     {
-        $template = '{{ ☃() }}';
+        $template = '{{ §() }}';
 
         $lexer = new Twig_Lexer(new Twig_Environment());
         $stream = $lexer->tokenize($template);
 
         $stream->expect(Twig_Token::VAR_START_TYPE);
-        $this->assertSame('☃', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
+        $this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
     }
 
     public function testBracketsNesting()
@@ -62,11 +62,11 @@ protected function countToken($template, $type, $value = null)
     public function testLineDirective()
     {
         $template = "foo\n"
-            . "bar\n"
-            . "{% line 10 %}\n"
-            . "{{\n"
-            . "baz\n"
-            . "}}\n";
+            ."bar\n"
+            ."{% line 10 %}\n"
+            ."{{\n"
+            ."baz\n"
+            ."}}\n";
 
         $lexer = new Twig_Lexer(new Twig_Environment());
         $stream = $lexer->tokenize($template);
@@ -84,9 +84,9 @@ public function testLineDirective()
     public function testLineDirectiveInline()
     {
         $template = "foo\n"
-            . "bar{% line 10 %}{{\n"
-            . "baz\n"
-            . "}}\n";
+            ."bar{% line 10 %}{{\n"
+            ."baz\n"
+            ."}}\n";
 
         $lexer = new Twig_Lexer(new Twig_Environment());
         $stream = $lexer->tokenize($template);
@@ -141,13 +141,17 @@ public function testLongBlock()
 
     public function testBigNumbers()
     {
+        if ('hiphop' === substr(PHP_VERSION, -6)) {
+            $this->markTestSkipped('hhvm thinks that the number is actually a T_CONSTANT_ENCAPSED_STRING!');
+        }
+
         $template = '{{ 922337203685477580700 }}';
 
         $lexer = new Twig_Lexer(new Twig_Environment());
         $stream = $lexer->tokenize($template);
         $node = $stream->next();
         $node = $stream->next();
-        $this->assertEquals(922337203685477580700, $node->getValue());
+        $this->assertEquals("922337203685477580700", $node->getValue());
     }
 
     public function testStringWithEscapedDelimiter()
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Loader/ChainTest.php b/core/vendor/twig/twig/test/Twig/Tests/Loader/ChainTest.php
index 580ae10508e5..4fe0db948edb 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Loader/ChainTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/Loader/ChainTest.php
@@ -60,4 +60,20 @@ public function testAddLoader()
 
         $this->assertEquals('bar', $loader->getSource('foo'));
     }
+
+    public function testExists()
+    {
+        $loader1 = $this->getMock('Twig_Loader_Array', array('exists', 'getSource'), array(), '', false);
+        $loader1->expects($this->once())->method('exists')->will($this->returnValue(false));
+        $loader1->expects($this->never())->method('getSource');
+
+        $loader2 = $this->getMock('Twig_LoaderInterface');
+        $loader2->expects($this->once())->method('getSource')->will($this->returnValue('content'));
+
+        $loader = new Twig_Loader_Chain();
+        $loader->addLoader($loader1);
+        $loader->addLoader($loader2);
+
+        $this->assertTrue($loader->exists('foo'));
+    }
 }
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php b/core/vendor/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php
index 798e994af493..13849b342e74 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php
@@ -80,12 +80,64 @@ public function testPaths()
         $this->assertEquals("named path (final)\n", $loader->getSource('@named/index.html'));
     }
 
+    public function testEmptyConstructor()
+    {
+        $loader = new Twig_Loader_Filesystem();
+        $this->assertEquals(array(), $loader->getPaths());
+    }
+
     public function testGetNamespaces()
     {
         $loader = new Twig_Loader_Filesystem(sys_get_temp_dir());
-        $this->assertEquals(array('__main__'), $loader->getNamespaces());
+        $this->assertEquals(array(Twig_Loader_Filesystem::MAIN_NAMESPACE), $loader->getNamespaces());
 
         $loader->addPath(sys_get_temp_dir(), 'named');
-        $this->assertEquals(array('__main__', 'named'), $loader->getNamespaces());
+        $this->assertEquals(array(Twig_Loader_Filesystem::MAIN_NAMESPACE, 'named'), $loader->getNamespaces());
+    }
+
+    public function testFindTemplateExceptionNamespace()
+    {
+        $basePath = dirname(__FILE__).'/Fixtures';
+
+        $loader = new Twig_Loader_Filesystem(array($basePath.'/normal'));
+        $loader->addPath($basePath.'/named', 'named');
+
+        try {
+            $loader->getSource('@named/nowhere.html');
+        } catch (Exception $e) {
+            $this->assertInstanceof('Twig_Error_Loader', $e);
+            $this->assertContains('Unable to find template "@named/nowhere.html"', $e->getMessage());
+        }
+    }
+
+    public function testFindTemplateWithCache()
+    {
+        $basePath = dirname(__FILE__).'/Fixtures';
+
+        $loader = new Twig_Loader_Filesystem(array($basePath.'/normal'));
+        $loader->addPath($basePath.'/named', 'named');
+
+        // prime the cache for index.html in the named namespace
+        $namedSource = $loader->getSource('@named/index.html');
+        $this->assertEquals("named path\n", $namedSource);
+
+        // get index.html from the main namespace
+        $this->assertEquals("path\n", $loader->getSource('index.html'));
+    }
+
+    public function testLoadTemplateAndRenderBlockWithCache()
+    {
+        $loader = new Twig_Loader_Filesystem(array());
+        $loader->addPath(dirname(__FILE__).'/Fixtures/themes/theme2');
+        $loader->addPath(dirname(__FILE__).'/Fixtures/themes/theme1');
+        $loader->addPath(dirname(__FILE__).'/Fixtures/themes/theme1', 'default_theme');
+
+        $twig = new Twig_Environment($loader);
+
+        $template = $twig->loadTemplate('blocks.html.twig');
+        $this->assertSame('block from theme 1', $template->renderBlock('b1', array()));
+
+        $template = $twig->loadTemplate('blocks.html.twig');
+        $this->assertSame('block from theme 2', $template->renderBlock('b2', array()));
     }
 }
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme1/blocks.html.twig b/core/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme1/blocks.html.twig
new file mode 100644
index 000000000000..dd0cbc2e712d
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme1/blocks.html.twig
@@ -0,0 +1,3 @@
+{% block b1 %}block from theme 1{% endblock %}
+
+{% block b2 %}block from theme 1{% endblock %}
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme2/blocks.html.twig b/core/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme2/blocks.html.twig
new file mode 100644
index 000000000000..07cf9db0dea5
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme2/blocks.html.twig
@@ -0,0 +1,3 @@
+{% use '@default_theme/blocks.html.twig' %}
+
+{% block b2 %}block from theme 2{% endblock %}
diff --git a/core/vendor/twig/twig/test/Twig/Tests/NativeExtensionTest.php b/core/vendor/twig/twig/test/Twig/Tests/NativeExtensionTest.php
index 3fafd335eda8..9519bdf4aaf6 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/NativeExtensionTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/NativeExtensionTest.php
@@ -23,7 +23,11 @@ public function testGetProperties()
         $d2 = new DateTime();
         $output = $twig->render('{{ d1.date }}{{ d2.date }}', compact('d1', 'd2'));
 
+        if ('hiphop' === substr(PHP_VERSION, -6)) {
+            $this->markTestSkipped('Skip under HHVM as the behavior is not the same as plain PHP (which is an edge case anyway)');
+        }
+
         // If it fails, PHP will crash.
-        $this->assertEquals($output, $d1->date . $d2->date);
+        $this->assertEquals($output, $d1->date.$d2->date);
     }
 }
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/CallTest.php b/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/CallTest.php
new file mode 100644
index 000000000000..c54ea1e02ebf
--- /dev/null
+++ b/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/CallTest.php
@@ -0,0 +1,67 @@
+<?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.
+ */
+
+class Twig_Tests_Node_Expression_CallTest extends PHPUnit_Framework_TestCase
+{
+    public function testGetArguments()
+    {
+        $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date'));
+        $this->assertEquals(array('U', null), $node->getArguments('date', array('format' => 'U', 'timestamp' => null)));
+    }
+
+    /**
+     * @expectedException        Twig_Error_Syntax
+     * @expectedExceptionMessage Positional arguments cannot be used after named arguments for function "date".
+     */
+    public function testGetArgumentsWhenPositionalArgumentsAfterNamedArguments()
+    {
+        $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date'));
+        $node->getArguments('date', array('timestamp' => 123456, 'Y-m-d'));
+    }
+
+    /**
+     * @expectedException        Twig_Error_Syntax
+     * @expectedExceptionMessage Argument "format" is defined twice for function "date".
+     */
+    public function testGetArgumentsWhenArgumentIsDefinedTwice()
+    {
+        $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date'));
+        $node->getArguments('date', array('Y-m-d', 'format' => 'U'));
+    }
+
+    /**
+     * @expectedException        Twig_Error_Syntax
+     * @expectedExceptionMessage Unknown argument "unknown" for function "date".
+     */
+    public function testGetArgumentsWithWrongNamedArgumentName()
+    {
+        $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date'));
+        $node->getArguments('date', array('Y-m-d', 'timestamp' => null, 'unknown' => ''));
+    }
+
+    /**
+     * @expectedException        Twig_Error_Syntax
+     * @expectedExceptionMessage Unknown arguments "unknown1", "unknown2" for function "date".
+     */
+    public function testGetArgumentsWithWrongNamedArgumentNames()
+    {
+        $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date'));
+        $node->getArguments('date', array('Y-m-d', 'timestamp' => null, 'unknown1' => '', 'unknown2' => ''));
+    }
+}
+
+class Twig_Tests_Node_Expression_Call extends Twig_Node_Expression_Call
+{
+    public function getArguments($callable, $arguments)
+    {
+        return parent::getArguments($callable, $arguments);
+    }
+}
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/FunctionTest.php b/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/FunctionTest.php
index 431dc387c790..2693b2ef193c 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/FunctionTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/FunctionTest.php
@@ -36,10 +36,10 @@ public function testCompile($node, $source, $environment = null)
     public function getTests()
     {
         $environment = new Twig_Environment();
-        $environment->addFunction('foo', new Twig_Function_Function('foo', array()));
-        $environment->addFunction('bar', new Twig_Function_Function('bar', array('needs_environment' => true)));
-        $environment->addFunction('foofoo', new Twig_Function_Function('foofoo', array('needs_context' => true)));
-        $environment->addFunction('foobar', new Twig_Function_Function('foobar', array('needs_environment' => true, 'needs_context' => true)));
+        $environment->addFunction(new Twig_SimpleFunction('foo', 'foo', array()));
+        $environment->addFunction(new Twig_SimpleFunction('bar', 'bar', array('needs_environment' => true)));
+        $environment->addFunction(new Twig_SimpleFunction('foofoo', 'foofoo', array('needs_context' => true)));
+        $environment->addFunction(new Twig_SimpleFunction('foobar', 'foobar', array('needs_environment' => true, 'needs_context' => true)));
 
         $tests = array();
 
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php b/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php
index 6a63cce655f9..62fb0d35eb73 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php
@@ -21,12 +21,12 @@ public function testConstructor()
         $args = new Twig_Node_Expression_Array(array(), 1);
         $args->addElement(new Twig_Node_Expression_Name('foo', 1));
         $args->addElement(new Twig_Node_Expression_Constant('bar', 1));
-        $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ARRAY_CALL, 1);
+        $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_Template::ARRAY_CALL, 1);
 
         $this->assertEquals($expr, $node->getNode('node'));
         $this->assertEquals($attr, $node->getNode('attribute'));
         $this->assertEquals($args, $node->getNode('arguments'));
-        $this->assertEquals(Twig_TemplateInterface::ARRAY_CALL, $node->getAttribute('type'));
+        $this->assertEquals(Twig_Template::ARRAY_CALL, $node->getAttribute('type'));
     }
 
     /**
@@ -45,16 +45,16 @@ public function getTests()
         $expr = new Twig_Node_Expression_Name('foo', 1);
         $attr = new Twig_Node_Expression_Constant('bar', 1);
         $args = new Twig_Node_Expression_Array(array(), 1);
-        $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ANY_CALL, 1);
+        $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_Template::ANY_CALL, 1);
         $tests[] = array($node, sprintf('%s%s, "bar")', $this->getAttributeGetter(), $this->getVariableGetter('foo')));
 
-        $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ARRAY_CALL, 1);
+        $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_Template::ARRAY_CALL, 1);
         $tests[] = array($node, sprintf('%s%s, "bar", array(), "array")', $this->getAttributeGetter(), $this->getVariableGetter('foo')));
 
         $args = new Twig_Node_Expression_Array(array(), 1);
         $args->addElement(new Twig_Node_Expression_Name('foo', 1));
         $args->addElement(new Twig_Node_Expression_Constant('bar', 1));
-        $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::METHOD_CALL, 1);
+        $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_Template::METHOD_CALL, 1);
         $tests[] = array($node, sprintf('%s%s, "bar", array(0 => %s, 1 => "bar"), "method")', $this->getAttributeGetter(), $this->getVariableGetter('foo'), $this->getVariableGetter('foo')));
 
         return $tests;
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Node/ForTest.php b/core/vendor/twig/twig/test/Twig/Tests/Node/ForTest.php
index f1093b7592b1..21cc84e6ee67 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Node/ForTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/Node/ForTest.php
@@ -70,7 +70,7 @@ public function getTests()
 }
 \$_parent = \$context['_parent'];
 unset(\$context['_seq'], \$context['_iterated'], \$context['key'], \$context['item'], \$context['_parent'], \$context['loop']);
-\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));
+\$context = array_intersect_key(\$context, \$_parent) + \$_parent;
 EOF
         );
 
@@ -113,7 +113,7 @@ public function getTests()
 }
 \$_parent = \$context['_parent'];
 unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
-\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));
+\$context = array_intersect_key(\$context, \$_parent) + \$_parent;
 EOF
         );
 
@@ -146,7 +146,7 @@ public function getTests()
 }
 \$_parent = \$context['_parent'];
 unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
-\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));
+\$context = array_intersect_key(\$context, \$_parent) + \$_parent;
 EOF
         );
 
@@ -194,7 +194,7 @@ public function getTests()
 }
 \$_parent = \$context['_parent'];
 unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
-\$context = array_merge(\$_parent, array_intersect_key(\$context, \$_parent));
+\$context = array_intersect_key(\$context, \$_parent) + \$_parent;
 EOF
         );
 
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Node/ModuleTest.php b/core/vendor/twig/twig/test/Twig/Tests/Node/ModuleTest.php
index 9411e99e2783..b8996edf42e6 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Node/ModuleTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/Node/ModuleTest.php
@@ -65,7 +65,7 @@ public function getTests()
 <?php
 
 /* foo.twig */
-class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
+class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c18638df0d extends Twig_Template
 {
     public function __construct(Twig_Environment \$env)
     {
@@ -106,7 +106,7 @@ public function getDebugInfo()
 <?php
 
 /* foo.twig */
-class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
+class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c18638df0d extends Twig_Template
 {
     public function __construct(Twig_Environment \$env)
     {
@@ -161,7 +161,7 @@ public function getDebugInfo()
 <?php
 
 /* foo.twig */
-class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
+class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c18638df0d extends Twig_Template
 {
     protected function doGetParent(array \$context)
     {
diff --git a/core/vendor/twig/twig/test/Twig/Tests/Node/SandboxedModuleTest.php b/core/vendor/twig/twig/test/Twig/Tests/Node/SandboxedModuleTest.php
index 217e3408ff5c..421f2109b839 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/Node/SandboxedModuleTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/Node/SandboxedModuleTest.php
@@ -63,7 +63,7 @@ public function getTests()
 <?php
 
 /* foo.twig */
-class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
+class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c18638df0d extends Twig_Template
 {
     public function __construct(Twig_Environment \$env)
     {
@@ -118,7 +118,7 @@ public function getDebugInfo()
 <?php
 
 /* foo.twig */
-class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template
+class __TwigTemplate_a2bfbf7dd6ab85666684fe9297f69363a3fc2046d90f22a317d380c18638df0d extends Twig_Template
 {
     public function __construct(Twig_Environment \$env)
     {
diff --git a/core/vendor/twig/twig/test/Twig/Tests/TemplateTest.php b/core/vendor/twig/twig/test/Twig/Tests/TemplateTest.php
index 7b821dc354e5..25c7a4aa1ba3 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/TemplateTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/TemplateTest.php
@@ -27,28 +27,33 @@ public function testGetAttributeExceptions($template, $message, $useExt)
         $template = $env->loadTemplate($name);
 
         $context = array(
-            'string'       => 'foo',
-            'array'        => array('foo' => 'foo'),
-            'array_access' => new Twig_TemplateArrayAccessObject(),
+            'string'          => 'foo',
+            'array'           => array('foo' => 'foo'),
+            'array_access'    => new Twig_TemplateArrayAccessObject(),
+            'magic_exception' => new Twig_TemplateMagicPropertyObjectWithException(),
         );
 
         try {
             $template->render($context);
+            $this->fail('Accessing an invalid attribute should throw an exception.');
         } catch (Twig_Error_Runtime $e) {
-            $this->assertEquals(sprintf($message, $name), $e->getMessage());
+            $this->assertSame(sprintf($message, $name), $e->getMessage());
         }
     }
 
     public function getAttributeExceptions()
     {
         $tests = array(
-            array('{{ string["a"] }}', 'Impossible to access a key ("a") on a "string" variable in "%s" at line 1', false),
+            array('{{ string["a"] }}', 'Impossible to access a key ("a") on a string variable ("foo") in "%s" at line 1', false),
             array('{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
             array('{{ array_access["a"] }}', 'Key "a" in object (with ArrayAccess) of type "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
-            array('{{ string.a }}', 'Item "a" for "foo" does not exist in "%s" at line 1', false),
-            array('{{ array.a }}', 'Item "a" for "Array" does not exist in "%s" at line 1', false),
+            array('{{ string.a }}', 'Impossible to access an attribute ("a") on a string variable ("foo") in "%s" at line 1', false),
+            array('{{ string.a() }}', 'Impossible to invoke a method ("a") on a string variable ("foo") in "%s" at line 1', false),
+            array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
+            array('{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1', false),
             array('{{ array_access.a }}', 'Method "a" for object "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
             array('{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ _self.foo(array_access) }}', 'Method "missing_method" for object "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
+            array('{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.', false),
         );
 
         if (function_exists('twig_template_get_attributes')) {
@@ -139,6 +144,46 @@ public function getGetAttributeWithTemplateAsObject()
         return $bools;
     }
 
+    /**
+     * @dataProvider getTestsDependingOnExtensionAvailability
+     */
+    public function testGetAttributeOnArrayWithConfusableKey($useExt = false)
+    {
+        $template = new Twig_TemplateTest(
+            new Twig_Environment(),
+            $useExt
+        );
+
+        $array = array('Zero', 'One', -1 => 'MinusOne', '' => 'EmptyString', '1.5' => 'FloatButString', '01' => 'IntegerButStringWithLeadingZeros');
+
+        $this->assertSame('Zero', $array[false]);
+        $this->assertSame('One', $array[true]);
+        $this->assertSame('One', $array[1.5]);
+        $this->assertSame('One', $array['1']);
+        $this->assertSame('MinusOne', $array[-1.5]);
+        $this->assertSame('FloatButString', $array['1.5']);
+        $this->assertSame('IntegerButStringWithLeadingZeros', $array['01']);
+        $this->assertSame('EmptyString', $array[null]);
+
+        $this->assertSame('Zero', $template->getAttribute($array, false), 'false is treated as 0 when accessing an array (equals PHP behavior)');
+        $this->assertSame('One', $template->getAttribute($array, true), 'true is treated as 1 when accessing an array (equals PHP behavior)');
+        $this->assertSame('One', $template->getAttribute($array, 1.5), 'float is casted to int when accessing an array (equals PHP behavior)');
+        $this->assertSame('One', $template->getAttribute($array, '1'), '"1" is treated as integer 1 when accessing an array (equals PHP behavior)');
+        $this->assertSame('MinusOne', $template->getAttribute($array, -1.5), 'negative float is casted to int when accessing an array (equals PHP behavior)');
+        $this->assertSame('FloatButString', $template->getAttribute($array, '1.5'), '"1.5" is treated as-is when accessing an array (equals PHP behavior)');
+        $this->assertSame('IntegerButStringWithLeadingZeros', $template->getAttribute($array, '01'), '"01" is treated as-is when accessing an array (equals PHP behavior)');
+        $this->assertSame('EmptyString', $template->getAttribute($array, null), 'null is treated as "" when accessing an array (equals PHP behavior)');
+    }
+
+    public function getTestsDependingOnExtensionAvailability()
+    {
+        if (function_exists('twig_template_get_attributes')) {
+            return array(array(false), array(true));
+        }
+
+        return array(array(false));
+    }
+
     /**
      * @dataProvider getGetAttributeTests
      */
@@ -191,6 +236,18 @@ public function testGetAttributeDefinedStrict($defined, $value, $object, $item,
         $this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true));
     }
 
+    /**
+     * @dataProvider getTestsDependingOnExtensionAvailability
+     */
+    public function testGetAttributeCallExceptions($useExt = false)
+    {
+        $template = new Twig_TemplateTest(new Twig_Environment(), $useExt);
+
+        $object = new Twig_TemplateMagicMethodExceptionObject();
+
+        $this->assertEquals(null, $template->getAttribute($object, 'foo'));
+    }
+
     public function getGetAttributeTests()
     {
         $array = array(
@@ -199,6 +256,8 @@ public function getGetAttributeTests()
             'null'    => null,
             '1'       => 1,
             'bar'     => true,
+            '09'      => '09',
+            '+4'      => '+4',
         );
 
         $objectArray         = new Twig_TemplateArrayAccessObject();
@@ -210,9 +269,9 @@ public function getGetAttributeTests()
         $methodObject        = new Twig_TemplateMethodObject();
         $magicMethodObject   = new Twig_TemplateMagicMethodObject();
 
-        $anyType    = Twig_TemplateInterface::ANY_CALL;
-        $methodType = Twig_TemplateInterface::METHOD_CALL;
-        $arrayType  = Twig_TemplateInterface::ARRAY_CALL;
+        $anyType    = Twig_Template::ANY_CALL;
+        $methodType = Twig_Template::METHOD_CALL;
+        $arrayType  = Twig_Template::ARRAY_CALL;
 
         $basicTests = array(
             // array(defined, value, property to fetch)
@@ -224,6 +283,8 @@ public function getGetAttributeTests()
             array(true,  1,         1.0),
             array(true,  null,      'null'),
             array(true,  true,      'bar'),
+            array(true,  '09',      '09'),
+            array(true,  '+4',      '+4'),
         );
         $testObjects = array(
             // array(object, type of fetch)
@@ -243,6 +304,10 @@ public function getGetAttributeTests()
             foreach ($basicTests as $test) {
                 // properties cannot be numbers
                 if (($testObject[0] instanceof stdClass || $testObject[0] instanceof Twig_TemplatePropertyObject) && is_numeric($test[2])) {
+                     continue;
+                }
+
+                if ('+4' === $test[2] && $methodObject === $testObject[0]) {
                     continue;
                 }
 
@@ -293,9 +358,9 @@ public function getGetAttributeTests()
 
         // tests when input is not an array or object
         $tests = array_merge($tests, array(
-            array(false, null, 42, 'a', array(), $anyType, false, 'Item "a" for "42" does not exist'),
-            array(false, null, "string", 'a', array(), $anyType, false, 'Item "a" for "string" does not exist'),
-            array(false, null, array(), 'a', array(), $anyType, false, 'Item "a" for "Array" does not exist'),
+            array(false, null, 42, 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a integer variable ("42")'),
+            array(false, null, "string", 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a string variable ("string")'),
+            array(false, null, array(), 'a', array(), $anyType, false, 'Key "a" for array with keys "" does not exist'),
         ));
 
         // add twig_template_get_attributes tests
@@ -360,7 +425,7 @@ protected function doDisplay(array $context, array $blocks = array())
     {
     }
 
-    public function getAttribute($object, $item, array $arguments = array(), $type = Twig_TemplateInterface::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
+    public function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
     {
         if ($this->useExtGetAttribute) {
             return twig_template_get_attributes($this, $object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
@@ -380,6 +445,8 @@ class Twig_TemplateArrayAccessObject implements ArrayAccess
         'null'    => null,
         '1'       => 1,
         'bar'     => true,
+        '09'      => '09',
+        '+4'      => '+4',
     );
 
     public function offsetExists($name)
@@ -410,6 +477,8 @@ class Twig_TemplateMagicPropertyObject
         'null'    => null,
         '1'       => 1,
         'bar'     => true,
+        '09'      => '09',
+        '+4'      => '+4',
     );
 
     protected $protected = 'protected';
@@ -425,6 +494,14 @@ public function __get($name)
     }
 }
 
+class Twig_TemplateMagicPropertyObjectWithException
+{
+    public function __isset($key)
+    {
+        throw new Exception("Hey! Don't try to isset me!");
+    }
+}
+
 class Twig_TemplatePropertyObject
 {
     public $defined = 'defined';
@@ -478,6 +555,11 @@ public function get1()
         return 1;
     }
 
+    public function get09()
+    {
+        return '09';
+    }
+
     public function getZero()
     {
         return 0;
@@ -533,6 +615,14 @@ public function __call($method, $arguments)
     }
 }
 
+class Twig_TemplateMagicMethodExceptionObject
+{
+    public function __call($method, $arguments)
+    {
+        throw new BadMethodCallException(sprintf('Unkown method %s', $method));
+    }
+}
+
 class CExtDisablingNodeVisitor implements Twig_NodeVisitorInterface
 {
     public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
diff --git a/core/vendor/twig/twig/test/Twig/Tests/escapingTest.php b/core/vendor/twig/twig/test/Twig/Tests/escapingTest.php
index b41b5f972e3b..34d2a2dbfc0c 100644
--- a/core/vendor/twig/twig/test/Twig/Tests/escapingTest.php
+++ b/core/vendor/twig/twig/test/Twig/Tests/escapingTest.php
@@ -237,18 +237,18 @@ protected function codepointToUtf8($codepoint)
         }
         if ($codepoint < 0x800) {
             return chr($codepoint >> 6 & 0x3f | 0xc0)
-                . chr($codepoint & 0x3f | 0x80);
+                .chr($codepoint & 0x3f | 0x80);
         }
         if ($codepoint < 0x10000) {
             return chr($codepoint >> 12 & 0x0f | 0xe0)
-                . chr($codepoint >> 6 & 0x3f | 0x80)
-                . chr($codepoint & 0x3f | 0x80);
+                .chr($codepoint >> 6 & 0x3f | 0x80)
+                .chr($codepoint & 0x3f | 0x80);
         }
         if ($codepoint < 0x110000) {
             return chr($codepoint >> 18 & 0x07 | 0xf0)
-                . chr($codepoint >> 12 & 0x3f | 0x80)
-                . chr($codepoint >> 6 & 0x3f | 0x80)
-                . chr($codepoint & 0x3f | 0x80);
+                .chr($codepoint >> 12 & 0x3f | 0x80)
+                .chr($codepoint >> 6 & 0x3f | 0x80)
+                .chr($codepoint & 0x3f | 0x80);
         }
         throw new Exception('Codepoint requested outside of Unicode range');
     }
diff --git a/core/vendor/twig/twig/test/bootstrap.php b/core/vendor/twig/twig/test/bootstrap.php
index 36eb46af67ef..aecb976f7f25 100644
--- a/core/vendor/twig/twig/test/bootstrap.php
+++ b/core/vendor/twig/twig/test/bootstrap.php
@@ -10,4 +10,4 @@
  */
 
 require_once dirname(__FILE__).'/../lib/Twig/Autoloader.php';
-Twig_Autoloader::register();
+Twig_Autoloader::register(true);
-- 
GitLab