merged branch Tobion/patch-4 (PR #614)

Commits
-------

a15e8f7 typo again
2561aa2 typo
faa90c9 updated doc for random function
fe66358 added tests for random function
6f5ceee Made the random function more versatile

Discussion
----------

Made the random function more versatile

The point is to meet user expectations and to make it more versatile, so it works under more circumstances.
At the moment the random function does only return the supplied parameter when it's not an array. That is not very useful. With this PR it will behave like

    random() => integer as with mt_rand()
    random(5) => integer between 0 and 5 as with mt_rand(0, 5)
    random('foobar') => random character from 'foobar'
    random(array(...)) => random element

I will add tests and documentation if you accept this PR.

---------------------------------------------------------------------------

by fabpot at 2012-01-26T07:29:35Z

Looks good to me. Can you update the docs and add some unit tests?

---------------------------------------------------------------------------

by Tobion at 2012-01-26T11:50:17Z

ready
This commit is contained in:
Fabien Potencier
2012-01-26 13:24:26 +01:00
4 changed files with 90 additions and 18 deletions
+1
View File
@@ -10,6 +10,7 @@
* added a date function to ease date comparison
* fixed unary operators precedence
* added recursive parsing support in the parser
* added string and integer handling for the random function
* 1.5.1 (2012-01-05)
+14 -2
View File
@@ -4,8 +4,20 @@
.. versionadded:: 1.5
The random function was added in Twig 1.5.
The ``random`` function returns a random item from a sequence:
.. versionadded:: 1.6
String and integer handling was added in Twig 1.6.
The ``random`` function returns a random value depending on the supplied parameter type:
* a random item from a Traversable or array
* a random character from a string
* a random integer between 0 and the integer parameter (inclusive)
.. code-block:: jinja
{{ random(['apple', 'orange', 'citrus']) }}
{{ random(['apple', 'orange', 'citrus']) }} {# example output: orange #}
{{ random('ABC') }} {# example output: C #}
{{ random() }} {# example output: 15386094 (works as native PHP `mt_rand`_ function) #}
{{ random(5) }} {# example output: 3 #}
.. _`mt_rand`: http://php.net/mt_rand
+21 -6
View File
@@ -283,20 +283,35 @@ function twig_cycle($values, $i)
}
/**
* Returns a random item from sequence.
* Returns a random value depending on the supplied parameter type:
* - a random item from a Traversable or array
* - a random character from a string
* - a random integer between 0 and the integer parameter
*
* @param Iterator|array $values An array or an ArrayAccess instance
* @param Traversable|array|int|string $values The values to pick a random item from
*
* @return mixed A random value from the given sequence
*/
function twig_random($values)
function twig_random($values = null)
{
if (!is_array($values) && !$values instanceof Traversable) {
return $values;
if (null === $values) {
return mt_rand();
}
if (is_object($values)) {
if (is_int($values) || is_float($values)) {
return mt_rand(0, $values);
}
if ($values instanceof Traversable) {
$values = iterator_to_array($values);
} elseif (is_string($values)) {
// unicode version of str_split()
// split at all positions, but not after the start and not before the end
$values = preg_split('/(?<!^)(?!$)/u', $values);
}
if (!is_array($values)) {
return $values;
}
if (0 === count($values)) {
+54 -10
View File
@@ -11,17 +11,61 @@
class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
{
public function testRandomFunction()
/**
* @dataProvider getRandomFunctionTestData
*/
public function testRandomFunction($value, $expectedInArray)
{
$items = array('apple', 'orange', 'citrus');
$values = array(
$items,
new ArrayObject($items),
);
foreach ($values as $value) {
for ($i = 0; $i < 100; $i++) {
$this->assertTrue(in_array(twig_random($value), $items));
}
for ($i = 0; $i < 100; $i++) {
$this->assertTrue(in_array(twig_random($value), $expectedInArray, true)); // assertContains() would not consider the type
}
}
public function getRandomFunctionTestData()
{
return array(
array( // array
array('apple', 'orange', 'citrus'),
array('apple', 'orange', 'citrus'),
),
array( // Traversable
new ArrayObject(array('apple', 'orange', 'citrus')),
array('apple', 'orange', 'citrus'),
),
array( // unicode string
'Ä€é',
array('Ä', '€', 'é'),
),
array( // numeric but string
'123',
array('1', '2', '3'),
),
array( // integer
5,
range(0, 5, 1),
),
array( // float
5.9,
range(0, 5, 1),
),
);
}
public function testRandomFunctionWithoutParameter()
{
$max = mt_getrandmax();
for ($i = 0; $i < 100; $i++) {
$val = twig_random();
$this->assertTrue(is_int($val) && $val >= 0 && $val <= $max);
}
}
/**
* @expectedException Twig_Error_Runtime
*/
public function testRandomFunctionOfEmptyArrayThrowsException()
{
twig_random(array());
}
}