bug #1855 Fix custom escaper null values (moufmouf)

This PR was squashed before being merged into the 1.x branch (closes #1855).

Discussion
----------

Fix custom escaper null values

First, a bit of context:

About 10 years ago, when I was doing some Java, I used to use a SQL mapper called iBatis (now moved to myBatis here: http://mybatis.github.io/mybatis-3/dynamic-sql.html)
The whole concept is to put SQL requests in XML files and use XML as a templating engine. Here is a code sample:

```xml
  SELECT * FROM BLOG
  WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
```

Fast forward today. I just realized Twig could be a great tool to do exactly the same. Just imagine:

```SQL
  SELECT * FROM BLOG
  WHERE state = ‘ACTIVE’
  {% if title %}
    AND title like {{ title }}
  {% endif %}
```

All I need to do is write a custom escaper. Like this one:

```php
$twig->getExtension('core')->setEscaper('sql', function(\Twig_Environment $env, $string, $charset) use ($connection) {
    // $connection is a DBAL connection
    return $connection->quote($string);
});
```

Now, here is my problem:

For an SQL escaper to work, I would need *null* to translate into the 'NULL' string.

But in Twig, escapers are not triggered for null or numeric values. This is due to these lines of code: https://github.com/twigphp/Twig/blob/1.x/lib/Twig/Extension/Core.php#L1021-L1027

```php
if (!is_string($string)) {
    if (is_object($string) && method_exists($string, '__toString')) {
        $string = (string) $string;
    } else {
        return $string;
    }
}
```

Everything that is not a string (i.e. a numeric value, null, an array...) is directly returned and completely bypasses the escaper.

I understand that this behaviour is ok in most cases (html, js, css, url, etc...), and that it allows some degree of optimisation, but it prevents from working on more specific escapers like a SQL escaper. It is also an undocumented behaviour of custom escapers.

This pull request tries to fix this without impacting performance.

In most Twig installations, no custom escapers are used. In this cases, returning early is a good idea since all default escapers share the same behaviour.
If there is a custom escaper configured however, I'm going the "long" route to be sure that the custom escaper is fed with all values (and not only non empty strings)

Commits
-------

6f84981 Fix custom escaper null values
This commit is contained in:
Fabien Potencier
2015-09-30 14:05:09 +02:00
2 changed files with 3 additions and 1 deletions
+1 -1
View File
@@ -1021,7 +1021,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
if (!is_string($string)) {
if (is_object($string) && method_exists($string, '__toString')) {
$string = (string) $string;
} else {
} elseif (in_array($strategy, array('html', 'js', 'css', 'html_attr', 'url'))) {
return $string;
}
}
+2
View File
@@ -121,6 +121,8 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
$twig->getExtension('core')->setEscaper('foo', 'foo_escaper_for_test');
$this->assertEquals('fooUTF-8', twig_escape_filter($twig, 'foo', 'foo'));
$this->assertEquals('UTF-8', twig_escape_filter($twig, null, 'foo'));
$this->assertEquals('42UTF-8', twig_escape_filter($twig, 42, 'foo'));
}
/**