Random.php 4.17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
<?php

/**
 * @file
 * Contains \Drupal\Component\Utility\Random.
 */

namespace Drupal\Component\Utility;

/**
 * Defines a utility class for creating random data.
12 13
 *
 * @ingroup utility
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 */
class Random {

  /**
   * The maximum number of times name() and string() can loop.
   *
   * This prevents infinite loops if the length of the random value is very
   * small.
   *
   * @see \Drupal\Tests\Component\Utility\RandomTest
   */
  const MAXIMUM_TRIES = 100;

  /**
   * A list of unique strings generated by string().
   *
   * @var array
   */
32
  protected $strings = array();
33 34 35 36 37 38

  /**
   * A list of unique names generated by name().
   *
   * @var array
   */
39
  protected $names = array();
40 41 42 43 44 45 46 47 48 49 50 51 52

  /**
   * Generates a random string of ASCII characters of codes 32 to 126.
   *
   * The generated string includes alpha-numeric characters and common
   * miscellaneous characters. Use this method when testing general input
   * where the content is not restricted.
   *
   * @param int $length
   *   Length of random string to generate.
   * @param bool $unique
   *   (optional) If TRUE ensures that the random string returned is unique.
   *   Defaults to FALSE.
53 54
   * @param callable $validator
   *   (optional) A callable to validate the the string. Defaults to NULL.
55 56 57 58 59 60
   *
   * @return string
   *   Randomly generated string.
   *
   * @see \Drupal\Component\Utility\Random::name()
   */
61
  public function string($length = 8, $unique = FALSE, $validator = NULL) {
62 63
    $counter = 0;

64 65 66
    // Continue to loop if $unique is TRUE and the generated string is not
    // unique or if $validator is a callable that returns FALSE. To generate a
    // random string this loop must be carried out at least once.
67 68 69 70 71 72 73 74 75
    do {
      if ($counter == static::MAXIMUM_TRIES) {
        throw new \RuntimeException('Unable to generate a unique random name');
      }
      $str = '';
      for ($i = 0; $i < $length; $i++) {
        $str .= chr(mt_rand(32, 126));
      }
      $counter++;
76 77 78 79 80 81 82 83 84 85 86

      $continue = FALSE;
      if ($unique) {
        $continue = isset($this->strings[$str]);
      }
      if (!$continue && is_callable($validator)) {
        // If the validator callback returns FALSE generate another random
        // string.
        $continue = !call_user_func($validator, $str);
      }
    } while ($continue);
87 88

    if ($unique) {
89
      $this->strings[$str] = TRUE;
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
    }

    return $str;
  }

  /**
   * Generates a random string containing letters and numbers.
   *
   * The string will always start with a letter. The letters may be upper or
   * lower case. This method is better for restricted inputs that do not
   * accept certain characters. For example, when testing input fields that
   * require machine readable values (i.e. without spaces and non-standard
   * characters) this method is best.
   *
   * @param int $length
   *   Length of random string to generate.
   * @param bool $unique
   *   (optional) If TRUE ensures that the random string returned is unique.
   *   Defaults to FALSE.
   *
   * @return string
   *   Randomly generated string.
   *
   * @see \Drupal\Component\Utility\Random::string()
   */
115
  public function name($length = 8, $unique = FALSE) {
116 117 118 119 120 121 122 123 124 125 126 127 128
    $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
    $max = count($values) - 1;
    $counter = 0;

    do {
      if ($counter == static::MAXIMUM_TRIES) {
        throw new \RuntimeException('Unable to generate a unique random name');
      }
      $str = chr(mt_rand(97, 122));
      for ($i = 1; $i < $length; $i++) {
        $str .= chr($values[mt_rand(0, $max)]);
      }
      $counter++;
129
    } while ($unique && isset($this->names[$str]));
130 131

    if ($unique) {
132
      $this->names[$str] = TRUE;
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
    }

    return $str;
  }

  /**
   * Generates a random PHP object.
   *
   * @param int $size
   *   The number of random keys to add to the object.
   *
   * @return \stdClass
   *   The generated object, with the specified number of random keys. Each key
   *   has a random string value.
   */
148
  public function object($size = 4) {
149 150
    $object = new \stdClass();
    for ($i = 0; $i < $size; $i++) {
151 152
      $random_key = $this->name();
      $random_value = $this->string();
153 154 155 156 157 158
      $object->{$random_key} = $random_value;
    }
    return $object;
  }

}