Merge branch '1.x'

* 1.x:
  updated CHANGELOG
  Fix variable names for the deprecation triggering code
  Mark test skipped if cannot write to cache directory.
This commit is contained in:
Fabien Potencier
2015-09-06 08:47:52 +02:00
9 changed files with 74 additions and 17 deletions
+2 -1
View File
@@ -15,7 +15,8 @@
* 1.21.2 (2015-XX-XX)
* n/a
* added Traversable support for replace, merge, and sort
* deprecated support for character by character replacement for the "replace" filter
* 1.21.1 (2015-08-26)
+2 -1
View File
@@ -42,6 +42,7 @@ overridden.
.. note::
Internally, Twig uses the PHP `array_merge`_ function.
Internally, Twig uses the PHP `array_merge`_ function. It supports
Traversable objects by transforming those to arrays.
.. _`array_merge`: http://php.net/array_merge
+2 -1
View File
@@ -12,6 +12,7 @@ The ``sort`` filter sorts an array:
.. note::
Internally, Twig uses the PHP `asort`_ function to maintain index
association.
association. It supports Traversable objects by transforming
those to arrays.
.. _`asort`: http://php.net/asort
+2 -2
View File
@@ -576,7 +576,7 @@ class Twig_ExpressionParser
if ($function->isDeprecated()) {
$message = sprintf('Twig Function "%s" is deprecated', $function->getName());
if ($test->getAlternative()) {
if ($function->getAlternative()) {
$message .= sprintf('. Use "%s" instead', $function->getAlternative());
}
$message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line);
@@ -602,7 +602,7 @@ class Twig_ExpressionParser
if ($filter->isDeprecated()) {
$message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
if ($test->getAlternative()) {
if ($filter->getAlternative()) {
$message .= sprintf('. Use "%s" instead', $filter->getAlternative());
}
$message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line);
+46 -8
View File
@@ -152,7 +152,7 @@ class Twig_Extension_Core extends Twig_Extension
new Twig_Filter('date', 'twig_date_format_filter', array('needs_environment' => true)),
new Twig_Filter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)),
new Twig_Filter('format', 'sprintf'),
new Twig_Filter('replace', 'strtr'),
new Twig_Filter('replace', 'twig_replace_filter'),
new Twig_Filter('number_format', 'twig_number_format_filter', array('needs_environment' => true)),
new Twig_Filter('abs', 'abs'),
new Twig_Filter('round', 'twig_round'),
@@ -527,6 +527,30 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
return $date;
}
/**
* Replaces strings within a string.
*
* @param string $str String to replace in
* @param array|Traversable $from Replace values
* @param string|null $to Replace to, deprecated (@see http://php.net/manual/en/function.strtr.php)
*
* @return string
*/
function twig_replace_filter($str, $from, $to = null)
{
if ($from instanceof Traversable) {
$from = iterator_to_array($from);
} elseif (is_string($from) && is_string($to)) {
@trigger_error('Using "replace" with character by character replacement is deprecated and will be removed in Twig 2.0', E_USER_DEPRECATED);
return strtr($str, $from, $to);
} elseif (!is_array($from)) {
throw new Twig_Error_Runtime(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".',is_object($from) ? get_class($from) : gettype($from)));
}
return strtr($str, $from);
}
/**
* Rounds a number.
*
@@ -636,15 +660,23 @@ function twig_jsonencode_filter($value, $options = 0)
* {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
* </pre>
*
* @param array $arr1 An array
* @param array $arr2 An array
* @param array|Traversable $arr1 An array
* @param array|Traversable $arr2 An array
*
* @return array The merged array
*/
function twig_array_merge($arr1, $arr2)
{
if (!is_array($arr1) || !is_array($arr2)) {
throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or hashes; %s and %s given.', gettype($arr1), gettype($arr2)));
if ($arr1 instanceof Traversable) {
$arr1 = iterator_to_array($arr1);
} elseif (!is_array($arr1)) {
throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', gettype($arr1)));
}
if ($arr2 instanceof Traversable) {
$arr2 = iterator_to_array($arr2);
} elseif (!is_array($arr2)) {
throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', gettype($arr2)));
}
return array_merge($arr1, $arr2);
@@ -828,7 +860,7 @@ function _twig_default_filter($value, $default = '')
*/
function twig_get_array_keys_filter($array)
{
if (is_object($array) && $array instanceof Traversable) {
if ($array instanceof Traversable) {
return array_keys(iterator_to_array($array));
}
@@ -850,7 +882,7 @@ function twig_get_array_keys_filter($array)
*/
function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
{
if (is_object($item) && $item instanceof Traversable) {
if ($item instanceof Traversable) {
return array_reverse(iterator_to_array($item), $preserveKeys);
}
@@ -882,12 +914,18 @@ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false
/**
* Sorts an array.
*
* @param array $array
* @param array|Traversable $array
*
* @return array
*/
function twig_sort_filter($array)
{
if ($array instanceof Traversable) {
$array = iterator_to_array($array);
} elseif (!is_array($array)) {
throw new Twig_Error_Runtime(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', gettype($array)));
}
asort($array);
return $array;
+3 -1
View File
@@ -6,11 +6,13 @@
{{ {'bar': 'foo'}|merge(items)|join }}
{{ {'bar': 'foo'}|merge(items)|keys|join }}
{{ numerics|merge([4, 5, 6])|join }}
{{ traversable.a|merge(traversable.b)|join }}
--DATA--
return array('items' => array('foo' => 'bar'), 'numerics' => array(1, 2, 3))
return array('items' => array('foo' => 'bar'), 'numerics' => array(1, 2, 3), 'traversable' => array('a' => new ArrayObject(array(0 => 1, 1 => 2, 2 => 3)), 'b' => new ArrayObject(array('a' => 'b'))))
--EXPECT--
barfoo
foobar
foobar
barfoo
123456
123b
@@ -1,8 +1,12 @@
--TEST--
"replace" filter
--TEMPLATE--
{{ "I like %this% and %that%."|replace({'%this%': "foo", '%that%': "bar"}) }}
{{ "I liké %this% and %that%."|replace({'%this%': "foo", '%that%': "bar"}) }}
{{ 'I like single replace operation only %that%'|replace({'%that%' : '%that%1'}) }}
{{ 'I like %this% and %that%.'|replace(traversable) }}
--DATA--
return array()
return array('traversable' => new ArrayObject(array('%this%' => 'foo', '%that%' => 'bar')))
--EXPECT--
I liké foo and bar.
I like single replace operation only %that%1
I like foo and bar.
@@ -0,0 +1,8 @@
--TEST--
Exception for invalid argument type in replace call
--TEMPLATE--
{{ 'test %foo%'|replace(stdClass) }}
--DATA--
return array('stdClass' => new \stdClass())
--EXCEPTION--
Twig_Error_Runtime: The "replace" filter expects an array or "Traversable" as replace values, got "stdClass" in "index.twig" at line 2.
+3 -1
View File
@@ -3,8 +3,10 @@
--TEMPLATE--
{{ array1|sort|join }}
{{ array2|sort|join }}
{{ traversable|sort|join }}
--DATA--
return array('array1' => array(4, 1), 'array2' => array('foo', 'bar'))
return array('array1' => array(4, 1), 'array2' => array('foo', 'bar'), 'traversable' => new ArrayObject(array(0 => 3, 1 => 2, 2 => 1)))
--EXPECT--
14
barfoo
123