From 50b270613d1bdbc95f4df84ea8e10fd785580658 Mon Sep 17 00:00:00 2001 From: SpacePossum Date: Tue, 5 Jun 2018 13:50:47 +0200 Subject: [PATCH] Add max value to random function --- doc/functions/random.rst | 3 ++ lib/Twig/Extension/Core.php | 20 +++++++++-- test/Twig/Tests/Extension/CoreTest.php | 48 +++++++++++++++++--------- 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/doc/functions/random.rst b/doc/functions/random.rst index 57015b840..9a9be3396 100644 --- a/doc/functions/random.rst +++ b/doc/functions/random.rst @@ -13,6 +13,8 @@ parameter type: * a random item from a sequence; * a random character from a string; * a random integer between 0 and the integer parameter (inclusive). +* a random integer between the integer parameter (when negative) and 0 (inclusive). +* a random integer between the first integer and the second integer parameter (inclusive). .. code-block:: jinja @@ -20,6 +22,7 @@ parameter type: {{ random('ABC') }} {# example output: C #} {{ random() }} {# example output: 15386094 (works as the native PHP mt_rand function) #} {{ random(5) }} {# example output: 3 #} + {{ random(50, 100) }} {# example output: 63 #} Arguments --------- diff --git a/lib/Twig/Extension/Core.php b/lib/Twig/Extension/Core.php index 44964ac6d..9fafe4804 100644 --- a/lib/Twig/Extension/Core.php +++ b/lib/Twig/Extension/Core.php @@ -330,19 +330,33 @@ function twig_cycle($values, $position) * - a random integer between 0 and the integer parameter. * * @param \Traversable|array|int|float|string $values The values to pick a random item from + * @param int|null $max Maximum value used when $values is an int * * @throws RuntimeError when $values is an empty array (does not apply to an empty string which is returned as is) * * @return mixed A random value from the given sequence */ -function twig_random(Twig_Environment $env, $values = null) +function twig_random(Twig_Environment $env, $values = null, $max = null) { if (null === $values) { - return mt_rand(); + return null === $max ? mt_rand() : mt_rand(0, $max); } if (\is_int($values) || \is_float($values)) { - return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values); + if (null === $max) { + if ($values < 0) { + $max = 0; + $min = $values; + } else { + $max = $values; + $min = 0; + } + } else { + $min = $values; + $max = $max; + } + + return mt_rand($min, $max); } if ($values instanceof \Traversable) { diff --git a/test/Twig/Tests/Extension/CoreTest.php b/test/Twig/Tests/Extension/CoreTest.php index fdcb4fb06..1a2dd4a23 100644 --- a/test/Twig/Tests/Extension/CoreTest.php +++ b/test/Twig/Tests/Extension/CoreTest.php @@ -16,45 +16,59 @@ class Twig_Tests_Extension_CoreTest extends \PHPUnit\Framework\TestCase /** * @dataProvider getRandomFunctionTestData */ - public function testRandomFunction($value, $expectedInArray) + public function testRandomFunction(array $expectedInArray, $value1, $value2 = null) { - $env = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock()); - + $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); for ($i = 0; $i < 100; ++$i) { - $this->assertTrue(\in_array(twig_random($env, $value), $expectedInArray, true)); // assertContains() would not consider the type + $this->assertTrue(\in_array(twig_random($env, $value1, $value2), $expectedInArray, true)); // assertContains() would not consider the type } } public function getRandomFunctionTestData() { return [ - [// array + 'array' => [ ['apple', 'orange', 'citrus'], ['apple', 'orange', 'citrus'], ], - [// Traversable - new \ArrayObject(['apple', 'orange', 'citrus']), + 'Traversable' => [ ['apple', 'orange', 'citrus'], + new ArrayObject(['apple', 'orange', 'citrus']), ], - [// unicode string - 'Ä€é', + 'unicode string' => [ ['Ä', '€', 'é'], + 'Ä€é', ], - [// numeric but string - '123', + 'numeric but string' => [ ['1', '2', '3'], + '123', ], - [// integer + 'integer' => [ + range(0, 5, 1), 5, - range(0, 5, 1), ], - [// float + 'float' => [ + range(0, 5, 1), 5.9, - range(0, 5, 1), ], - [// negative - -2, + 'negative' => [ [0, -1, -2], + -2, + ], + 'min max int' => [ + range(50, 100), + 50, + 100, + ], + 'min max float' => [ + range(-10, 10), + -9.5, + 9.5, + ], + 'min null' => [ + range(0, 100), + null, + 100, ], ]; }