annotate core/lib/Drupal/Component/Utility/Random.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Component\Utility;
Chris@0 4
Chris@0 5 /**
Chris@0 6 * Defines a utility class for creating random data.
Chris@0 7 *
Chris@0 8 * @ingroup utility
Chris@0 9 */
Chris@0 10 class Random {
Chris@0 11
Chris@0 12 /**
Chris@0 13 * The maximum number of times name() and string() can loop.
Chris@0 14 *
Chris@0 15 * This prevents infinite loops if the length of the random value is very
Chris@0 16 * small.
Chris@0 17 *
Chris@0 18 * @see \Drupal\Tests\Component\Utility\RandomTest
Chris@0 19 */
Chris@0 20 const MAXIMUM_TRIES = 100;
Chris@0 21
Chris@0 22 /**
Chris@0 23 * A list of unique strings generated by string().
Chris@0 24 *
Chris@0 25 * @var array
Chris@0 26 */
Chris@0 27 protected $strings = [];
Chris@0 28
Chris@0 29 /**
Chris@0 30 * A list of unique names generated by name().
Chris@0 31 *
Chris@0 32 * @var array
Chris@0 33 */
Chris@0 34 protected $names = [];
Chris@0 35
Chris@0 36 /**
Chris@0 37 * Generates a random string of ASCII characters of codes 32 to 126.
Chris@0 38 *
Chris@0 39 * The generated string includes alpha-numeric characters and common
Chris@0 40 * miscellaneous characters. Use this method when testing general input
Chris@0 41 * where the content is not restricted.
Chris@0 42 *
Chris@0 43 * @param int $length
Chris@0 44 * Length of random string to generate.
Chris@0 45 * @param bool $unique
Chris@0 46 * (optional) If TRUE ensures that the random string returned is unique.
Chris@0 47 * Defaults to FALSE.
Chris@0 48 * @param callable $validator
Chris@0 49 * (optional) A callable to validate the string. Defaults to NULL.
Chris@0 50 *
Chris@0 51 * @return string
Chris@0 52 * Randomly generated string.
Chris@0 53 *
Chris@0 54 * @see \Drupal\Component\Utility\Random::name()
Chris@0 55 */
Chris@0 56 public function string($length = 8, $unique = FALSE, $validator = NULL) {
Chris@0 57 $counter = 0;
Chris@0 58
Chris@0 59 // Continue to loop if $unique is TRUE and the generated string is not
Chris@0 60 // unique or if $validator is a callable that returns FALSE. To generate a
Chris@0 61 // random string this loop must be carried out at least once.
Chris@0 62 do {
Chris@0 63 if ($counter == static::MAXIMUM_TRIES) {
Chris@0 64 throw new \RuntimeException('Unable to generate a unique random name');
Chris@0 65 }
Chris@0 66 $str = '';
Chris@0 67 for ($i = 0; $i < $length; $i++) {
Chris@0 68 $str .= chr(mt_rand(32, 126));
Chris@0 69 }
Chris@0 70 $counter++;
Chris@0 71
Chris@0 72 $continue = FALSE;
Chris@0 73 if ($unique) {
Chris@0 74 $continue = isset($this->strings[$str]);
Chris@0 75 }
Chris@0 76 if (!$continue && is_callable($validator)) {
Chris@0 77 // If the validator callback returns FALSE generate another random
Chris@0 78 // string.
Chris@0 79 $continue = !call_user_func($validator, $str);
Chris@0 80 }
Chris@0 81 } while ($continue);
Chris@0 82
Chris@0 83 if ($unique) {
Chris@0 84 $this->strings[$str] = TRUE;
Chris@0 85 }
Chris@0 86
Chris@0 87 return $str;
Chris@0 88 }
Chris@0 89
Chris@0 90 /**
Chris@0 91 * Generates a random string containing letters and numbers.
Chris@0 92 *
Chris@0 93 * The string will always start with a letter. The letters may be upper or
Chris@0 94 * lower case. This method is better for restricted inputs that do not
Chris@0 95 * accept certain characters. For example, when testing input fields that
Chris@0 96 * require machine readable values (i.e. without spaces and non-standard
Chris@0 97 * characters) this method is best.
Chris@0 98 *
Chris@0 99 * @param int $length
Chris@0 100 * Length of random string to generate.
Chris@0 101 * @param bool $unique
Chris@0 102 * (optional) If TRUE ensures that the random string returned is unique.
Chris@0 103 * Defaults to FALSE.
Chris@0 104 *
Chris@0 105 * @return string
Chris@0 106 * Randomly generated string.
Chris@0 107 *
Chris@0 108 * @see \Drupal\Component\Utility\Random::string()
Chris@0 109 */
Chris@0 110 public function name($length = 8, $unique = FALSE) {
Chris@0 111 $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
Chris@0 112 $max = count($values) - 1;
Chris@0 113 $counter = 0;
Chris@0 114
Chris@0 115 do {
Chris@0 116 if ($counter == static::MAXIMUM_TRIES) {
Chris@0 117 throw new \RuntimeException('Unable to generate a unique random name');
Chris@0 118 }
Chris@0 119 $str = chr(mt_rand(97, 122));
Chris@0 120 for ($i = 1; $i < $length; $i++) {
Chris@0 121 $str .= chr($values[mt_rand(0, $max)]);
Chris@0 122 }
Chris@0 123 $counter++;
Chris@0 124 } while ($unique && isset($this->names[$str]));
Chris@0 125
Chris@0 126 if ($unique) {
Chris@0 127 $this->names[$str] = TRUE;
Chris@0 128 }
Chris@0 129
Chris@0 130 return $str;
Chris@0 131 }
Chris@0 132
Chris@0 133 /**
Chris@0 134 * Generate a string that looks like a word (letters only, alternating consonants and vowels).
Chris@0 135 *
Chris@0 136 * @param int $length
Chris@0 137 * The desired word length.
Chris@0 138 *
Chris@0 139 * @return string
Chris@0 140 */
Chris@0 141 public function word($length) {
Chris@0 142 mt_srand((double) microtime() * 1000000);
Chris@0 143
Chris@0 144 $vowels = ["a", "e", "i", "o", "u"];
Chris@0 145 $cons = ["b", "c", "d", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "u", "v", "w", "tr",
Chris@0 146 "cr", "br", "fr", "th", "dr", "ch", "ph", "wr", "st", "sp", "sw", "pr",
Chris@0 147 "sl", "cl", "sh",
Chris@0 148 ];
Chris@0 149
Chris@0 150 $num_vowels = count($vowels);
Chris@0 151 $num_cons = count($cons);
Chris@0 152 $word = '';
Chris@0 153
Chris@0 154 while (strlen($word) < $length) {
Chris@0 155 $word .= $cons[mt_rand(0, $num_cons - 1)] . $vowels[mt_rand(0, $num_vowels - 1)];
Chris@0 156 }
Chris@0 157
Chris@0 158 return substr($word, 0, $length);
Chris@0 159 }
Chris@0 160
Chris@0 161 /**
Chris@0 162 * Generates a random PHP object.
Chris@0 163 *
Chris@0 164 * @param int $size
Chris@0 165 * The number of random keys to add to the object.
Chris@0 166 *
Chris@0 167 * @return \stdClass
Chris@0 168 * The generated object, with the specified number of random keys. Each key
Chris@0 169 * has a random string value.
Chris@0 170 */
Chris@0 171 public function object($size = 4) {
Chris@0 172 $object = new \stdClass();
Chris@0 173 for ($i = 0; $i < $size; $i++) {
Chris@0 174 $random_key = $this->name();
Chris@0 175 $random_value = $this->string();
Chris@0 176 $object->{$random_key} = $random_value;
Chris@0 177 }
Chris@0 178 return $object;
Chris@0 179 }
Chris@0 180
Chris@0 181 /**
Chris@0 182 * Generates sentences Latin words, often used as placeholder text.
Chris@0 183 *
Chris@0 184 * @param int $min_word_count
Chris@0 185 * The minimum number of words in the return string. Total word count
Chris@0 186 * can slightly exceed provided this value in order to deliver
Chris@0 187 * sentences of random length.
Chris@0 188 * @param bool $capitalize
Chris@0 189 * Uppercase all the words in the string.
Chris@0 190 *
Chris@0 191 * @return string
Chris@0 192 * Nonsense latin words which form sentence(s).
Chris@0 193 */
Chris@0 194 public function sentences($min_word_count, $capitalize = FALSE) {
Chris@0 195 $dictionary = ["abbas", "abdo", "abico", "abigo", "abluo", "accumsan",
Chris@0 196 "acsi", "ad", "adipiscing", "aliquam", "aliquip", "amet", "antehabeo",
Chris@0 197 "appellatio", "aptent", "at", "augue", "autem", "bene", "blandit",
Chris@0 198 "brevitas", "caecus", "camur", "capto", "causa", "cogo", "comis",
Chris@0 199 "commodo", "commoveo", "consectetuer", "consequat", "conventio", "cui",
Chris@0 200 "damnum", "decet", "defui", "diam", "dignissim", "distineo", "dolor",
Chris@0 201 "dolore", "dolus", "duis", "ea", "eligo", "elit", "enim", "erat",
Chris@0 202 "eros", "esca", "esse", "et", "eu", "euismod", "eum", "ex", "exerci",
Chris@0 203 "exputo", "facilisi", "facilisis", "fere", "feugiat", "gemino",
Chris@0 204 "genitus", "gilvus", "gravis", "haero", "hendrerit", "hos", "huic",
Chris@0 205 "humo", "iaceo", "ibidem", "ideo", "ille", "illum", "immitto",
Chris@0 206 "importunus", "imputo", "in", "incassum", "inhibeo", "interdico",
Chris@0 207 "iriure", "iusto", "iustum", "jugis", "jumentum", "jus", "laoreet",
Chris@0 208 "lenis", "letalis", "lobortis", "loquor", "lucidus", "luctus", "ludus",
Chris@0 209 "luptatum", "macto", "magna", "mauris", "melior", "metuo", "meus",
Chris@0 210 "minim", "modo", "molior", "mos", "natu", "neo", "neque", "nibh",
Chris@0 211 "nimis", "nisl", "nobis", "nostrud", "nulla", "nunc", "nutus", "obruo",
Chris@0 212 "occuro", "odio", "olim", "oppeto", "os", "pagus", "pala", "paratus",
Chris@0 213 "patria", "paulatim", "pecus", "persto", "pertineo", "plaga", "pneum",
Chris@0 214 "populus", "praemitto", "praesent", "premo", "probo", "proprius",
Chris@0 215 "quadrum", "quae", "qui", "quia", "quibus", "quidem", "quidne", "quis",
Chris@0 216 "ratis", "refero", "refoveo", "roto", "rusticus", "saepius",
Chris@0 217 "sagaciter", "saluto", "scisco", "secundum", "sed", "si", "similis",
Chris@0 218 "singularis", "sino", "sit", "sudo", "suscipere", "suscipit", "tamen",
Chris@0 219 "tation", "te", "tego", "tincidunt", "torqueo", "tum", "turpis",
Chris@0 220 "typicus", "ulciscor", "ullamcorper", "usitas", "ut", "utinam",
Chris@0 221 "utrum", "uxor", "valde", "valetudo", "validus", "vel", "velit",
Chris@0 222 "veniam", "venio", "vereor", "vero", "verto", "vicis", "vindico",
Chris@0 223 "virtus", "voco", "volutpat", "vulpes", "vulputate", "wisi", "ymo",
Chris@0 224 "zelus",
Chris@0 225 ];
Chris@0 226 $dictionary_flipped = array_flip($dictionary);
Chris@0 227 $greeking = '';
Chris@0 228
Chris@0 229 if (!$capitalize) {
Chris@0 230 $words_remaining = $min_word_count;
Chris@0 231 while ($words_remaining > 0) {
Chris@0 232 $sentence_length = mt_rand(3, 10);
Chris@0 233 $words = array_rand($dictionary_flipped, $sentence_length);
Chris@0 234 $sentence = implode(' ', $words);
Chris@0 235 $greeking .= ucfirst($sentence) . '. ';
Chris@0 236 $words_remaining -= $sentence_length;
Chris@0 237 }
Chris@0 238 }
Chris@0 239 else {
Chris@0 240 // Use slightly different method for titles.
Chris@0 241 $words = array_rand($dictionary_flipped, $min_word_count);
Chris@0 242 $words = is_array($words) ? implode(' ', $words) : $words;
Chris@0 243 $greeking = ucwords($words);
Chris@0 244 }
Chris@0 245 return trim($greeking);
Chris@0 246 }
Chris@0 247
Chris@0 248 /**
Chris@0 249 * Generate paragraphs separated by double new line.
Chris@0 250 *
Chris@0 251 * @param int $paragraph_count
Chris@0 252 * @return string
Chris@0 253 */
Chris@0 254 public function paragraphs($paragraph_count = 12) {
Chris@0 255 $output = '';
Chris@0 256 for ($i = 1; $i <= $paragraph_count; $i++) {
Chris@0 257 $output .= $this->sentences(mt_rand(20, 60)) . "\n\n";
Chris@0 258 }
Chris@0 259 return $output;
Chris@0 260 }
Chris@0 261
Chris@0 262 /**
Chris@0 263 * Create a placeholder image.
Chris@0 264 *
Chris@0 265 * @param string $destination
Chris@0 266 * The absolute file path where the image should be stored.
Chris@0 267 * @param int $min_resolution
Chris@0 268 * @param int $max_resolution
Chris@0 269 *
Chris@0 270 * @return string
Chris@0 271 * Path to image file.
Chris@0 272 */
Chris@0 273 public function image($destination, $min_resolution, $max_resolution) {
Chris@0 274 $extension = pathinfo($destination, PATHINFO_EXTENSION);
Chris@0 275 $min = explode('x', $min_resolution);
Chris@0 276 $max = explode('x', $max_resolution);
Chris@0 277
Chris@0 278 $width = rand((int) $min[0], (int) $max[0]);
Chris@0 279 $height = rand((int) $min[1], (int) $max[1]);
Chris@0 280
Chris@0 281 // Make an image split into 4 sections with random colors.
Chris@0 282 $im = imagecreate($width, $height);
Chris@0 283 for ($n = 0; $n < 4; $n++) {
Chris@0 284 $color = imagecolorallocate($im, rand(0, 255), rand(0, 255), rand(0, 255));
Chris@0 285 $x = $width / 2 * ($n % 2);
Chris@0 286 $y = $height / 2 * (int) ($n >= 2);
Chris@0 287 imagefilledrectangle($im, $x, $y, $x + $width / 2, $y + $height / 2, $color);
Chris@0 288 }
Chris@0 289
Chris@0 290 // Make a perfect circle in the image middle.
Chris@0 291 $color = imagecolorallocate($im, rand(0, 255), rand(0, 255), rand(0, 255));
Chris@0 292 $smaller_dimension = min($width, $height);
Chris@0 293 imageellipse($im, $width / 2, $height / 2, $smaller_dimension, $smaller_dimension, $color);
Chris@0 294
Chris@0 295 $save_function = 'image' . ($extension == 'jpg' ? 'jpeg' : $extension);
Chris@0 296 $save_function($im, $destination);
Chris@0 297 return $destination;
Chris@0 298 }
Chris@0 299
Chris@0 300 }