fixed the random() function on strings when the charset is not UTF-8
authorFabien Potencier <fabien.potencier@gmail.com>
Fri, 27 Jan 2012 07:24:59 +0000 (08:24 +0100)
committerFabien Potencier <fabien.potencier@gmail.com>
Fri, 27 Jan 2012 07:25:05 +0000 (08:25 +0100)
(refs #614)

lib/Twig/Extension/Core.php
test/Twig/Tests/Extension/CoreTest.php

index 2d5522c..9d35ae1 100644 (file)
@@ -158,7 +158,7 @@ class Twig_Extension_Core extends Twig_Extension
             'range'    => new Twig_Function_Function('range'),
             'constant' => new Twig_Function_Function('constant'),
             'cycle'    => new Twig_Function_Function('twig_cycle'),
-            'random'   => new Twig_Function_Function('twig_random'),
+            'random'   => new Twig_Function_Function('twig_random', array('needs_environment' => true)),
             'date'     => new Twig_Function_Function('twig_date_converter'),
         );
     }
@@ -288,11 +288,12 @@ function twig_cycle($values, $i)
  * - a random character from a string 
  * - a random integer between 0 and the integer parameter
  *
+ * @param Twig_Environment             $env    A Twig_Environment 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 = null)
+function twig_random(Twig_Environment $env, $values = null)
 {
     if (null === $values) {
         return mt_rand();
@@ -305,9 +306,21 @@ function twig_random($values = null)
     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 (null !== $charset = $env->getCharset()) {
+            if ('UTF-8' != $charset) {
+                $values = twig_convert_encoding($values, 'UTF-8', $charset);
+            }
+
+            // 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 ('UTF-8' != $charset) {
+                $values = twig_convert_encoding($values, $charset, 'UTF-8');
+            }
+        } else {
+            return substr($values, mt_rand(0, strlen($values)), 1);
+        }
     }
 
     if (!is_array($values)) {
index e1936c3..49abdfb 100644 (file)
@@ -17,7 +17,7 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
     public function testRandomFunction($value, $expectedInArray)
     {
         for ($i = 0; $i < 100; $i++) {
-            $this->assertTrue(in_array(twig_random($value), $expectedInArray, true)); // assertContains() would not consider the type
+            $this->assertTrue(in_array(twig_random(new Twig_Environment(), $value), $expectedInArray, true)); // assertContains() would not consider the type
         }
     }
 
@@ -60,17 +60,17 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
         $max = mt_getrandmax();
 
         for ($i = 0; $i < 100; $i++) {
-            $val = twig_random();
+            $val = twig_random(new Twig_Environment());
             $this->assertTrue(is_int($val) && $val >= 0 && $val <= $max);
         }
     }
 
     public function testRandomFunctionReturnsAsIs()
     {
-        $this->assertSame('', twig_random(''));
+        $this->assertSame('', twig_random(new Twig_Environment(), ''));
 
         $instance = new stdClass();
-        $this->assertSame($instance, twig_random($instance));
+        $this->assertSame($instance, twig_random(new Twig_Environment(), $instance));
     }
 
     /**
@@ -78,6 +78,6 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
      */
     public function testRandomFunctionOfEmptyArrayThrowsException()
     {
-        twig_random(array());
+        twig_random(new Twig_Environment(), array());
     }
 }