Merge branch '1.x' into 2.x

* 1.x:
  updated CHANGELOG
  Call clearstatcache() before calling is_dir().
  bumped version to 1.33
  fixed CHANGELOG
  Make "length" filter and "empty" test consider __toString [Twig 1.x]
This commit is contained in:
Fabien Potencier
2017-03-22 08:12:17 -07:00
10 changed files with 152 additions and 43 deletions
+12 -2
View File
@@ -1,5 +1,10 @@
* 2.2.1 (2017-XX-XX)
* 2.3.0 (2017-XX-XX)
* fixed a race condition handling when writing cache files
* "length" filter now returns string length when applied to an object that does
not implement \Countable but provides __toString()
* "empty" test will now consider the return value of the __toString() method for
objects implement __toString() but not \Countable
* fixed JS escaping for unicode characters with higher code points
* added error message when calling `parent()` in a block that doesn't exist in the parent template
@@ -34,8 +39,13 @@
* improved the performance of the filesystem loader
* removed features that were deprecated in 1.x
* 1.32.1 (2017-XX-XX)
* 1.33.0 (2017-XX-XX)
* fixed a race condition handling when writing cache files
* "length" filter now returns string length when applied to an object that does
not implement \Countable but provides __toString()
* "empty" test will now consider the return value of the __toString() method for
objects implement __toString() but not \Countable
* fixed JS escaping for unicode characters with higher code points
* 1.32.0 (2017-02-26)
+1 -1
View File
@@ -47,7 +47,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
"dev-master": "2.3-dev"
}
}
}
+11 -1
View File
@@ -1,8 +1,18 @@
``length``
==========
.. versionadded:: 2.3
Support for the ``__toString()`` magic method has been added in Twig 2.3.
The ``length`` filter returns the number of items of a sequence or mapping, or
the length of a string:
the length of a string.
For objects that implement the ``Countable`` interface, ``length`` will use the
return value of the ``count()`` method.
For objects that implement the ``__toString()`` magic method (and not ``Countable``),
it will return the length of the string provided by that method.
.. code-block:: jinja
+12 -1
View File
@@ -1,11 +1,22 @@
``empty``
=========
.. versionadded:: 2.3
Support for the ``__toString()`` magic method has been added in Twig 2.3.
``empty`` checks if a variable is an empty string, an empty array, an empty
hash, exactly ``false``, or exactly ``null``:
hash, exactly ``false``, or exactly ``null``.
For objects that implement the ``Countable`` interface, ``empty`` will check the
return value of the ``count()`` method.
For objects that implement the ``__toString()`` magic method (and not ``Countable``),
it will check if an empty string is returned.
.. code-block:: jinja
{% if foo is empty %}
...
{% endif %}
+5 -2
View File
@@ -49,8 +49,11 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
{
$dir = dirname($key);
if (!is_dir($dir)) {
if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
if (false === @mkdir($dir, 0777, true)) {
clearstatcache(true, $dir);
if (!is_dir($dir)) {
throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
}
}
} elseif (!is_writable($dir)) {
throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir));
+4 -4
View File
@@ -16,11 +16,11 @@
*/
class Twig_Environment
{
const VERSION = '2.2.1';
const VERSION_ID = 20201;
const VERSION = '2.3.0';
const VERSION_ID = 20300;
const MAJOR_VERSION = 2;
const MINOR_VERSION = 2;
const RELEASE_VERSION = 1;
const MINOR_VERSION = 3;
const RELEASE_VERSION = 0;
const EXTRA_VERSION = 'DEV';
private $charset;
+13 -1
View File
@@ -1144,7 +1144,15 @@ function twig_convert_encoding($string, $to, $from)
*/
function twig_length_filter(Twig_Environment $env, $thing)
{
return is_scalar($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing);
if (is_scalar($thing)) {
return mb_strlen($thing, $env->getCharset());
}
if (method_exists($thing, '__toString') && !$thing instanceof \Countable) {
return mb_strlen((string) $thing, $env->getCharset());
}
return count($thing);
}
/**
@@ -1233,6 +1241,10 @@ function twig_test_empty($value)
return 0 == count($value);
}
if (method_exists($value, '__toString')) {
return '' === (string) $value;
}
return '' === $value || false === $value || null === $value || array() === $value;
}
+14 -3
View File
@@ -4,11 +4,22 @@
{{ array|length }}
{{ string|length }}
{{ number|length }}
{{ markup|length }}
{{ to_string_able|length }}
{{ countable|length }}
{{ magic|length }}
--DATA--
return array('array' => array(1, 4), 'string' => 'foo', 'number' => 1000, 'markup' => new Twig_Markup('foo', 'UTF-8'))
return array(
'array' => array(1, 4),
'string' => 'foo',
'number' => 1000,
'to_string_able' => new ToStringStub('foobar'),
'countable' => new CountableStub(42), /* also asserts we do *not* call __toString() */
'magic' => new MagicCallStub(), /* used to assert we do *not* call __call */
);
--EXPECT--
2
3
4
3
6
42
1
+25 -28
View File
@@ -1,35 +1,28 @@
--TEST--
"empty" test
--TEMPLATE--
{{ foo is empty ? 'ok' : 'ko' }}
{{ bar is empty ? 'ok' : 'ko' }}
{{ foobar is empty ? 'ok' : 'ko' }}
{{ array is empty ? 'ok' : 'ko' }}
{{ zero is empty ? 'ok' : 'ko' }}
{{ string is empty ? 'ok' : 'ko' }}
{{ string_empty is empty ? 'ok' : 'ko' }}
{{ string_zero is empty ? 'ko' : 'ok' }}
{{ value_null is empty ? 'ok' : 'ko' }}
{{ value_false is empty ? 'ok' : 'ko' }}
{{ value_int_zero is empty ? 'ko' : 'ok' }}
{{ array_empty is empty ? 'ok' : 'ko' }}
{{ array_not_empty is empty ? 'ko' : 'ok' }}
{{ magically_callable is empty ? 'ko' : 'ok' }}
{{ countable_empty is empty ? 'ok' : 'ko' }}
{{ countable_not_empty is empty ? 'ok' : 'ko' }}
{{ countable_not_empty is empty ? 'ko' : 'ok' }}
{{ tostring_empty is empty ? 'ok' : 'ko' }}
{{ tostring_not_empty is empty ? 'ko' : 'ok' }}
{{ markup_empty is empty ? 'ok' : 'ko' }}
{{ markup_not_empty is empty ? 'ok' : 'ko' }}
{{ markup_not_empty is empty ? 'ko' : 'ok' }}
--DATA--
class CountableStub implements Countable
{
private $items;
public function __construct(array $items)
{
$this->items = $items;
}
public function count()
{
return count($this->items);
}
}
return array(
'foo' => '', 'bar' => null, 'foobar' => false, 'array' => array(), 'zero' => 0, 'string' => '0',
'string_empty' => '', 'string_zero' => '0',
'value_null' => null, 'value_false' => false, 'value_int_zero' => 0,
'array_empty' => array(), 'array_not_empty' => array(1, 2),
'magically_callable' => new MagicCallStub(),
'countable_empty' => new CountableStub(array()), 'countable_not_empty' => new CountableStub(array(1, 2)),
'tostring_empty' => new ToStringStub(''), 'tostring_not_empty' => new ToStringStub('0' /* edge case of using "0" as the string */),
'markup_empty' => new Twig_Markup('', 'UTF-8'), 'markup_not_empty' => new Twig_Markup('test', 'UTF-8'),
);
--EXPECT--
@@ -37,9 +30,13 @@ ok
ok
ok
ok
ko
ko
ok
ko
ok
ko
ok
ok
ok
ok
ok
ok
ok
ok
+55
View File
@@ -254,3 +254,58 @@ class TwigTestExtension extends Twig_Extension
return 'static_magic_'.$arguments[0];
}
}
/**
* This class is used in tests for the "length" filter and "empty" test. It asserts that __call is not
* used to convert such objects to strings.
*/
class MagicCallStub
{
public function __call($name, $args)
{
throw new Exception('__call shall not be called');
}
}
class ToStringStub
{
/**
* @var string
*/
private $string;
public function __construct($string)
{
$this->string = $string;
}
public function __toString()
{
return $this->string;
}
}
/**
* This class is used in tests for the length filter and empty test to show
* that when \Countable is implemented, it is preferred over the __toString()
* method.
*/
class CountableStub implements \Countable
{
private $count;
public function __construct($count)
{
$this->count = $count;
}
public function count()
{
return $this->count;
}
public function __toString()
{
throw new Exception('__toString shall not be called on \Countables');
}
}