Awight has uploaded a new change for review.
https://gerrit.wikimedia.org/r/178396
Change subject: update twig
......................................................................
update twig
Change-Id: Ia9ce422c57cf893c4971de2c8b4d51858be846fe
---
M twig/twig/.travis.yml
M twig/twig/CHANGELOG
M twig/twig/doc/api.rst
M twig/twig/doc/deprecated.rst
M twig/twig/doc/filters/batch.rst
M twig/twig/doc/filters/convert_encoding.rst
M twig/twig/doc/filters/first.rst
M twig/twig/doc/filters/last.rst
M twig/twig/doc/filters/merge.rst
M twig/twig/doc/filters/nl2br.rst
M twig/twig/doc/filters/number_format.rst
M twig/twig/doc/filters/raw.rst
M twig/twig/doc/filters/slice.rst
M twig/twig/doc/filters/split.rst
M twig/twig/doc/filters/trim.rst
M twig/twig/doc/functions/date.rst
M twig/twig/doc/functions/dump.rst
M twig/twig/doc/functions/include.rst
M twig/twig/doc/functions/random.rst
M twig/twig/doc/functions/source.rst
M twig/twig/doc/functions/template_from_string.rst
M twig/twig/doc/index.rst
M twig/twig/doc/installation.rst
M twig/twig/doc/intro.rst
M twig/twig/doc/tags/autoescape.rst
M twig/twig/doc/tags/do.rst
M twig/twig/doc/tags/if.rst
M twig/twig/doc/tags/use.rst
M twig/twig/doc/templates.rst
D twig/twig/ext/twig/LICENSE
M twig/twig/ext/twig/php_twig.h
M twig/twig/ext/twig/twig.c
M twig/twig/lib/Twig/Compiler.php
M twig/twig/lib/Twig/Environment.php
M twig/twig/lib/Twig/Error.php
M twig/twig/lib/Twig/ExpressionParser.php
M twig/twig/lib/Twig/Extension/Core.php
M twig/twig/lib/Twig/Loader/Array.php
M twig/twig/lib/Twig/Loader/String.php
M twig/twig/lib/Twig/Node.php
M twig/twig/lib/Twig/Node/AutoEscape.php
M twig/twig/lib/Twig/Node/Block.php
M twig/twig/lib/Twig/Node/BlockReference.php
M twig/twig/lib/Twig/Node/Do.php
M twig/twig/lib/Twig/Node/Expression/Array.php
M twig/twig/lib/Twig/Node/Expression/AssignName.php
M twig/twig/lib/Twig/Node/Expression/Binary.php
M twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php
M twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php
M twig/twig/lib/Twig/Node/Expression/Binary/In.php
M twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php
M twig/twig/lib/Twig/Node/Expression/Binary/Power.php
M twig/twig/lib/Twig/Node/Expression/Binary/Range.php
M twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php
M twig/twig/lib/Twig/Node/Expression/BlockReference.php
M twig/twig/lib/Twig/Node/Expression/ExtensionReference.php
M twig/twig/lib/Twig/Node/Expression/GetAttr.php
M twig/twig/lib/Twig/Node/Expression/Parent.php
M twig/twig/lib/Twig/Node/Flush.php
M twig/twig/lib/Twig/Node/For.php
M twig/twig/lib/Twig/Node/ForLoop.php
M twig/twig/lib/Twig/Node/If.php
M twig/twig/lib/Twig/Node/Import.php
M twig/twig/lib/Twig/Node/Include.php
M twig/twig/lib/Twig/Node/Macro.php
M twig/twig/lib/Twig/Node/Module.php
M twig/twig/lib/Twig/Node/Print.php
M twig/twig/lib/Twig/Node/Sandbox.php
M twig/twig/lib/Twig/Node/SandboxedModule.php
M twig/twig/lib/Twig/Node/SandboxedPrint.php
M twig/twig/lib/Twig/Node/Set.php
M twig/twig/lib/Twig/Node/Spaceless.php
M twig/twig/lib/Twig/Node/Text.php
M twig/twig/lib/Twig/NodeInterface.php
M twig/twig/lib/Twig/NodeVisitor/Optimizer.php
M twig/twig/lib/Twig/NodeVisitor/Sandbox.php
A twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php
A twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php
A twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php
M twig/twig/lib/Twig/Sandbox/SecurityPolicy.php
M twig/twig/lib/Twig/Template.php
M twig/twig/test/Twig/Tests/EnvironmentTest.php
M twig/twig/test/Twig/Tests/Extension/CoreTest.php
M twig/twig/test/Twig/Tests/Extension/SandboxTest.php
M twig/twig/test/Twig/Tests/FileCachingTest.php
M twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_trait.test
M twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test
M twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test
M twig/twig/test/Twig/Tests/Fixtures/filters/date.test
M twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test
M twig/twig/test/Twig/Tests/Fixtures/filters/slice.test
M twig/twig/test/Twig/Tests/Fixtures/filters/split.test
A twig/twig/test/Twig/Tests/Fixtures/filters/split_utf8.test
M twig/twig/test/Twig/Tests/Fixtures/functions/attribute.test
M twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test
A twig/twig/test/Twig/Tests/Fixtures/regression/combined_debug_info.test
A twig/twig/test/Twig/Tests/Fixtures/regression/multi_word_tests.test
A twig/twig/test/Twig/Tests/Fixtures/tags/macro/super_globals.test
M twig/twig/test/Twig/Tests/IntegrationTest.php
M twig/twig/test/Twig/Tests/LexerTest.php
M twig/twig/test/Twig/Tests/NativeExtensionTest.php
M twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php
M twig/twig/test/Twig/Tests/Node/IncludeTest.php
M twig/twig/test/Twig/Tests/Node/MacroTest.php
M twig/twig/test/Twig/Tests/Node/SandboxedModuleTest.php
M twig/twig/test/Twig/Tests/TemplateTest.php
M twig/twig/test/Twig/Tests/escapingTest.php
107 files changed, 705 insertions(+), 320 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/wikimedia/fundraising/crm/vendor
refs/changes/96/178396/1
diff --git a/twig/twig/.travis.yml b/twig/twig/.travis.yml
index a8d71c2..1fbff75 100644
--- a/twig/twig/.travis.yml
+++ b/twig/twig/.travis.yml
@@ -5,6 +5,7 @@
- 5.3
- 5.4
- 5.5
+ - 5.6
- hhvm
env:
diff --git a/twig/twig/CHANGELOG b/twig/twig/CHANGELOG
index 1cf54a7..33b32f8 100644
--- a/twig/twig/CHANGELOG
+++ b/twig/twig/CHANGELOG
@@ -1,3 +1,24 @@
+* 1.16.2 (2014-10-17)
+
+ * fixed timezone on dates as strings
+ * fixed 2-words test names when a custom node class is not used
+ * fixed macros when using an argument named like a PHP super global (like GET
or POST)
+ * fixed date_modify when working with DateTimeImmutable
+ * optimized for loops
+ * fixed multi-byte characters handling in the split filter
+ * fixed a regression in the in operator
+ * fixed a regression in the slice filter
+
+* 1.16.1 (2014-10-10)
+
+ * improved error reporting in a sandboxed template
+ * fixed missing error file/line information under certain circumstances
+ * fixed wrong error line number in some error messages
+ * fixed the in operator to use strict comparisons
+ * sped up the slice filter
+ * fixed for mb function overload mb_substr acting different
+ * fixed the attribute() function when passing a variable for the arguments
+
* 1.16.0 (2014-07-05)
* changed url_encode to always encode according to RFC 3986
diff --git a/twig/twig/doc/api.rst b/twig/twig/doc/api.rst
index b00d61e..7756127 100644
--- a/twig/twig/doc/api.rst
+++ b/twig/twig/doc/api.rst
@@ -166,21 +166,6 @@
$twig->render('@admin/index.html', array());
-``Twig_Loader_String``
-......................
-
-``Twig_Loader_String`` loads templates from strings. It's a dummy loader as
-the template reference is the template source code::
-
- $loader = new Twig_Loader_String();
- $twig = new Twig_Environment($loader);
-
- echo $twig->render('Hello {{ name }}!', array('name' => 'Fabien'));
-
-This loader should only be used for unit testing as it has severe limitations:
-several tags, like ``extends`` or ``include`` do not make sense to use as the
-reference to the template is the template source code itself.
-
``Twig_Loader_Array``
.....................
@@ -214,7 +199,7 @@
'base.html' => '{% block content %}{% endblock %}',
));
$loader2 = new Twig_Loader_Array(array(
- 'index.html' => '{% extends "base.twig" %}{% block content %}Hello {{
name }}{% endblock %}',
+ 'index.html' => '{% extends "base.html" %}{% block content %}Hello {{
name }}{% endblock %}',
'base.html' => 'Will never be loaded',
));
@@ -266,26 +251,6 @@
* @param timestamp $time The last modification time of the cached
template
*/
function isFresh($name, $time);
- }
-
-As an example, here is how the built-in ``Twig_Loader_String`` reads::
-
- class Twig_Loader_String implements Twig_LoaderInterface
- {
- public function getSource($name)
- {
- return $name;
- }
-
- public function getCacheKey($name)
- {
- return $name;
- }
-
- public function isFresh($name, $time)
- {
- return false;
- }
}
The ``isFresh()`` method must return ``true`` if the current cached template
diff --git a/twig/twig/doc/deprecated.rst b/twig/twig/doc/deprecated.rst
index 641f31e..30aaac1 100644
--- a/twig/twig/doc/deprecated.rst
+++ b/twig/twig/doc/deprecated.rst
@@ -23,7 +23,7 @@
PEAR
----
-PEAR support has been discontinued in Twig 1.15.1, and no PEAR packages is
+PEAR support has been discontinued in Twig 1.15.1, and no PEAR packages are
provided anymore. Use Composer instead.
Filters
@@ -80,6 +80,12 @@
* The ``sameas`` and ``divisibleby`` tests are deprecated in favor of ``same
as`` and ``divisible by`` respectively.
+Nodes
+-----
+
+* As of Twig 1.x, ``Node::toXml()`` is deprecated and will be removed in Twig
+ 2.0.
+
Interfaces
----------
diff --git a/twig/twig/doc/filters/batch.rst b/twig/twig/doc/filters/batch.rst
index b0b9964..30dd782 100644
--- a/twig/twig/doc/filters/batch.rst
+++ b/twig/twig/doc/filters/batch.rst
@@ -2,7 +2,7 @@
=========
.. versionadded:: 1.12.3
- The batch filter was added in Twig 1.12.3.
+ The ``batch`` filter was added in Twig 1.12.3.
The ``batch`` filter "batches" items by returning a list of lists with the
given number of items. If you provide a second parameter, it is used to fill
diff --git a/twig/twig/doc/filters/convert_encoding.rst
b/twig/twig/doc/filters/convert_encoding.rst
index c417e12..f4ebe58 100644
--- a/twig/twig/doc/filters/convert_encoding.rst
+++ b/twig/twig/doc/filters/convert_encoding.rst
@@ -21,8 +21,8 @@
Arguments
---------
-* ``from``: The input charset
* ``to``: The output charset
+* ``from``: The input charset
.. _`iconv`: http://php.net/iconv
.. _`mbstring`: http://php.net/mbstring
diff --git a/twig/twig/doc/filters/first.rst b/twig/twig/doc/filters/first.rst
index 4295e83..674c1f9 100644
--- a/twig/twig/doc/filters/first.rst
+++ b/twig/twig/doc/filters/first.rst
@@ -2,7 +2,7 @@
=========
.. versionadded:: 1.12.2
- The first filter was added in Twig 1.12.2.
+ The ``first`` filter was added in Twig 1.12.2.
The ``first`` filter returns the first "element" of a sequence, a mapping, or
a string:
diff --git a/twig/twig/doc/filters/last.rst b/twig/twig/doc/filters/last.rst
index 723c0b5..345b657 100644
--- a/twig/twig/doc/filters/last.rst
+++ b/twig/twig/doc/filters/last.rst
@@ -2,7 +2,7 @@
========
.. versionadded:: 1.12.2
- The last filter was added in Twig 1.12.2.
+ The ``last`` filter was added in Twig 1.12.2.
The ``last`` filter returns the last "element" of a sequence, a mapping, or
a string:
diff --git a/twig/twig/doc/filters/merge.rst b/twig/twig/doc/filters/merge.rst
index 05a2ae7..cb8b1b2 100644
--- a/twig/twig/doc/filters/merge.rst
+++ b/twig/twig/doc/filters/merge.rst
@@ -39,3 +39,9 @@
{% set items = { 'apple': 'unknown' }|merge(items) %}
{# items now contains { 'apple': 'fruit', 'orange': 'fruit' } #}
+
+.. note::
+
+ Internally, Twig uses the PHP `array_merge`_ function.
+
+.. _`array_merge`: http://php.net/array_merge
diff --git a/twig/twig/doc/filters/nl2br.rst b/twig/twig/doc/filters/nl2br.rst
index 694c672..5c923e1 100644
--- a/twig/twig/doc/filters/nl2br.rst
+++ b/twig/twig/doc/filters/nl2br.rst
@@ -2,7 +2,7 @@
=========
.. versionadded:: 1.5
- The nl2br filter was added in Twig 1.5.
+ The ``nl2br`` filter was added in Twig 1.5.
The ``nl2br`` filter inserts HTML line breaks before all newlines in a string:
diff --git a/twig/twig/doc/filters/number_format.rst
b/twig/twig/doc/filters/number_format.rst
index 3e60691..3114e84 100644
--- a/twig/twig/doc/filters/number_format.rst
+++ b/twig/twig/doc/filters/number_format.rst
@@ -2,7 +2,7 @@
=================
.. versionadded:: 1.5
- The number_format filter was added in Twig 1.5
+ The ``number_format`` filter was added in Twig 1.5
The ``number_format`` filter formats numbers. It is a wrapper around PHP's
`number_format`_ function:
diff --git a/twig/twig/doc/filters/raw.rst b/twig/twig/doc/filters/raw.rst
index a9900c7..e5e5b12 100644
--- a/twig/twig/doc/filters/raw.rst
+++ b/twig/twig/doc/filters/raw.rst
@@ -10,3 +10,27 @@
{% autoescape %}
{{ var|raw }} {# var won't be escaped #}
{% endautoescape %}
+
+.. note::
+
+ Be careful when using the ``raw`` filter inside expressions:
+
+ .. code-block:: jinja
+
+ {% autoescape %}
+ {% set hello = '<strong>Hello</strong>' %}
+ {% set hola = '<strong>Hola</strong>' %}
+
+ {{ false ? '<strong>Hola</strong>' : hello|raw }}
+ does not render the same as
+ {{ false ? hola : hello|raw }}
+ but renders the same as
+ {{ (false ? hola : hello)|raw }}
+ {% endautoescape %}
+
+ The first ternary statement is not escaped: ``hello`` is marked as being
+ safe and Twig does not escape static values (see
+ :doc:`escape<../tags/autoescape>`). In the second ternary statement, even
+ if ``hello`` is marked as safe, ``hola`` remains unsafe and so is the whole
+ expression. The third ternary statement is marked as safe and the result is
+ not escaped.
diff --git a/twig/twig/doc/filters/slice.rst b/twig/twig/doc/filters/slice.rst
index afc8300..a856664 100644
--- a/twig/twig/doc/filters/slice.rst
+++ b/twig/twig/doc/filters/slice.rst
@@ -2,7 +2,7 @@
===========
.. versionadded:: 1.6
- The slice filter was added in Twig 1.6.
+ The ``slice`` filter was added in Twig 1.6.
The ``slice`` filter extracts a slice of a sequence, a mapping, or a string:
diff --git a/twig/twig/doc/filters/split.rst b/twig/twig/doc/filters/split.rst
index 5c70b46..bbc6d79 100644
--- a/twig/twig/doc/filters/split.rst
+++ b/twig/twig/doc/filters/split.rst
@@ -2,7 +2,7 @@
=========
.. versionadded:: 1.10.3
- The split filter was added in Twig 1.10.3.
+ The ``split`` filter was added in Twig 1.10.3.
The ``split`` filter splits a string by the given delimiter and returns a list
of strings:
diff --git a/twig/twig/doc/filters/trim.rst b/twig/twig/doc/filters/trim.rst
index 0c5b32e..4ddb208 100644
--- a/twig/twig/doc/filters/trim.rst
+++ b/twig/twig/doc/filters/trim.rst
@@ -2,7 +2,7 @@
========
.. versionadded:: 1.6.2
- The trim filter was added in Twig 1.6.2.
+ The ``trim`` filter was added in Twig 1.6.2.
The ``trim`` filter strips whitespace (or other characters) from the beginning
and end of a string:
diff --git a/twig/twig/doc/functions/date.rst b/twig/twig/doc/functions/date.rst
index 9442c39..714e08c 100644
--- a/twig/twig/doc/functions/date.rst
+++ b/twig/twig/doc/functions/date.rst
@@ -15,7 +15,7 @@
{# do something #}
{% endif %}
-The argument must be in a format supported by the `date`_ function.
+The argument must be in one of PHP’s supported `date and time formats`_.
You can pass a timezone as the second argument:
@@ -49,4 +49,4 @@
* ``date``: The date
* ``timezone``: The timezone
-.. _`date`: http://www.php.net/date
+.. _`date and time formats`: http://php.net/manual/en/datetime.formats.php
diff --git a/twig/twig/doc/functions/dump.rst b/twig/twig/doc/functions/dump.rst
index 54f8d4e..a231f08 100644
--- a/twig/twig/doc/functions/dump.rst
+++ b/twig/twig/doc/functions/dump.rst
@@ -2,7 +2,7 @@
========
.. versionadded:: 1.5
- The dump function was added in Twig 1.5.
+ The ``dump`` function was added in Twig 1.5.
The ``dump`` function dumps information about a template variable. This is
mostly useful to debug a template that does not behave as expected by
diff --git a/twig/twig/doc/functions/include.rst
b/twig/twig/doc/functions/include.rst
index 8feb0f1..33bd56d 100644
--- a/twig/twig/doc/functions/include.rst
+++ b/twig/twig/doc/functions/include.rst
@@ -2,7 +2,7 @@
===========
.. versionadded:: 1.12
- The include function was added in Twig 1.12.
+ The ``include`` function was added in Twig 1.12.
The ``include`` function returns the rendered content of a template:
diff --git a/twig/twig/doc/functions/random.rst
b/twig/twig/doc/functions/random.rst
index acbffe5..168e74f 100644
--- a/twig/twig/doc/functions/random.rst
+++ b/twig/twig/doc/functions/random.rst
@@ -2,7 +2,7 @@
==========
.. versionadded:: 1.5
- The random function was added in Twig 1.5.
+ The ``random`` function was added in Twig 1.5.
.. versionadded:: 1.6
String and integer handling was added in Twig 1.6.
diff --git a/twig/twig/doc/functions/source.rst
b/twig/twig/doc/functions/source.rst
index defa5fb..8ff39c2 100644
--- a/twig/twig/doc/functions/source.rst
+++ b/twig/twig/doc/functions/source.rst
@@ -2,7 +2,7 @@
==========
.. versionadded:: 1.15
- The source function was added in Twig 1.15.
+ The ``source`` function was added in Twig 1.15.
The ``source`` function returns the content of a template without rendering it:
diff --git a/twig/twig/doc/functions/template_from_string.rst
b/twig/twig/doc/functions/template_from_string.rst
index 95d9256..ce6a60d 100644
--- a/twig/twig/doc/functions/template_from_string.rst
+++ b/twig/twig/doc/functions/template_from_string.rst
@@ -2,7 +2,7 @@
========================
.. versionadded:: 1.11
- The template_from_string function was added in Twig 1.11.
+ The ``template_from_string`` function was added in Twig 1.11.
The ``template_from_string`` function loads a template from a string:
diff --git a/twig/twig/doc/index.rst b/twig/twig/doc/index.rst
index 3109c73..358bd73 100644
--- a/twig/twig/doc/index.rst
+++ b/twig/twig/doc/index.rst
@@ -5,15 +5,15 @@
:maxdepth: 2
intro
+ installation
templates
api
advanced
internals
+ deprecated
recipes
coding_standards
tags/index
filters/index
functions/index
tests/index
- installation
- deprecated
diff --git a/twig/twig/doc/installation.rst b/twig/twig/doc/installation.rst
index d402f8a..2d19f75 100644
--- a/twig/twig/doc/installation.rst
+++ b/twig/twig/doc/installation.rst
@@ -9,44 +9,26 @@
Installing via Composer (recommended)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. Install Composer in your project:
+Install `Composer`_ and run the following command to get the latest version:
.. 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`_.
+ composer require twig/twig:~1.0
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
+2. Verify the integrity of the tarball
http://fabien.potencier.org/article/73/signing-project-releases
+3. Unpack the tarball
+4. Move the files somewhere in your project
Installing the development version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. Install Git
-2. ``git clone git://github.com/fabpot/Twig.git``
+.. code-block:: bash
+
+ git clone git://github.com/fabpot/Twig.git
Installing the PEAR package
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -56,9 +38,10 @@
Using PEAR for installing Twig is deprecated and Twig 1.15.1 was the last
version published on the PEAR channel; use Composer instead.
-1. Install PEAR
-2. ``pear channel-discover pear.twig-project.org``
-3. ``pear install twig/Twig``
+.. code-block:: bash
+
+ pear channel-discover pear.twig-project.org
+ pear install twig/Twig
Installing the C extension
--------------------------
@@ -75,11 +58,11 @@
.. code-block:: bash
- $ cd ext/twig
- $ phpize
- $ ./configure
- $ make
- $ make install
+ cd ext/twig
+ phpize
+ ./configure
+ make
+ make install
.. note::
@@ -87,9 +70,10 @@
deprecated and newer versions of Twig are not available on the PEAR
channel):
- 1. Install PEAR
- 2. ``pear channel-discover pear.twig-project.org``
- 3. ``pear install twig/CTwig``
+ .. code-block:: bash
+
+ pear channel-discover pear.twig-project.org
+ pear install twig/CTwig
For Windows:
@@ -124,6 +108,6 @@
``Twig_Template::getAttribute()`` method.
.. _`download page`: https://github.com/fabpot/Twig/tags
-.. _`online documentation`: http://getcomposer.org/doc
+.. _`Composer`: https://getcomposer.org/download/
.. _`PHP documentation`: https://wiki.php.net/internals/windows/stepbystepbuild
.. _`Zend Server FAQ`: http://www.zend.com/en/products/server/faq#faqD6
diff --git a/twig/twig/doc/intro.rst b/twig/twig/doc/intro.rst
index 8677d50..3a7c1d4 100644
--- a/twig/twig/doc/intro.rst
+++ b/twig/twig/doc/intro.rst
@@ -33,7 +33,7 @@
.. code-block:: bash
- composer require "twig/twig:1.*"
+ composer require "twig/twig:~1.0"
.. note::
@@ -50,12 +50,14 @@
require_once '/path/to/vendor/autoload.php';
- $loader = new Twig_Loader_String();
+ $loader = new Twig_Loader_Array(
+ 'index' => 'Hello {{ name }}!',
+ );
$twig = new Twig_Environment($loader);
- echo $twig->render('Hello {{ name }}!', array('name' => 'Fabien'));
+ echo $twig->render('index', array('name' => 'Fabien'));
-Twig uses a loader (``Twig_Loader_String``) to locate templates, and an
+Twig uses a loader (``Twig_Loader_Array``) to locate templates, and an
environment (``Twig_Environment``) to store the configuration.
The ``render()`` method loads the template passed as a first argument and
diff --git a/twig/twig/doc/tags/autoescape.rst
b/twig/twig/doc/tags/autoescape.rst
index c5ff0c2..4208d1a 100644
--- a/twig/twig/doc/tags/autoescape.rst
+++ b/twig/twig/doc/tags/autoescape.rst
@@ -67,5 +67,17 @@
.. note::
+ Twig does not escape static expressions:
+
+ .. code-block:: jinja
+
+ {% set hello = "<strong>Hello</strong>" %}
+ {{ hello }}
+ {{ "<strong>world</strong>" }}
+
+ Will be rendered "<strong>Hello</strong> **world**".
+
+.. note::
+
The chapter :doc:`Twig for Developers<../api>` gives more information
about when and how automatic escaping is applied.
diff --git a/twig/twig/doc/tags/do.rst b/twig/twig/doc/tags/do.rst
index eca63d0..1c344e3 100644
--- a/twig/twig/doc/tags/do.rst
+++ b/twig/twig/doc/tags/do.rst
@@ -2,7 +2,7 @@
======
.. versionadded:: 1.5
- The do tag was added in Twig 1.5.
+ The ``do`` tag was added in Twig 1.5.
The ``do`` tag works exactly like the regular variable expression (``{{ ...
}}``) just that it doesn't print anything:
diff --git a/twig/twig/doc/tags/if.rst b/twig/twig/doc/tags/if.rst
index d7a1451..273207d 100644
--- a/twig/twig/doc/tags/if.rst
+++ b/twig/twig/doc/tags/if.rst
@@ -41,3 +41,20 @@
{% else %}
Kenny looks okay --- so far
{% endif %}
+
+.. note::
+
+ The rules to determine if an expression is ``true`` or ``false`` are the
+ same as in PHP; here are the edge cases rules:
+
+ ====================== ====================
+ Value Boolean evaluation
+ ====================== ====================
+ empty string false
+ numeric zero false
+ whitespace-only string true
+ empty array false
+ null false
+ non-empty array true
+ object true
+ ====================== ====================
diff --git a/twig/twig/doc/tags/use.rst b/twig/twig/doc/tags/use.rst
index e403632..a2f3af0 100644
--- a/twig/twig/doc/tags/use.rst
+++ b/twig/twig/doc/tags/use.rst
@@ -39,7 +39,8 @@
.. code-block:: jinja
- # blocks.html
+ {# blocks.html #}
+
{% block sidebar %}{% endblock %}
In this example, the ``use`` statement imports the ``sidebar`` block into the
diff --git a/twig/twig/doc/templates.rst b/twig/twig/doc/templates.rst
index aff036d..82b6f0c 100644
--- a/twig/twig/doc/templates.rst
+++ b/twig/twig/doc/templates.rst
@@ -693,7 +693,7 @@
.. code-block:: jinja
- {% if phone matches '{^[\d\.]+$}' %}
+ {% if phone matches '/^[\\d\\.]+$/' %}
{% endif %}
Containment Operator
diff --git a/twig/twig/ext/twig/LICENSE b/twig/twig/ext/twig/LICENSE
deleted file mode 100644
index 3384cc5..0000000
--- a/twig/twig/ext/twig/LICENSE
+++ /dev/null
@@ -1,31 +0,0 @@
-Copyright (c) 2009-2013 by the Twig Team, see AUTHORS for more details.
-
-Some rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
-
- * The names of the contributors may not be used to endorse or
- promote products derived from this software without specific
- prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/twig/twig/ext/twig/php_twig.h b/twig/twig/ext/twig/php_twig.h
index aefbf04..e116b4c 100644
--- a/twig/twig/ext/twig/php_twig.h
+++ b/twig/twig/ext/twig/php_twig.h
@@ -15,7 +15,7 @@
#ifndef PHP_TWIG_H
#define PHP_TWIG_H
-#define PHP_TWIG_VERSION "1.16.0"
+#define PHP_TWIG_VERSION "1.16.2"
#include "php.h"
diff --git a/twig/twig/ext/twig/twig.c b/twig/twig/ext/twig/twig.c
index 5cb923f..5c482be 100644
--- a/twig/twig/ext/twig/twig.c
+++ b/twig/twig/ext/twig/twig.c
@@ -830,7 +830,11 @@
} elseif (is_object($object)) {
$message = sprintf('Impossible to access a key
"%s" on an object of class "%s" that does not implement ArrayAccess interface',
$item, get_class($object));
} elseif (is_array($object)) {
- $message = sprintf('Key "%s" for array with
keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
+ if (empty($object)) {
+ $message = sprintf('Key "%s" does not exist
as the array is empty', $arrayItem);
+ } else {
+ $message = sprintf('Key "%s" for array with
keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
+ }
} elseif (Twig_Template::ARRAY_CALL === $type) {
$message = sprintf('Impossible to access a key
("%s") on a %s variable ("%s")', $item, gettype($object), $object);
} else {
@@ -845,7 +849,11 @@
} else if (Z_TYPE_P(object) == IS_OBJECT) {
TWIG_RUNTIME_ERROR(template TSRMLS_CC,
"Impossible to access a key \"%s\" on an object of class \"%s\" that does not
implement ArrayAccess interface", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
} 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));
+ if (0 ==
zend_hash_num_elements(Z_ARRVAL_P(object))) {
+ TWIG_RUNTIME_ERROR(template TSRMLS_CC,
"Key \"%s\" does not exist as the array is empty", item);
+ } else {
+ 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 {
char *type_name = zend_zval_type_name(object);
Z_ADDREF_P(object);
diff --git a/twig/twig/lib/Twig/Compiler.php b/twig/twig/lib/Twig/Compiler.php
index ee00519..93dc876 100644
--- a/twig/twig/lib/Twig/Compiler.php
+++ b/twig/twig/lib/Twig/Compiler.php
@@ -74,6 +74,7 @@
{
$this->lastLine = null;
$this->source = '';
+ $this->debugInfo = array();
$this->sourceOffset = 0;
// source code starts at 1 (as we then increment it when we encounter
new lines)
$this->sourceLine = 1;
@@ -181,14 +182,14 @@
} elseif (is_array($value)) {
$this->raw('array(');
$first = true;
- foreach ($value as $key => $value) {
+ foreach ($value as $key => $v) {
if (!$first) {
$this->raw(', ');
}
$first = false;
$this->repr($key);
$this->raw(' => ');
- $this->repr($value);
+ $this->repr($v);
}
$this->raw(')');
} else {
@@ -267,4 +268,9 @@
return $this;
}
+
+ public function getVarName()
+ {
+ return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(),
true), false));
+ }
}
diff --git a/twig/twig/lib/Twig/Environment.php
b/twig/twig/lib/Twig/Environment.php
index d3ba9be..17e88ab 100644
--- a/twig/twig/lib/Twig/Environment.php
+++ b/twig/twig/lib/Twig/Environment.php
@@ -16,7 +16,7 @@
*/
class Twig_Environment
{
- const VERSION = '1.16.0';
+ const VERSION = '1.16.2';
protected $charset;
protected $loader;
diff --git a/twig/twig/lib/Twig/Error.php b/twig/twig/lib/Twig/Error.php
index 6772887..5b253dd 100644
--- a/twig/twig/lib/Twig/Error.php
+++ b/twig/twig/lib/Twig/Error.php
@@ -229,6 +229,8 @@
while ($e = array_pop($exceptions)) {
$traces = $e->getTrace();
+ array_unshift($traces, array('file' => $e->getFile(), 'line' =>
$e->getLine()));
+
while ($trace = array_shift($traces)) {
if (!isset($trace['file']) || !isset($trace['line']) || $file
!= $trace['file']) {
continue;
diff --git a/twig/twig/lib/Twig/ExpressionParser.php
b/twig/twig/lib/Twig/ExpressionParser.php
index 01594f7..f685bad 100644
--- a/twig/twig/lib/Twig/ExpressionParser.php
+++ b/twig/twig/lib/Twig/ExpressionParser.php
@@ -318,7 +318,7 @@
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_Template::ANY_CALL, $line);
+ return new Twig_Node_Expression_GetAttr($args->getNode(0),
$args->getNode(1), count($args) > 2 ? $args->getNode(2) : null,
Twig_Template::ANY_CALL, $line);
default:
if (null !== $alias =
$this->parser->getImportedSymbol('function', $name)) {
$arguments = new Twig_Node_Expression_Array(array(),
$line);
diff --git a/twig/twig/lib/Twig/Extension/Core.php
b/twig/twig/lib/Twig/Extension/Core.php
index 750ef0f..e71d741 100644
--- a/twig/twig/lib/Twig/Extension/Core.php
+++ b/twig/twig/lib/Twig/Extension/Core.php
@@ -173,7 +173,7 @@
// array helpers
new Twig_SimpleFilter('join', 'twig_join_filter'),
- new Twig_SimpleFilter('split', 'twig_split_filter'),
+ new Twig_SimpleFilter('split', 'twig_split_filter',
array('needs_environment' => true)),
new Twig_SimpleFilter('sort', 'twig_sort_filter'),
new Twig_SimpleFilter('merge', 'twig_array_merge'),
new Twig_SimpleFilter('batch', 'twig_array_batch'),
@@ -298,8 +298,8 @@
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());
+ $name = $this->getTestName($parser, $node->getLine());
+ $class = $this->getTestNodeClass($parser, $name);
$arguments = null;
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
$arguments = $parser->getExpressionParser()->parseArguments(true);
@@ -308,32 +308,40 @@
return new $class($node, $name, $arguments,
$parser->getCurrentToken()->getLine());
}
- protected function getTestNodeClass(Twig_Parser $parser, $name, $line)
+ protected function getTestName(Twig_Parser $parser, $line)
{
+ $stream = $parser->getStream();
+ $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
$env = $parser->getEnvironment();
$testMap = $env->getTests();
- $testName = null;
+
if (isset($testMap[$name])) {
- $testName = $name;
- } elseif ($parser->getStream()->test(Twig_Token::NAME_TYPE)) {
+ return $name;
+ }
+
+ if ($stream->test(Twig_Token::NAME_TYPE)) {
// try 2-words tests
$name = $name.' '.$parser->getCurrentToken()->getValue();
if (isset($testMap[$name])) {
$parser->getStream()->next();
- $testName = $name;
+ return $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));
- }
-
- throw new Twig_Error_Syntax($message, $line,
$parser->getFilename());
+ $message = sprintf('The test "%s" does not exist', $name);
+ if ($alternatives = $env->computeAlternatives($name,
array_keys($testMap))) {
+ $message = sprintf('%s. Did you mean "%s"', $message, implode('",
"', $alternatives));
}
+
+ throw new Twig_Error_Syntax($message, $line, $parser->getFilename());
+ }
+
+ protected function getTestNodeClass(Twig_Parser $parser, $name)
+ {
+ $env = $parser->getEnvironment();
+ $testMap = $env->getTests();
if ($testMap[$name] instanceof Twig_SimpleTest) {
return $testMap[$name]->getNodeClass();
@@ -436,10 +444,10 @@
* {{ post.published_at|date("m/d/Y") }}
* </pre>
*
- * @param Twig_Environment $env A Twig_Environment instance
- * @param DateTime|DateInterval|string $date A date
- * @param string $format A format
- * @param DateTimeZone|string $timezone A timezone
+ * @param Twig_Environment $env A
Twig_Environment instance
+ * @param DateTime|DateTimeInterface|DateInterval|string $date A date
+ * @param string|null $format The target
format, null to use the default
+ * @param DateTimeZone|string|null|false $timezone The target
timezone, null to use the default, false to leave unchanged
*
* @return string The formatted date
*/
@@ -473,9 +481,12 @@
function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
{
$date = twig_date_converter($env, $date, false);
- $date->modify($modifier);
+ $resultDate = $date->modify($modifier);
- return $date;
+ // This is a hack to ensure PHP 5.2 support and support for
DateTimeImmutable
+ // DateTime::modify does not return the modified DateTime object < 5.3.0
+ // and DateTimeImmutable does not modify $date.
+ return null === $resultDate ? $date : $resultDate;
}
/**
@@ -487,32 +498,32 @@
* {% endif %}
* </pre>
*
- * @param Twig_Environment $env A Twig_Environment instance
- * @param DateTime|string $date A date
- * @param DateTimeZone|string $timezone A timezone
+ * @param Twig_Environment $env A Twig_Environment
instance
+ * @param DateTime|DateTimeInterface|string|null $date A date
+ * @param DateTimeZone|string|null|false $timezone The target
timezone, null to use the default, false to leave unchanged
*
* @return DateTime A DateTime instance
*/
function twig_date_converter(Twig_Environment $env, $date = null, $timezone =
null)
{
// determine the timezone
- if (!$timezone) {
- $defaultTimezone = $env->getExtension('core')->getTimezone();
- } elseif (!$timezone instanceof DateTimeZone) {
- $defaultTimezone = new DateTimeZone($timezone);
- } else {
- $defaultTimezone = $timezone;
+ if (false !== $timezone) {
+ if (null === $timezone) {
+ $timezone = $env->getExtension('core')->getTimezone();
+ } elseif (!$timezone instanceof DateTimeZone) {
+ $timezone = new DateTimeZone($timezone);
+ }
}
// immutable dates
if ($date instanceof DateTimeImmutable) {
- return false !== $timezone ? $date->setTimezone($defaultTimezone) :
$date;
+ return false !== $timezone ? $date->setTimezone($timezone) : $date;
}
if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
$date = clone $date;
if (false !== $timezone) {
- $date->setTimezone($defaultTimezone);
+ $date->setTimezone($timezone);
}
return $date;
@@ -523,9 +534,9 @@
$date = '@'.$date;
}
- $date = new DateTime($date, $defaultTimezone);
+ $date = new DateTime($date, $env->getExtension('core')->getTimezone());
if (false !== $timezone) {
- $date->setTimezone($defaultTimezone);
+ $date->setTimezone($timezone);
}
return $date;
@@ -672,7 +683,7 @@
function twig_array_merge($arr1, $arr2)
{
if (!is_array($arr1) || !is_array($arr2)) {
- throw new Twig_Error_Runtime('The merge filter only works with arrays
or hashes.');
+ throw new Twig_Error_Runtime(sprintf('The merge filter only works with
arrays or hashes; %s and %s given.', gettype($arr1), gettype($arr2)));
}
return array_merge($arr1, $arr2);
@@ -692,7 +703,15 @@
function twig_slice(Twig_Environment $env, $item, $start, $length = null,
$preserveKeys = false)
{
if ($item instanceof Traversable) {
- $item = iterator_to_array($item, false);
+ if ($item instanceof IteratorAggregate) {
+ $item = $item->getIterator();
+ }
+
+ if ($start >= 0 && $length >= 0) {
+ return iterator_to_array(new LimitIterator($item, $start, $length
=== null ? -1 : $length), $preserveKeys);
+ }
+
+ $item = iterator_to_array($item, $preserveKeys);
}
if (is_array($item)) {
@@ -702,10 +721,10 @@
$item = (string) $item;
if (function_exists('mb_get_info') && null !== $charset =
$env->getCharset()) {
- return mb_substr($item, $start, null === $length ? mb_strlen($item,
$charset) - $start : $length, $charset);
+ return (string) mb_substr($item, $start, null === $length ?
mb_strlen($item, $charset) - $start : $length, $charset);
}
- return null === $length ? substr($item, $start) : substr($item, $start,
$length);
+ return (string) (null === $length ? substr($item, $start) : substr($item,
$start, $length));
}
/**
@@ -788,13 +807,31 @@
*
* @return array The split string as an array
*/
-function twig_split_filter($value, $delimiter, $limit = null)
+function twig_split_filter(Twig_Environment $env, $value, $delimiter, $limit =
null)
{
- if (empty($delimiter)) {
+ if (!empty($delimiter)) {
+ return null === $limit ? explode($delimiter, $value) :
explode($delimiter, $value, $limit);
+ }
+
+ if (!function_exists('mb_get_info') || null === $charset =
$env->getCharset()) {
return str_split($value, null === $limit ? 1 : $limit);
}
- return null === $limit ? explode($delimiter, $value) : explode($delimiter,
$value, $limit);
+ if ($limit <= 1) {
+ return preg_split('/(?<!^)(?!$)/u', $value);
+ }
+
+ $length = mb_strlen($value, $charset);
+ if ($length < $limit) {
+ return array($value);
+ }
+
+ $r = array();
+ for ($i = 0; $i < $length; $i += $limit) {
+ $r[] = mb_substr($value, $i, $limit, $charset);
+ }
+
+ return $r;
}
// The '_default' filter is used internally to avoid using the ternary operator
@@ -944,7 +981,7 @@
static $htmlspecialcharsCharsets;
if (null === $htmlspecialcharsCharsets) {
- if ('hiphop' === substr(PHP_VERSION, -6)) {
+ if (defined('HHVM_VERSION')) {
$htmlspecialcharsCharsets = array('utf-8' => true, 'UTF-8'
=> true);
} else {
$htmlspecialcharsCharsets = array(
diff --git a/twig/twig/lib/Twig/Loader/Array.php
b/twig/twig/lib/Twig/Loader/Array.php
index ac56104..436edd8 100644
--- a/twig/twig/lib/Twig/Loader/Array.php
+++ b/twig/twig/lib/Twig/Loader/Array.php
@@ -17,6 +17,8 @@
* source code of the template). If you don't want to see your cache grows out
of
* control, you need to take care of clearing the old cache file by yourself.
*
+ * This loader should only be used for unit testing.
+ *
* @author Fabien Potencier <[email protected]>
*/
class Twig_Loader_Array implements Twig_LoaderInterface,
Twig_ExistsLoaderInterface
diff --git a/twig/twig/lib/Twig/Loader/String.php
b/twig/twig/lib/Twig/Loader/String.php
index 8ad9856..2099c09 100644
--- a/twig/twig/lib/Twig/Loader/String.php
+++ b/twig/twig/lib/Twig/Loader/String.php
@@ -12,9 +12,7 @@
/**
* Loads a template from a string.
*
- * This loader should only be used for unit testing as it has many limitations
- * (for instance, the include or extends tag does not make any sense for a
string
- * loader).
+ * This loader should NEVER be used. It only exists for Twig internal purposes.
*
* When using this loader with a cache mechanism, you should know that a new
cache
* key is generated each time a template content "changes" (the cache key
being the
diff --git a/twig/twig/lib/Twig/Node.php b/twig/twig/lib/Twig/Node.php
index 978e766..20af544 100644
--- a/twig/twig/lib/Twig/Node.php
+++ b/twig/twig/lib/Twig/Node.php
@@ -69,6 +69,9 @@
return implode("\n", $repr);
}
+ /**
+ * @deprecated since 1.16.1 (to be removed in 2.0)
+ */
public function toXml($asDom = false)
{
$dom = new DOMDocument('1.0', 'UTF-8');
diff --git a/twig/twig/lib/Twig/Node/AutoEscape.php
b/twig/twig/lib/Twig/Node/AutoEscape.php
index 8f190e0..fcabf90 100644
--- a/twig/twig/lib/Twig/Node/AutoEscape.php
+++ b/twig/twig/lib/Twig/Node/AutoEscape.php
@@ -30,7 +30,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Block.php
b/twig/twig/lib/Twig/Node/Block.php
index 50eb67e..989e4a0 100644
--- a/twig/twig/lib/Twig/Node/Block.php
+++ b/twig/twig/lib/Twig/Node/Block.php
@@ -25,7 +25,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/BlockReference.php
b/twig/twig/lib/Twig/Node/BlockReference.php
index 013e369..a05ea04 100644
--- a/twig/twig/lib/Twig/Node/BlockReference.php
+++ b/twig/twig/lib/Twig/Node/BlockReference.php
@@ -25,7 +25,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Do.php b/twig/twig/lib/Twig/Node/Do.php
index c528066..9981bc1 100644
--- a/twig/twig/lib/Twig/Node/Do.php
+++ b/twig/twig/lib/Twig/Node/Do.php
@@ -24,7 +24,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/Array.php
b/twig/twig/lib/Twig/Node/Expression/Array.php
index 1da785f..6cf7ca1 100644
--- a/twig/twig/lib/Twig/Node/Expression/Array.php
+++ b/twig/twig/lib/Twig/Node/Expression/Array.php
@@ -63,7 +63,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/AssignName.php
b/twig/twig/lib/Twig/Node/Expression/AssignName.php
index 2ddea78..4d5dbdb 100644
--- a/twig/twig/lib/Twig/Node/Expression/AssignName.php
+++ b/twig/twig/lib/Twig/Node/Expression/AssignName.php
@@ -15,7 +15,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/Binary.php
b/twig/twig/lib/Twig/Node/Expression/Binary.php
index 9dd5de2..5c383d1 100644
--- a/twig/twig/lib/Twig/Node/Expression/Binary.php
+++ b/twig/twig/lib/Twig/Node/Expression/Binary.php
@@ -19,7 +19,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php
b/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php
index 5de6c72..93b3b96 100644
--- a/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php
+++ b/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php
@@ -12,14 +12,14 @@
{
public function compile(Twig_Compiler $compiler)
{
+ $left = $compiler->getVarName();
+ $right = $compiler->getVarName();
$compiler
- ->raw('(0 === substr_compare(')
+ ->raw(sprintf('(is_string($%s = ', $left))
->subcompile($this->getNode('left'))
- ->raw(', ')
+ ->raw(sprintf(') && is_string($%s = ', $right))
->subcompile($this->getNode('right'))
- ->raw(', -strlen(')
- ->subcompile($this->getNode('right'))
- ->raw(')))')
+ ->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s,
-strlen($%2$s))))', $left, $right))
;
}
diff --git a/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php
b/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php
index 7fbd055..d3518b5 100644
--- a/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php
+++ b/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php
@@ -13,7 +13,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/Binary/In.php
b/twig/twig/lib/Twig/Node/Expression/Binary/In.php
index 788f937..1d485b6 100644
--- a/twig/twig/lib/Twig/Node/Expression/Binary/In.php
+++ b/twig/twig/lib/Twig/Node/Expression/Binary/In.php
@@ -13,7 +13,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php
b/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php
index f347b7b..8f215f1 100644
--- a/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php
+++ b/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php
@@ -13,7 +13,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/Binary/Power.php
b/twig/twig/lib/Twig/Node/Expression/Binary/Power.php
index b2c5904..6cd3a21 100644
--- a/twig/twig/lib/Twig/Node/Expression/Binary/Power.php
+++ b/twig/twig/lib/Twig/Node/Expression/Binary/Power.php
@@ -13,7 +13,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/Binary/Range.php
b/twig/twig/lib/Twig/Node/Expression/Binary/Range.php
index bea4f2a..fc102fe 100644
--- a/twig/twig/lib/Twig/Node/Expression/Binary/Range.php
+++ b/twig/twig/lib/Twig/Node/Expression/Binary/Range.php
@@ -13,7 +13,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php
b/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php
index eb8c107..d2e30d6 100644
--- a/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php
+++ b/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php
@@ -12,12 +12,14 @@
{
public function compile(Twig_Compiler $compiler)
{
+ $left = $compiler->getVarName();
+ $right = $compiler->getVarName();
$compiler
- ->raw('(0 === strpos(')
+ ->raw(sprintf('(is_string($%s = ', $left))
->subcompile($this->getNode('left'))
- ->raw(', ')
+ ->raw(sprintf(') && is_string($%s = ', $right))
->subcompile($this->getNode('right'))
- ->raw('))')
+ ->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s,
$%2$s)))', $left, $right))
;
}
diff --git a/twig/twig/lib/Twig/Node/Expression/BlockReference.php
b/twig/twig/lib/Twig/Node/Expression/BlockReference.php
index 647196e..4ddb2cf 100644
--- a/twig/twig/lib/Twig/Node/Expression/BlockReference.php
+++ b/twig/twig/lib/Twig/Node/Expression/BlockReference.php
@@ -25,7 +25,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php
b/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php
index 00ac670..db06abb 100644
--- a/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php
+++ b/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php
@@ -24,7 +24,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Expression/GetAttr.php
b/twig/twig/lib/Twig/Node/Expression/GetAttr.php
index 55d9fcc..6ce6111 100644
--- a/twig/twig/lib/Twig/Node/Expression/GetAttr.php
+++ b/twig/twig/lib/Twig/Node/Expression/GetAttr.php
@@ -11,7 +11,7 @@
*/
class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
{
- public function __construct(Twig_Node_Expression $node,
Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type,
$lineno)
+ public function __construct(Twig_Node_Expression $node,
Twig_Node_Expression $attribute, Twig_Node_Expression $arguments = null, $type,
$lineno)
{
parent::__construct(array('node' => $node, 'attribute' => $attribute,
'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false,
'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno);
}
@@ -32,20 +32,30 @@
$compiler->raw(', ')->subcompile($this->getNode('attribute'));
- 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'));
+ // only generate optional arguments when needed (to make generated
code more readable)
+ $needFourth = $this->getAttribute('ignore_strict_check');
+ $needThird = $needFourth || $this->getAttribute('is_defined_test');
+ $needSecond = $needThird || Twig_Template::ANY_CALL !==
$this->getAttribute('type');
+ $needFirst = $needSecond || null !== $this->getNode('arguments');
- if (Twig_Template::ANY_CALL !== $this->getAttribute('type') ||
$this->getAttribute('is_defined_test') ||
$this->getAttribute('ignore_strict_check')) {
- $compiler->raw(', ')->repr($this->getAttribute('type'));
+ if ($needFirst) {
+ if (null !== $this->getNode('arguments')) {
+ $compiler->raw(', ')->subcompile($this->getNode('arguments'));
+ } else {
+ $compiler->raw(', array()');
}
+ }
- if ($this->getAttribute('is_defined_test') ||
$this->getAttribute('ignore_strict_check')) {
- $compiler->raw(', '.($this->getAttribute('is_defined_test') ?
'true' : 'false'));
- }
+ if ($needSecond) {
+ $compiler->raw(', ')->repr($this->getAttribute('type'));
+ }
- if ($this->getAttribute('ignore_strict_check')) {
- $compiler->raw(',
'.($this->getAttribute('ignore_strict_check') ? 'true' : 'false'));
- }
+ if ($needThird) {
+ $compiler->raw(', ')->repr($this->getAttribute('is_defined_test'));
+ }
+
+ if ($needFourth) {
+ $compiler->raw(',
')->repr($this->getAttribute('ignore_strict_check'));
}
$compiler->raw(')');
diff --git a/twig/twig/lib/Twig/Node/Expression/Parent.php
b/twig/twig/lib/Twig/Node/Expression/Parent.php
index dcf618c..a22ce03 100644
--- a/twig/twig/lib/Twig/Node/Expression/Parent.php
+++ b/twig/twig/lib/Twig/Node/Expression/Parent.php
@@ -25,7 +25,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Flush.php
b/twig/twig/lib/Twig/Node/Flush.php
index 0467ddc..20d6aab 100644
--- a/twig/twig/lib/Twig/Node/Flush.php
+++ b/twig/twig/lib/Twig/Node/Flush.php
@@ -24,7 +24,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/For.php b/twig/twig/lib/Twig/Node/For.php
index d1ff371..c54a23c 100644
--- a/twig/twig/lib/Twig/Node/For.php
+++ b/twig/twig/lib/Twig/Node/For.php
@@ -33,7 +33,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/ForLoop.php
b/twig/twig/lib/Twig/Node/ForLoop.php
index b884158..d330283 100644
--- a/twig/twig/lib/Twig/Node/ForLoop.php
+++ b/twig/twig/lib/Twig/Node/ForLoop.php
@@ -24,7 +24,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/If.php b/twig/twig/lib/Twig/Node/If.php
index b42d107..980274e 100644
--- a/twig/twig/lib/Twig/Node/If.php
+++ b/twig/twig/lib/Twig/Node/If.php
@@ -25,7 +25,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Import.php
b/twig/twig/lib/Twig/Node/Import.php
index 99efc09..2306655 100644
--- a/twig/twig/lib/Twig/Node/Import.php
+++ b/twig/twig/lib/Twig/Node/Import.php
@@ -24,7 +24,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Include.php
b/twig/twig/lib/Twig/Node/Include.php
index 860aedf..0654888 100644
--- a/twig/twig/lib/Twig/Node/Include.php
+++ b/twig/twig/lib/Twig/Node/Include.php
@@ -25,7 +25,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
@@ -60,40 +60,26 @@
protected function addGetTemplate(Twig_Compiler $compiler)
{
- if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) {
- $compiler
- ->write("\$this->env->loadTemplate(")
- ->subcompile($this->getNode('expr'))
- ->raw(")")
- ;
- } else {
- $compiler
- ->write("\$template = \$this->env->resolveTemplate(")
- ->subcompile($this->getNode('expr'))
- ->raw(");\n")
- ->write('$template')
- ;
- }
+ $method = $this->getNode('expr') instanceof
Twig_Node_Expression_Constant ? 'loadTemplate' : 'resolveTemplate';
+ $compiler
+ ->write(sprintf('$this->env->%s(', $method))
+ ->subcompile($this->getNode('expr'))
+ ->raw(')')
+ ;
}
protected function addTemplateArguments(Twig_Compiler $compiler)
{
- if (false === $this->getAttribute('only')) {
- if (null === $this->getNode('variables')) {
- $compiler->raw('$context');
- } else {
- $compiler
- ->raw('array_merge($context, ')
- ->subcompile($this->getNode('variables'))
- ->raw(')')
- ;
- }
+ if (null === $this->getNode('variables')) {
+ $compiler->raw(false === $this->getAttribute('only') ? '$context'
: 'array()');
+ } elseif (false === $this->getAttribute('only')) {
+ $compiler
+ ->raw('array_merge($context, ')
+ ->subcompile($this->getNode('variables'))
+ ->raw(')')
+ ;
} else {
- if (null === $this->getNode('variables')) {
- $compiler->raw('array()');
- } else {
- $compiler->subcompile($this->getNode('variables'));
- }
+ $compiler->subcompile($this->getNode('variables'));
}
}
}
diff --git a/twig/twig/lib/Twig/Node/Macro.php
b/twig/twig/lib/Twig/Node/Macro.php
index 8991061..ab7e8d2 100644
--- a/twig/twig/lib/Twig/Node/Macro.php
+++ b/twig/twig/lib/Twig/Node/Macro.php
@@ -24,7 +24,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
@@ -37,7 +37,7 @@
$pos = 0;
foreach ($this->getNode('arguments') as $name => $default) {
$compiler
- ->raw('$_'.$name.' = ')
+ ->raw('$__'.$name.'__ = ')
->subcompile($default)
;
@@ -64,7 +64,7 @@
$compiler
->write('')
->string($name)
- ->raw(' => $_'.$name)
+ ->raw(' => $__'.$name.'__')
->raw(",\n")
;
}
diff --git a/twig/twig/lib/Twig/Node/Module.php
b/twig/twig/lib/Twig/Node/Module.php
index 3f80175..9f66b28 100644
--- a/twig/twig/lib/Twig/Node/Module.php
+++ b/twig/twig/lib/Twig/Node/Module.php
@@ -31,7 +31,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Print.php
b/twig/twig/lib/Twig/Node/Print.php
index b0c41d1..4263536 100644
--- a/twig/twig/lib/Twig/Node/Print.php
+++ b/twig/twig/lib/Twig/Node/Print.php
@@ -25,7 +25,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Sandbox.php
b/twig/twig/lib/Twig/Node/Sandbox.php
index 8cf3ed4..8ca772b 100644
--- a/twig/twig/lib/Twig/Node/Sandbox.php
+++ b/twig/twig/lib/Twig/Node/Sandbox.php
@@ -24,7 +24,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/SandboxedModule.php
b/twig/twig/lib/Twig/Node/SandboxedModule.php
index 0de4503..410332c 100644
--- a/twig/twig/lib/Twig/Node/SandboxedModule.php
+++ b/twig/twig/lib/Twig/Node/SandboxedModule.php
@@ -43,17 +43,53 @@
{
parent::compileDisplayFooter($compiler);
+ $tags = $filters = $functions = array();
+ foreach (array('tags', 'filters', 'functions') as $type) {
+ foreach ($this->{'used'.ucfirst($type)} as $name => $node) {
+ if ($node instanceof Twig_Node) {
+ ${$type}[$name] = $node->getLine();
+ } else {
+ ${$type}[$node] = null;
+ }
+ }
+ }
+
$compiler
->write("protected function checkSecurity()\n", "{\n")
->indent()
+ ->write("\$tags = ")->repr(array_filter($tags))->raw(";\n")
+ ->write("\$filters = ")->repr(array_filter($filters))->raw(";\n")
+ ->write("\$functions =
")->repr(array_filter($functions))->raw(";\n\n")
+ ->write("try {\n")
+ ->indent()
->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
->indent()
- ->write(!$this->usedTags ? "array(),\n" : "array('".implode('\',
\'', $this->usedTags)."'),\n")
- ->write(!$this->usedFilters ? "array(),\n" :
"array('".implode('\', \'', $this->usedFilters)."'),\n")
- ->write(!$this->usedFunctions ? "array()\n" :
"array('".implode('\', \'', $this->usedFunctions)."')\n")
+ ->write(!$tags ? "array(),\n" : "array('".implode("', '",
array_keys($tags))."'),\n")
+ ->write(!$filters ? "array(),\n" : "array('".implode("', '",
array_keys($filters))."'),\n")
+ ->write(!$functions ? "array()\n" : "array('".implode("', '",
array_keys($functions))."')\n")
->outdent()
->write(");\n")
->outdent()
+ ->write("} catch (Twig_Sandbox_SecurityError \$e) {\n")
+ ->indent()
+ ->write("\$e->setTemplateFile(\$this->getTemplateName());\n\n")
+ ->write("if (\$e instanceof
Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()]))
{\n")
+ ->indent()
+ ->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n")
+ ->outdent()
+ ->write("} elseif (\$e instanceof
Twig_Sandbox_SecurityNotAllowedFilterError &&
isset(\$filters[\$e->getFilterName()])) {\n")
+ ->indent()
+ ->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n")
+ ->outdent()
+ ->write("} elseif (\$e instanceof
Twig_Sandbox_SecurityNotAllowedFunctionError &&
isset(\$functions[\$e->getFunctionName()])) {\n")
+ ->indent()
+
->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n")
+ ->outdent()
+ ->write("}\n\n")
+ ->write("throw \$e;\n")
+ ->outdent()
+ ->write("}\n")
+ ->outdent()
->write("}\n\n")
;
}
diff --git a/twig/twig/lib/Twig/Node/SandboxedPrint.php
b/twig/twig/lib/Twig/Node/SandboxedPrint.php
index 73dfaa9..91872cc 100644
--- a/twig/twig/lib/Twig/Node/SandboxedPrint.php
+++ b/twig/twig/lib/Twig/Node/SandboxedPrint.php
@@ -29,7 +29,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Set.php b/twig/twig/lib/Twig/Node/Set.php
index 4c9c16c..407d147 100644
--- a/twig/twig/lib/Twig/Node/Set.php
+++ b/twig/twig/lib/Twig/Node/Set.php
@@ -39,7 +39,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Spaceless.php
b/twig/twig/lib/Twig/Node/Spaceless.php
index 7555fa0..1478c59 100644
--- a/twig/twig/lib/Twig/Node/Spaceless.php
+++ b/twig/twig/lib/Twig/Node/Spaceless.php
@@ -26,7 +26,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/Node/Text.php b/twig/twig/lib/Twig/Node/Text.php
index 21bdcea..6863604 100644
--- a/twig/twig/lib/Twig/Node/Text.php
+++ b/twig/twig/lib/Twig/Node/Text.php
@@ -25,7 +25,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
diff --git a/twig/twig/lib/Twig/NodeInterface.php
b/twig/twig/lib/Twig/NodeInterface.php
index 43afd0d..8077349 100644
--- a/twig/twig/lib/Twig/NodeInterface.php
+++ b/twig/twig/lib/Twig/NodeInterface.php
@@ -21,7 +21,7 @@
/**
* Compiles the node to PHP.
*
- * @param Twig_Compiler A Twig_Compiler instance
+ * @param Twig_Compiler $compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler);
diff --git a/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
b/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
index 06f69db..3cc3312 100644
--- a/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
+++ b/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
@@ -28,6 +28,7 @@
const OPTIMIZE_VAR_ACCESS = 8;
protected $loops = array();
+ protected $loopsTargets = array();
protected $optimizers;
protected $prependedNodes = array();
protected $inABody = false;
@@ -174,6 +175,8 @@
// disable the loop variable by default
$node->setAttribute('with_loop', false);
array_unshift($this->loops, $node);
+ array_unshift($this->loopsTargets,
$node->getNode('value_target')->getAttribute('name'));
+ array_unshift($this->loopsTargets,
$node->getNode('key_target')->getAttribute('name'));
} elseif (!$this->loops) {
// we are outside a loop
return;
@@ -183,7 +186,13 @@
// the loop variable is referenced for the current loop
elseif ($node instanceof Twig_Node_Expression_Name && 'loop' ===
$node->getAttribute('name')) {
+ $node->setAttribute('always_defined', true);
$this->addLoopToCurrent();
+ }
+
+ // optimize access to loop targets
+ elseif ($node instanceof Twig_Node_Expression_Name &&
in_array($node->getAttribute('name'), $this->loopsTargets)) {
+ $node->setAttribute('always_defined', true);
}
// block reference
@@ -221,6 +230,8 @@
{
if ($node instanceof Twig_Node_For) {
array_shift($this->loops);
+ array_shift($this->loopsTargets);
+ array_shift($this->loopsTargets);
}
}
diff --git a/twig/twig/lib/Twig/NodeVisitor/Sandbox.php
b/twig/twig/lib/Twig/NodeVisitor/Sandbox.php
index fb27045..e5e3ff6 100644
--- a/twig/twig/lib/Twig/NodeVisitor/Sandbox.php
+++ b/twig/twig/lib/Twig/NodeVisitor/Sandbox.php
@@ -40,18 +40,18 @@
return $node;
} elseif ($this->inAModule) {
// look for tags
- if ($node->getNodeTag()) {
- $this->tags[] = $node->getNodeTag();
+ if ($node->getNodeTag() &&
!isset($this->tags[$node->getNodeTag()])) {
+ $this->tags[$node->getNodeTag()] = $node;
}
// look for filters
- if ($node instanceof Twig_Node_Expression_Filter) {
- $this->filters[] =
$node->getNode('filter')->getAttribute('value');
+ if ($node instanceof Twig_Node_Expression_Filter &&
!isset($this->filters[$node->getNode('filter')->getAttribute('value')])) {
+
$this->filters[$node->getNode('filter')->getAttribute('value')] = $node;
}
// look for functions
- if ($node instanceof Twig_Node_Expression_Function) {
- $this->functions[] = $node->getAttribute('name');
+ if ($node instanceof Twig_Node_Expression_Function &&
!isset($this->functions[$node->getAttribute('name')])) {
+ $this->functions[$node->getAttribute('name')] = $node;
}
// wrap print to check __toString() calls
@@ -76,7 +76,7 @@
if ($node instanceof Twig_Node_Module) {
$this->inAModule = false;
- return new Twig_Node_SandboxedModule($node,
array_unique($this->filters), array_unique($this->tags),
array_unique($this->functions));
+ return new Twig_Node_SandboxedModule($node, $this->filters,
$this->tags, $this->functions);
}
return $node;
diff --git a/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php
b/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php
new file mode 100644
index 0000000..99faba9
--- /dev/null
+++ b/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Exception thrown when a not allowed filter is used in a template.
+ *
+ * @author Martin Hasoň <[email protected]>
+ */
+class Twig_Sandbox_SecurityNotAllowedFilterError extends
Twig_Sandbox_SecurityError
+{
+ private $filterName;
+
+ public function __construct($message, $functionName, $lineno = -1,
$filename = null, Exception $previous = null)
+ {
+ parent::__construct($message, $lineno, $filename, $previous);
+ $this->filterName = $functionName;
+ }
+
+ public function getFilterName()
+ {
+ return $this->filterName;
+ }
+}
diff --git a/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php
b/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php
new file mode 100644
index 0000000..05cf488
--- /dev/null
+++ b/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Exception thrown when a not allowed function is used in a template.
+ *
+ * @author Martin Hasoň <[email protected]>
+ */
+class Twig_Sandbox_SecurityNotAllowedFunctionError extends
Twig_Sandbox_SecurityError
+{
+ private $functionName;
+
+ public function __construct($message, $functionName, $lineno = -1,
$filename = null, Exception $previous = null)
+ {
+ parent::__construct($message, $lineno, $filename, $previous);
+ $this->functionName = $functionName;
+ }
+
+ public function getFunctionName()
+ {
+ return $this->functionName;
+ }
+}
diff --git a/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php
b/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php
new file mode 100644
index 0000000..b3bb5e8
--- /dev/null
+++ b/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Exception thrown when a not allowed tag is used in a template.
+ *
+ * @author Martin Hasoň <[email protected]>
+ */
+class Twig_Sandbox_SecurityNotAllowedTagError extends
Twig_Sandbox_SecurityError
+{
+ private $tagName;
+
+ public function __construct($message, $tagName, $lineno = -1, $filename =
null, Exception $previous = null)
+ {
+ parent::__construct($message, $lineno, $filename, $previous);
+ $this->tagName = $tagName;
+ }
+
+ public function getTagName()
+ {
+ return $this->tagName;
+ }
+}
diff --git a/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php
b/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php
index 66ee233..c4dd03d 100644
--- a/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php
+++ b/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php
@@ -63,19 +63,19 @@
{
foreach ($tags as $tag) {
if (!in_array($tag, $this->allowedTags)) {
- throw new Twig_Sandbox_SecurityError(sprintf('Tag "%s" is not
allowed.', $tag));
+ throw new Twig_Sandbox_SecurityNotAllowedTagError(sprintf('Tag
"%s" is not allowed.', $tag), $tag);
}
}
foreach ($filters as $filter) {
if (!in_array($filter, $this->allowedFilters)) {
- throw new Twig_Sandbox_SecurityError(sprintf('Filter "%s" is
not allowed.', $filter));
+ throw new
Twig_Sandbox_SecurityNotAllowedFilterError(sprintf('Filter "%s" is not
allowed.', $filter), $filter);
}
}
foreach ($functions as $function) {
if (!in_array($function, $this->allowedFunctions)) {
- throw new Twig_Sandbox_SecurityError(sprintf('Function "%s" is
not allowed.', $function));
+ throw new
Twig_Sandbox_SecurityNotAllowedFunctionError(sprintf('Function "%s" is not
allowed.', $function), $function);
}
}
}
diff --git a/twig/twig/lib/Twig/Template.php b/twig/twig/lib/Twig/Template.php
index 1e23e8b..63910da 100644
--- a/twig/twig/lib/Twig/Template.php
+++ b/twig/twig/lib/Twig/Template.php
@@ -379,7 +379,11 @@
} elseif (is_object($object)) {
$message = sprintf('Impossible to access a key "%s" on an
object of class "%s" that does not implement ArrayAccess interface', $item,
get_class($object));
} elseif (is_array($object)) {
- $message = sprintf('Key "%s" for array with keys "%s" does
not exist', $arrayItem, implode(', ', array_keys($object)));
+ if (empty($object)) {
+ $message = sprintf('Key "%s" does not exist as the
array is empty', $arrayItem);
+ } else {
+ $message = sprintf('Key "%s" for array with keys "%s"
does not exist', $arrayItem, implode(', ', array_keys($object)));
+ }
} elseif (Twig_Template::ARRAY_CALL === $type) {
$message = sprintf('Impossible to access a key ("%s") on a
%s variable ("%s")', $item, gettype($object), $object);
} else {
diff --git a/twig/twig/test/Twig/Tests/EnvironmentTest.php
b/twig/twig/test/Twig/Tests/EnvironmentTest.php
index a5fc878..b791e57 100644
--- a/twig/twig/test/Twig/Tests/EnvironmentTest.php
+++ b/twig/twig/test/Twig/Tests/EnvironmentTest.php
@@ -48,7 +48,7 @@
// globals can be added after calling getGlobals
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
- $globals = $twig->getGlobals();
+ $twig->getGlobals();
$twig->addGlobal('foo', 'bar');
$globals = $twig->getGlobals();
$this->assertEquals('bar', $globals['foo']);
@@ -65,7 +65,7 @@
// globals can be modified after extensions init
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
- $globals = $twig->getGlobals();
+ $twig->getGlobals();
$twig->getFunctions();
$twig->addGlobal('foo', 'bar');
$globals = $twig->getGlobals();
@@ -74,7 +74,7 @@
// globals can be modified after extensions and runtime init
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
- $globals = $twig->getGlobals();
+ $twig->getGlobals();
$twig->getFunctions();
$twig->initRuntime();
$twig->addGlobal('foo', 'bar');
diff --git a/twig/twig/test/Twig/Tests/Extension/CoreTest.php
b/twig/twig/test/Twig/Tests/Extension/CoreTest.php
index 5f3da18..b3b1cb0 100644
--- a/twig/twig/test/Twig/Tests/Extension/CoreTest.php
+++ b/twig/twig/test/Twig/Tests/Extension/CoreTest.php
@@ -130,6 +130,24 @@
{
twig_escape_filter(new Twig_Environment(), 'foo', 'bar');
}
+
+ public function testTwigFirst()
+ {
+ $twig = new Twig_Environment();
+ $this->assertEquals('a', twig_first($twig, 'abc'));
+ $this->assertEquals(1, twig_first($twig, array(1, 2, 3)));
+ $this->assertSame('', twig_first($twig, null));
+ $this->assertSame('', twig_first($twig, ''));
+ }
+
+ public function testTwigLast()
+ {
+ $twig = new Twig_Environment();
+ $this->assertEquals('c', twig_last($twig, 'abc'));
+ $this->assertEquals(3, twig_last($twig, array(1, 2, 3)));
+ $this->assertSame('', twig_last($twig, null));
+ $this->assertSame('', twig_last($twig, ''));
+ }
}
function foo_escaper_for_test(Twig_Environment $env, $string, $charset)
diff --git a/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
b/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
index 1022338..fee35a0 100644
--- a/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
+++ b/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
@@ -33,13 +33,13 @@
'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 %}',
+ '1_child' => "{% extends \"1_layout\" %}\n{% block content %}\n{{
\"a\"|json_encode }}\n{% endblock %}",
);
}
/**
* @expectedException Twig_Sandbox_SecurityError
- * @expectedExceptionMessage Filter "json_encode" is not allowed in
"1_child".
+ * @expectedExceptionMessage Filter "json_encode" is not allowed in
"1_child" at line 3.
*/
public function testSandboxWithInheritance()
{
diff --git a/twig/twig/test/Twig/Tests/FileCachingTest.php
b/twig/twig/test/Twig/Tests/FileCachingTest.php
index 8efc948..36cdd33 100644
--- a/twig/twig/test/Twig/Tests/FileCachingTest.php
+++ b/twig/twig/test/Twig/Tests/FileCachingTest.php
@@ -32,7 +32,7 @@
public function testWritingCacheFiles()
{
$name = 'This is just text.';
- $template = $this->env->loadTemplate($name);
+ $this->env->loadTemplate($name);
$cacheFileName = $this->env->getCacheFilename($name);
$this->assertTrue(file_exists($cacheFileName), 'Cache file does not
exist.');
@@ -42,7 +42,7 @@
public function testClearingCacheFiles()
{
$name = 'I will be deleted.';
- $template = $this->env->loadTemplate($name);
+ $this->env->loadTemplate($name);
$cacheFileName = $this->env->getCacheFilename($name);
$this->assertTrue(file_exists($cacheFileName), 'Cache file does not
exist.');
diff --git a/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_trait.test
b/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_trait.test
index 026bd52..6679fbe 100644
--- a/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_trait.test
+++ b/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_trait.test
@@ -6,4 +6,4 @@
{% block bar %}
{% endblock %}
--EXCEPTION--
-Twig_Error_Runtime: Block "foobar" is not defined in trait "foo" in
"index.twig".
+Twig_Error_Runtime: Block "foobar" is not defined in trait "foo" in
"index.twig" at line 2.
diff --git a/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test
b/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test
index d259d11..9ad5e5e 100644
--- a/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test
+++ b/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test
@@ -4,9 +4,23 @@
{{ 'foo' ends with 'o' ? 'OK' : 'KO' }}
{{ not ('foo' ends with 'f') ? 'OK' : 'KO' }}
{{ not ('foo' ends with 'foowaytoolong') ? 'OK' : 'KO' }}
+{{ 'foo' ends with '' ? 'OK' : 'KO' }}
+{{ '1' ends with true ? 'OK' : 'KO' }}
+{{ 1 ends with true ? 'OK' : 'KO' }}
+{{ 0 ends with false ? 'OK' : 'KO' }}
+{{ '' ends with false ? 'OK' : 'KO' }}
+{{ false ends with false ? 'OK' : 'KO' }}
+{{ false ends with '' ? 'OK' : 'KO' }}
--DATA--
return array()
--EXPECT--
OK
OK
OK
+OK
+KO
+KO
+KO
+KO
+KO
+KO
diff --git a/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test
b/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test
index 1ae4f86..75d331e 100644
--- a/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test
+++ b/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test
@@ -7,6 +7,11 @@
{{ 'foo' starts with 'f' ? 'OK' : 'KO' }}
{{ 'foo' starts
with 'f' ? 'OK' : 'KO' }}
+{{ 'foo' starts with '' ? 'OK' : 'KO' }}
+{{ '1' starts with true ? 'OK' : 'KO' }}
+{{ '' starts with false ? 'OK' : 'KO' }}
+{{ 'a' starts with false ? 'OK' : 'KO' }}
+{{ false starts with '' ? 'OK' : 'KO' }}
--DATA--
return array()
--EXPECT--
@@ -15,3 +20,8 @@
OK
OK
OK
+OK
+KO
+KO
+KO
+KO
diff --git a/twig/twig/test/Twig/Tests/Fixtures/filters/date.test
b/twig/twig/test/Twig/Tests/Fixtures/filters/date.test
index d40bb04..d17e5e2 100644
--- a/twig/twig/test/Twig/Tests/Fixtures/filters/date.test
+++ b/twig/twig/test/Twig/Tests/Fixtures/filters/date.test
@@ -31,6 +31,13 @@
{{ date6|date('e', false) }}
{{ date7|date }}
+{{ date7|date(timezone='Europe/Paris') }}
+{{ date7|date(timezone='Asia/Hong_Kong') }}
+{{ date7|date(timezone=false) }}
+{{ date7|date(timezone='Indian/Mauritius') }}
+
+{{ '2010-01-28 15:00:00'|date(timezone="Europe/Paris") }}
+{{ '2010-01-28 15:00:00'|date(timezone="Asia/Hong_Kong") }}
--DATA--
date_default_timezone_set('Europe/Paris');
return array(
@@ -40,7 +47,7 @@
'date4' => 1286199900, // DateTime::createFromFormat('Y-m-d H:i',
'2010-10-04 13:45', new DateTimeZone('UTC'))->getTimestamp() -- A unixtimestamp
is always GMT
'date5' => -189291360, // DateTime::createFromFormat('Y-m-d H:i',
'1964-01-02 03:04', new DateTimeZone('UTC'))->getTimestamp(),
'date6' => new DateTime('2010-10-04 13:45', new
DateTimeZone('America/New_York')),
- 'date7' => '2010-01-28T15:00:00+05:00',
+ 'date7' => '2010-01-28T15:00:00+04:00',
'timezone1' => new DateTimeZone('America/New_York'),
)
--EXPECT--
@@ -73,4 +80,11 @@
Europe/Paris
America/New_York
-January 28, 2010 11:00
+January 28, 2010 12:00
+January 28, 2010 12:00
+January 28, 2010 19:00
+January 28, 2010 15:00
+January 28, 2010 15:00
+
+January 28, 2010 15:00
+January 28, 2010 22:00
diff --git a/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test
b/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test
index b89ceb3..4e18325 100644
--- a/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test
+++ b/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test
@@ -8,6 +8,7 @@
{{ 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') }}
+{{ date1|date_modify('+1 hour')|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') }}
@@ -27,6 +28,7 @@
04/10/2010 19:45:00
04/10/2010 07:45:00
04/10/2010 13:45:00
+04/10/2010 14:45:00
04/10/2010 19:45:00 +02:00
05/10/2010 01:45:00 +08:00
diff --git a/twig/twig/test/Twig/Tests/Fixtures/filters/slice.test
b/twig/twig/test/Twig/Tests/Fixtures/filters/slice.test
index b37ad65..fb36a4e 100644
--- a/twig/twig/test/Twig/Tests/Fixtures/filters/slice.test
+++ b/twig/twig/test/Twig/Tests/Fixtures/filters/slice.test
@@ -19,6 +19,9 @@
{{ '1234'|slice(1) }}
{{ '1234'[1:] }}
{{ '1234'[:1] }}
+
+{{ arr|slice(3)|join('') }}
+{{ arr[2:]|join('') }}
--DATA--
return array('start' => 1, 'length' => 2, 'arr' => new ArrayObject(array(1, 2,
3, 4)))
--EXPECT--
@@ -40,3 +43,6 @@
234
234
1
+
+4
+34
\ No newline at end of file
diff --git a/twig/twig/test/Twig/Tests/Fixtures/filters/split.test
b/twig/twig/test/Twig/Tests/Fixtures/filters/split.test
index ce8ec9c..a093ed7 100644
--- a/twig/twig/test/Twig/Tests/Fixtures/filters/split.test
+++ b/twig/twig/test/Twig/Tests/Fixtures/filters/split.test
@@ -5,6 +5,7 @@
{{ foo|split(',')|join('-') }}
{{ foo|split(',', 3)|join('-') }}
{{ baz|split('')|join('-') }}
+{{ baz|split('', 1)|join('-') }}
{{ baz|split('', 2)|join('-') }}
{{ foo|split(',', -2)|join('-') }}
--DATA--
@@ -14,5 +15,6 @@
one-two-three-four-five
one-two-three,four,five
1-2-3-4-5
+1-2-3-4-5
12-34-5
one-two-three
\ No newline at end of file
diff --git a/twig/twig/test/Twig/Tests/Fixtures/filters/split_utf8.test
b/twig/twig/test/Twig/Tests/Fixtures/filters/split_utf8.test
new file mode 100644
index 0000000..305e162
--- /dev/null
+++ b/twig/twig/test/Twig/Tests/Fixtures/filters/split_utf8.test
@@ -0,0 +1,24 @@
+--TEST--
+"split" filter
+--CONDITION--
+function_exists('mb_get_info')
+--TEMPLATE--
+{{ "é"|split('', 10)|join('-') }}
+{{ foo|split(',')|join('-') }}
+{{ foo|split(',', 1)|join('-') }}
+{{ foo|split(',', 2)|join('-') }}
+{{ foo|split(',', 3)|join('-') }}
+{{ baz|split('')|join('-') }}
+{{ baz|split('', 1)|join('-') }}
+{{ baz|split('', 2)|join('-') }}
+--DATA--
+return array('foo' => 'Ä,é,Äほ', 'baz' => 'éÄßごa',)
+--EXPECT--
+é
+Ä-é-Äほ
+Ä,é,Äほ
+Ä-é,Äほ
+Ä-é-Äほ
+é-Ä-ß-ご-a
+é-Ä-ß-ご-a
+éÄ-ßご-a
\ No newline at end of file
diff --git a/twig/twig/test/Twig/Tests/Fixtures/functions/attribute.test
b/twig/twig/test/Twig/Tests/Fixtures/functions/attribute.test
index 472b74d..71b2038 100644
--- a/twig/twig/test/Twig/Tests/Fixtures/functions/attribute.test
+++ b/twig/twig/test/Twig/Tests/Fixtures/functions/attribute.test
@@ -4,13 +4,15 @@
{{ attribute(obj, method) }}
{{ attribute(array, item) }}
{{ attribute(obj, "bar", ["a", "b"]) }}
+{{ attribute(obj, "bar", arguments) }}
{{ attribute(obj, method) is defined ? 'ok' : 'ko' }}
{{ attribute(obj, nonmethod) is defined ? 'ok' : 'ko' }}
--DATA--
-return array('obj' => new TwigTestFoo(), 'method' => 'foo', 'array' =>
array('foo' => 'bar'), 'item' => 'foo', 'nonmethod' => 'xxx')
+return array('obj' => new TwigTestFoo(), 'method' => 'foo', 'array' =>
array('foo' => 'bar'), 'item' => 'foo', 'nonmethod' => 'xxx', 'arguments' =>
array('a', 'b'))
--EXPECT--
foo
bar
bar_a-b
+bar_a-b
ok
ko
diff --git a/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test
b/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test
index 788a2ab..7b9ccac 100644
--- a/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test
+++ b/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test
@@ -3,8 +3,11 @@
--TEMPLATE--
{{ include("foo.twig", sandboxed = true) }}
--TEMPLATE(foo.twig)--
+
+
+{{ foo|e }}
{{ foo|e }}
--DATA--
return array()
--EXCEPTION--
-Twig_Sandbox_SecurityError: Filter "e" is not allowed in "index.twig" at line
2.
+Twig_Sandbox_SecurityNotAllowedFilterError: Filter "e" is not allowed in
"foo.twig" at line 4.
diff --git
a/twig/twig/test/Twig/Tests/Fixtures/regression/combined_debug_info.test
b/twig/twig/test/Twig/Tests/Fixtures/regression/combined_debug_info.test
new file mode 100644
index 0000000..df48578
--- /dev/null
+++ b/twig/twig/test/Twig/Tests/Fixtures/regression/combined_debug_info.test
@@ -0,0 +1,15 @@
+--TEST--
+Exception with bad line number
+--TEMPLATE--
+{% block content %}
+ {{ foo }}
+ {{ include("foo") }}
+{% endblock %}
+index
+--TEMPLATE(foo)--
+foo
+{{ foo.bar }}
+--DATA--
+return array('foo' => 'foo');
+--EXCEPTION--
+Twig_Error_Runtime: Impossible to access an attribute ("bar") on a string
variable ("foo") in "foo" at line 3
diff --git
a/twig/twig/test/Twig/Tests/Fixtures/regression/multi_word_tests.test
b/twig/twig/test/Twig/Tests/Fixtures/regression/multi_word_tests.test
new file mode 100644
index 0000000..269a305
--- /dev/null
+++ b/twig/twig/test/Twig/Tests/Fixtures/regression/multi_word_tests.test
@@ -0,0 +1,10 @@
+--TEST--
+Twig allows multi-word tests without a custom node class
+--TEMPLATE--
+{{ 'foo' is multi word ? 'yes' : 'no' }}
+{{ 'foo bar' is multi word ? 'yes' : 'no' }}
+--DATA--
+return array()
+--EXPECT--
+no
+yes
diff --git a/twig/twig/test/Twig/Tests/Fixtures/tags/macro/super_globals.test
b/twig/twig/test/Twig/Tests/Fixtures/tags/macro/super_globals.test
new file mode 100644
index 0000000..5679462
--- /dev/null
+++ b/twig/twig/test/Twig/Tests/Fixtures/tags/macro/super_globals.test
@@ -0,0 +1,14 @@
+--TEST--
+Super globals as macro arguments
+--TEMPLATE--
+{% import _self as macros %}
+
+{{ macros.foo('foo') }}
+
+{% macro foo(GET) %}
+ {{ GET }}
+{% endmacro %}
+--DATA--
+return array()
+--EXPECT--
+foo
diff --git a/twig/twig/test/Twig/Tests/IntegrationTest.php
b/twig/twig/test/Twig/Tests/IntegrationTest.php
index ea00b02..70f9b80 100644
--- a/twig/twig/test/Twig/Tests/IntegrationTest.php
+++ b/twig/twig/test/Twig/Tests/IntegrationTest.php
@@ -157,6 +157,13 @@
);
}
+ public function getTests()
+ {
+ return array(
+ new Twig_SimpleTest('multi word', array($this, 'is_multi_word')),
+ );
+ }
+
public function §Filter($value)
{
return "§{$value}§";
@@ -210,6 +217,11 @@
return '<br />';
}
+ public function is_multi_word($value)
+ {
+ return false !== strpos($value, ' ');
+ }
+
public function getName()
{
return 'integration_test';
diff --git a/twig/twig/test/Twig/Tests/LexerTest.php
b/twig/twig/test/Twig/Tests/LexerTest.php
index ab104f4..c4d7083 100644
--- a/twig/twig/test/Twig/Tests/LexerTest.php
+++ b/twig/twig/test/Twig/Tests/LexerTest.php
@@ -46,7 +46,6 @@
$stream = $lexer->tokenize($template);
$count = 0;
- $tokens = array();
while (!$stream->isEOF()) {
$token = $stream->next();
if ($type === $token->getType()) {
@@ -114,7 +113,7 @@
$template = '{% raw %}'.str_repeat('*', 100000).'{% endraw %}';
$lexer = new Twig_Lexer(new Twig_Environment());
- $stream = $lexer->tokenize($template);
+ $lexer->tokenize($template);
// should not throw an exception
}
@@ -124,7 +123,7 @@
$template = '{{ '.str_repeat('x', 100000).' }}';
$lexer = new Twig_Lexer(new Twig_Environment());
- $stream = $lexer->tokenize($template);
+ $lexer->tokenize($template);
// should not throw an exception
}
@@ -134,17 +133,13 @@
$template = '{% '.str_repeat('x', 100000).' %}';
$lexer = new Twig_Lexer(new Twig_Environment());
- $stream = $lexer->tokenize($template);
+ $lexer->tokenize($template);
// should not throw an exception
}
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());
@@ -216,7 +211,7 @@
$template = '{{ "bar #{x" }}';
$lexer = new Twig_Lexer(new Twig_Environment());
- $stream = $lexer->tokenize($template);
+ $lexer->tokenize($template);
}
public function testStringWithNestedInterpolations()
@@ -281,7 +276,7 @@
';
$lexer = new Twig_Lexer(new Twig_Environment());
- $stream = $lexer->tokenize($template);
+ $lexer->tokenize($template);
}
/**
@@ -300,6 +295,6 @@
';
$lexer = new Twig_Lexer(new Twig_Environment());
- $stream = $lexer->tokenize($template);
+ $lexer->tokenize($template);
}
}
diff --git a/twig/twig/test/Twig/Tests/NativeExtensionTest.php
b/twig/twig/test/Twig/Tests/NativeExtensionTest.php
index 9519bdf..7de268c 100644
--- a/twig/twig/test/Twig/Tests/NativeExtensionTest.php
+++ b/twig/twig/test/Twig/Tests/NativeExtensionTest.php
@@ -23,7 +23,7 @@
$d2 = new DateTime();
$output = $twig->render('{{ d1.date }}{{ d2.date }}', compact('d1',
'd2'));
- if ('hiphop' === substr(PHP_VERSION, -6)) {
+ if (defined('HHVM_VERSION')) {
$this->markTestSkipped('Skip under HHVM as the behavior is not the
same as plain PHP (which is an edge case anyway)');
}
diff --git a/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php
b/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php
index 62fb0d3..76cf5c6 100644
--- a/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php
+++ b/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php
@@ -46,7 +46,7 @@
$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_Template::ANY_CALL, 1);
- $tests[] = array($node, sprintf('%s%s, "bar")',
$this->getAttributeGetter(), $this->getVariableGetter('foo')));
+ $tests[] = array($node, sprintf('%s%s, "bar", array())',
$this->getAttributeGetter(), $this->getVariableGetter('foo')));
$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')));
diff --git a/twig/twig/test/Twig/Tests/Node/IncludeTest.php
b/twig/twig/test/Twig/Tests/Node/IncludeTest.php
index e8aa326..9afecef 100644
--- a/twig/twig/test/Twig/Tests/Node/IncludeTest.php
+++ b/twig/twig/test/Twig/Tests/Node/IncludeTest.php
@@ -59,8 +59,7 @@
$node = new Twig_Node_Include($expr, null, false, false, 1);
$tests[] = array($node, <<<EOF
// line 1
-\$template = \$this->env->resolveTemplate(((true) ? ("foo") : ("foo")));
-\$template->display(\$context);
+\$this->env->resolveTemplate(((true) ? ("foo") : ("foo")))->display(\$context);
EOF
);
diff --git a/twig/twig/test/Twig/Tests/Node/MacroTest.php
b/twig/twig/test/Twig/Tests/Node/MacroTest.php
index 4d2f641..2a77ac7 100644
--- a/twig/twig/test/Twig/Tests/Node/MacroTest.php
+++ b/twig/twig/test/Twig/Tests/Node/MacroTest.php
@@ -46,11 +46,11 @@
return array(
array($node, <<<EOF
// line 1
-public function getfoo(\$_foo = null, \$_bar = "Foo")
+public function getfoo(\$__foo__ = null, \$__bar__ = "Foo")
{
\$context = \$this->env->mergeGlobals(array(
- "foo" => \$_foo,
- "bar" => \$_bar,
+ "foo" => \$__foo__,
+ "bar" => \$__bar__,
));
\$blocks = array();
diff --git a/twig/twig/test/Twig/Tests/Node/SandboxedModuleTest.php
b/twig/twig/test/Twig/Tests/Node/SandboxedModuleTest.php
index 421f210..bb9ffb7 100644
--- a/twig/twig/test/Twig/Tests/Node/SandboxedModuleTest.php
+++ b/twig/twig/test/Twig/Tests/Node/SandboxedModuleTest.php
@@ -84,11 +84,29 @@
protected function checkSecurity()
{
- \$this->env->getExtension('sandbox')->checkSecurity(
- array('upper'),
- array('for'),
- array('cycle')
- );
+ \$tags = array();
+ \$filters = array();
+ \$functions = array();
+
+ try {
+ \$this->env->getExtension('sandbox')->checkSecurity(
+ array('upper'),
+ array('for'),
+ array('cycle')
+ );
+ } catch (Twig_Sandbox_SecurityError \$e) {
+ \$e->setTemplateFile(\$this->getTemplateName());
+
+ if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError &&
isset(\$tags[\$e->getTagName()])) {
+ \$e->setTemplateLine(\$tags[\$e->getTagName()]);
+ } elseif (\$e instanceof
Twig_Sandbox_SecurityNotAllowedFilterError &&
isset(\$filters[\$e->getFilterName()])) {
+ \$e->setTemplateLine(\$filters[\$e->getFilterName()]);
+ } elseif (\$e instanceof
Twig_Sandbox_SecurityNotAllowedFunctionError &&
isset(\$functions[\$e->getFunctionName()])) {
+ \$e->setTemplateLine(\$functions[\$e->getFunctionName()]);
+ }
+
+ throw \$e;
+ }
}
public function getTemplateName()
@@ -143,11 +161,29 @@
protected function checkSecurity()
{
- \$this->env->getExtension('sandbox')->checkSecurity(
- array('upper'),
- array('for'),
- array('cycle')
- );
+ \$tags = array();
+ \$filters = array();
+ \$functions = array();
+
+ try {
+ \$this->env->getExtension('sandbox')->checkSecurity(
+ array('upper'),
+ array('for'),
+ array('cycle')
+ );
+ } catch (Twig_Sandbox_SecurityError \$e) {
+ \$e->setTemplateFile(\$this->getTemplateName());
+
+ if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError &&
isset(\$tags[\$e->getTagName()])) {
+ \$e->setTemplateLine(\$tags[\$e->getTagName()]);
+ } elseif (\$e instanceof
Twig_Sandbox_SecurityNotAllowedFilterError &&
isset(\$filters[\$e->getFilterName()])) {
+ \$e->setTemplateLine(\$filters[\$e->getFilterName()]);
+ } elseif (\$e instanceof
Twig_Sandbox_SecurityNotAllowedFunctionError &&
isset(\$functions[\$e->getFunctionName()])) {
+ \$e->setTemplateLine(\$functions[\$e->getFunctionName()]);
+ }
+
+ throw \$e;
+ }
}
public function getTemplateName()
diff --git a/twig/twig/test/Twig/Tests/TemplateTest.php
b/twig/twig/test/Twig/Tests/TemplateTest.php
index b6f5a67..e2f84ee 100644
--- a/twig/twig/test/Twig/Tests/TemplateTest.php
+++ b/twig/twig/test/Twig/Tests/TemplateTest.php
@@ -28,6 +28,7 @@
$context = array(
'string' => 'foo',
+ 'empty_array' => array(),
'array' => array('foo' => 'foo'),
'array_access' => new Twig_TemplateArrayAccessObject(),
'magic_exception' => new
Twig_TemplateMagicPropertyObjectWithException(),
@@ -46,10 +47,12 @@
{
$tests = array(
array('{{ string["a"] }}', 'Impossible to access a key ("a") on a
string variable ("foo") in "%s" at line 1', false),
+ array('{{ empty_array["a"] }}', 'Key "a" does not exist as the
array is empty 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 class "Twig_TemplateArrayAccessObject" 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('{{ empty_array.a }}', 'Key "a" does not exist as the array
is empty 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),
@@ -368,7 +371,7 @@
$tests = array_merge($tests, array(
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'),
+ array(false, null, array(), 'a', array(), $anyType, false, 'Key
"a" does not exist as the array is empty'),
));
// add twig_template_get_attributes tests
diff --git a/twig/twig/test/Twig/Tests/escapingTest.php
b/twig/twig/test/Twig/Tests/escapingTest.php
index 34d2a2d..d581315 100644
--- a/twig/twig/test/Twig/Tests/escapingTest.php
+++ b/twig/twig/test/Twig/Tests/escapingTest.php
@@ -227,7 +227,7 @@
/**
* Convert a Unicode Codepoint to a literal UTF-8 character.
*
- * @param int Unicode codepoint in hex notation
+ * @param int $codepoint Unicode codepoint in hex notation
* @return string UTF-8 literal string
*/
protected function codepointToUtf8($codepoint)
@@ -301,7 +301,7 @@
public function testCssEscapingEscapesOwaspRecommendedRanges()
{
- $immune = array(); // CSS has no exceptions to escaping ranges
+ // CSS has no exceptions to escaping ranges
for ($chr=0; $chr < 0xFF; $chr++) {
if ($chr >= 0x30 && $chr <= 0x39
|| $chr >= 0x41 && $chr <= 0x5A
--
To view, visit https://gerrit.wikimedia.org/r/178396
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia9ce422c57cf893c4971de2c8b4d51858be846fe
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/fundraising/crm/vendor
Gerrit-Branch: master
Gerrit-Owner: Awight <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits