| 148 |
lars |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
namespace Faker\Provider;
|
|
|
4 |
|
|
|
5 |
use Faker\DefaultGenerator;
|
|
|
6 |
use Faker\Generator;
|
|
|
7 |
use Faker\UniqueGenerator;
|
|
|
8 |
use Faker\ValidGenerator;
|
|
|
9 |
|
|
|
10 |
class Base
|
|
|
11 |
{
|
|
|
12 |
/**
|
|
|
13 |
* @var \Faker\Generator
|
|
|
14 |
*/
|
|
|
15 |
protected $generator;
|
|
|
16 |
|
|
|
17 |
/**
|
|
|
18 |
* @var \Faker\UniqueGenerator
|
|
|
19 |
*/
|
|
|
20 |
protected $unique;
|
|
|
21 |
|
|
|
22 |
public function __construct(Generator $generator)
|
|
|
23 |
{
|
|
|
24 |
$this->generator = $generator;
|
|
|
25 |
}
|
|
|
26 |
|
|
|
27 |
/**
|
|
|
28 |
* Returns a random number between 0 and 9
|
|
|
29 |
*
|
|
|
30 |
* @return int
|
|
|
31 |
*/
|
|
|
32 |
public static function randomDigit()
|
|
|
33 |
{
|
|
|
34 |
return mt_rand(0, 9);
|
|
|
35 |
}
|
|
|
36 |
|
|
|
37 |
/**
|
|
|
38 |
* Returns a random number between 1 and 9
|
|
|
39 |
*
|
|
|
40 |
* @return int
|
|
|
41 |
*/
|
|
|
42 |
public static function randomDigitNotNull()
|
|
|
43 |
{
|
|
|
44 |
return mt_rand(1, 9);
|
|
|
45 |
}
|
|
|
46 |
|
|
|
47 |
/**
|
|
|
48 |
* Generates a random digit, which cannot be $except
|
|
|
49 |
*
|
|
|
50 |
* @param int $except
|
|
|
51 |
*
|
|
|
52 |
* @return int
|
|
|
53 |
*/
|
|
|
54 |
public static function randomDigitNot($except)
|
|
|
55 |
{
|
|
|
56 |
$result = self::numberBetween(0, 8);
|
|
|
57 |
|
|
|
58 |
if ($result >= $except) {
|
|
|
59 |
++$result;
|
|
|
60 |
}
|
|
|
61 |
|
|
|
62 |
return $result;
|
|
|
63 |
}
|
|
|
64 |
|
|
|
65 |
/**
|
|
|
66 |
* Returns a random integer with 0 to $nbDigits digits.
|
|
|
67 |
*
|
|
|
68 |
* The maximum value returned is mt_getrandmax()
|
|
|
69 |
*
|
|
|
70 |
* @param int $nbDigits Defaults to a random number between 1 and 9
|
|
|
71 |
* @param bool $strict Whether the returned number should have exactly $nbDigits
|
|
|
72 |
*
|
|
|
73 |
* @example 79907610
|
|
|
74 |
*
|
|
|
75 |
* @return int
|
|
|
76 |
*/
|
|
|
77 |
public static function randomNumber($nbDigits = null, $strict = false)
|
|
|
78 |
{
|
|
|
79 |
if (!is_bool($strict)) {
|
|
|
80 |
throw new \InvalidArgumentException('randomNumber() generates numbers of fixed width. To generate numbers between two boundaries, use numberBetween() instead.');
|
|
|
81 |
}
|
|
|
82 |
|
|
|
83 |
if (null === $nbDigits) {
|
|
|
84 |
$nbDigits = static::randomDigitNotNull();
|
|
|
85 |
}
|
|
|
86 |
$max = 10 ** $nbDigits - 1;
|
|
|
87 |
|
|
|
88 |
if ($max > mt_getrandmax()) {
|
|
|
89 |
throw new \InvalidArgumentException('randomNumber() can only generate numbers up to mt_getrandmax()');
|
|
|
90 |
}
|
|
|
91 |
|
|
|
92 |
if ($strict) {
|
|
|
93 |
return mt_rand(10 ** ($nbDigits - 1), $max);
|
|
|
94 |
}
|
|
|
95 |
|
|
|
96 |
return mt_rand(0, $max);
|
|
|
97 |
}
|
|
|
98 |
|
|
|
99 |
/**
|
|
|
100 |
* Return a random float number
|
|
|
101 |
*
|
|
|
102 |
* @param int $nbMaxDecimals
|
|
|
103 |
* @param float|int $min
|
|
|
104 |
* @param float|int $max
|
|
|
105 |
*
|
|
|
106 |
* @example 48.8932
|
|
|
107 |
*
|
|
|
108 |
* @return float
|
|
|
109 |
*/
|
|
|
110 |
public static function randomFloat($nbMaxDecimals = null, $min = 0, $max = null)
|
|
|
111 |
{
|
|
|
112 |
if (null === $nbMaxDecimals) {
|
|
|
113 |
$nbMaxDecimals = static::randomDigit();
|
|
|
114 |
}
|
|
|
115 |
|
|
|
116 |
if (null === $max) {
|
|
|
117 |
$max = static::randomNumber();
|
|
|
118 |
|
|
|
119 |
if ($min > $max) {
|
|
|
120 |
$max = $min;
|
|
|
121 |
}
|
|
|
122 |
}
|
|
|
123 |
|
|
|
124 |
if ($min > $max) {
|
|
|
125 |
$tmp = $min;
|
|
|
126 |
$min = $max;
|
|
|
127 |
$max = $tmp;
|
|
|
128 |
}
|
|
|
129 |
|
|
|
130 |
return round($min + mt_rand() / mt_getrandmax() * ($max - $min), $nbMaxDecimals);
|
|
|
131 |
}
|
|
|
132 |
|
|
|
133 |
/**
|
|
|
134 |
* Returns a random number between $int1 and $int2 (any order)
|
|
|
135 |
*
|
|
|
136 |
* @param int $int1 default to 0
|
|
|
137 |
* @param int $int2 defaults to 32 bit max integer, ie 2147483647
|
|
|
138 |
*
|
|
|
139 |
* @example 79907610
|
|
|
140 |
*
|
|
|
141 |
* @return int
|
|
|
142 |
*/
|
|
|
143 |
public static function numberBetween($int1 = 0, $int2 = 2147483647)
|
|
|
144 |
{
|
|
|
145 |
$min = $int1 < $int2 ? $int1 : $int2;
|
|
|
146 |
$max = $int1 < $int2 ? $int2 : $int1;
|
|
|
147 |
|
|
|
148 |
return mt_rand($min, $max);
|
|
|
149 |
}
|
|
|
150 |
|
|
|
151 |
/**
|
|
|
152 |
* Returns the passed value
|
|
|
153 |
*/
|
|
|
154 |
public static function passthrough($value)
|
|
|
155 |
{
|
|
|
156 |
return $value;
|
|
|
157 |
}
|
|
|
158 |
|
|
|
159 |
/**
|
|
|
160 |
* Returns a random letter from a to z
|
|
|
161 |
*
|
|
|
162 |
* @return string
|
|
|
163 |
*/
|
|
|
164 |
public static function randomLetter()
|
|
|
165 |
{
|
|
|
166 |
return chr(mt_rand(97, 122));
|
|
|
167 |
}
|
|
|
168 |
|
|
|
169 |
/**
|
|
|
170 |
* Returns a random ASCII character (excluding accents and special chars)
|
|
|
171 |
*
|
|
|
172 |
* @return string
|
|
|
173 |
*/
|
|
|
174 |
public static function randomAscii()
|
|
|
175 |
{
|
|
|
176 |
return chr(mt_rand(33, 126));
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
/**
|
|
|
180 |
* Returns randomly ordered subsequence of $count elements from a provided array
|
|
|
181 |
*
|
|
|
182 |
* @param array $array Array to take elements from. Defaults to a-c
|
|
|
183 |
* @param int $count Number of elements to take.
|
|
|
184 |
* @param bool $allowDuplicates Allow elements to be picked several times. Defaults to false
|
|
|
185 |
*
|
|
|
186 |
* @throws \LengthException When requesting more elements than provided
|
|
|
187 |
*
|
|
|
188 |
* @return array New array with $count elements from $array
|
|
|
189 |
*/
|
|
|
190 |
public static function randomElements($array = ['a', 'b', 'c'], $count = 1, $allowDuplicates = false)
|
|
|
191 |
{
|
|
|
192 |
$traversables = [];
|
|
|
193 |
|
|
|
194 |
if ($array instanceof \Traversable) {
|
|
|
195 |
foreach ($array as $element) {
|
|
|
196 |
$traversables[] = $element;
|
|
|
197 |
}
|
|
|
198 |
}
|
|
|
199 |
|
|
|
200 |
$arr = count($traversables) ? $traversables : $array;
|
|
|
201 |
|
|
|
202 |
$allKeys = array_keys($arr);
|
|
|
203 |
$numKeys = count($allKeys);
|
|
|
204 |
|
|
|
205 |
if (!$allowDuplicates && $numKeys < $count) {
|
|
|
206 |
throw new \LengthException(sprintf('Cannot get %d elements, only %d in array', $count, $numKeys));
|
|
|
207 |
}
|
|
|
208 |
|
|
|
209 |
$highKey = $numKeys - 1;
|
|
|
210 |
$keys = $elements = [];
|
|
|
211 |
$numElements = 0;
|
|
|
212 |
|
|
|
213 |
while ($numElements < $count) {
|
|
|
214 |
$num = mt_rand(0, $highKey);
|
|
|
215 |
|
|
|
216 |
if (!$allowDuplicates) {
|
|
|
217 |
if (isset($keys[$num])) {
|
|
|
218 |
continue;
|
|
|
219 |
}
|
|
|
220 |
$keys[$num] = true;
|
|
|
221 |
}
|
|
|
222 |
|
|
|
223 |
$elements[] = $arr[$allKeys[$num]];
|
|
|
224 |
++$numElements;
|
|
|
225 |
}
|
|
|
226 |
|
|
|
227 |
return $elements;
|
|
|
228 |
}
|
|
|
229 |
|
|
|
230 |
/**
|
|
|
231 |
* Returns a random element from a passed array
|
|
|
232 |
*
|
|
|
233 |
* @param array $array
|
|
|
234 |
*/
|
|
|
235 |
public static function randomElement($array = ['a', 'b', 'c'])
|
|
|
236 |
{
|
|
|
237 |
if (!$array || ($array instanceof \Traversable && !count($array))) {
|
|
|
238 |
return null;
|
|
|
239 |
}
|
|
|
240 |
$elements = static::randomElements($array, 1);
|
|
|
241 |
|
|
|
242 |
return $elements[0];
|
|
|
243 |
}
|
|
|
244 |
|
|
|
245 |
/**
|
|
|
246 |
* Returns a random key from a passed associative array
|
|
|
247 |
*
|
|
|
248 |
* @param array $array
|
|
|
249 |
*
|
|
|
250 |
* @return int|string|null
|
|
|
251 |
*/
|
|
|
252 |
public static function randomKey($array = [])
|
|
|
253 |
{
|
|
|
254 |
if (!$array) {
|
|
|
255 |
return null;
|
|
|
256 |
}
|
|
|
257 |
$keys = array_keys($array);
|
|
|
258 |
|
|
|
259 |
return $keys[mt_rand(0, count($keys) - 1)];
|
|
|
260 |
}
|
|
|
261 |
|
|
|
262 |
/**
|
|
|
263 |
* Returns a shuffled version of the argument.
|
|
|
264 |
*
|
|
|
265 |
* This function accepts either an array, or a string.
|
|
|
266 |
*
|
|
|
267 |
* @example $faker->shuffle([1, 2, 3]); // [2, 1, 3]
|
|
|
268 |
* @example $faker->shuffle('hello, world'); // 'rlo,h eold!lw'
|
|
|
269 |
*
|
|
|
270 |
* @see shuffleArray()
|
|
|
271 |
* @see shuffleString()
|
|
|
272 |
*
|
|
|
273 |
* @param array|string $arg The set to shuffle
|
|
|
274 |
*
|
|
|
275 |
* @return array|string The shuffled set
|
|
|
276 |
*/
|
|
|
277 |
public static function shuffle($arg = '')
|
|
|
278 |
{
|
|
|
279 |
if (is_array($arg)) {
|
|
|
280 |
return static::shuffleArray($arg);
|
|
|
281 |
}
|
|
|
282 |
|
|
|
283 |
if (is_string($arg)) {
|
|
|
284 |
return static::shuffleString($arg);
|
|
|
285 |
}
|
|
|
286 |
|
|
|
287 |
throw new \InvalidArgumentException('shuffle() only supports strings or arrays');
|
|
|
288 |
}
|
|
|
289 |
|
|
|
290 |
/**
|
|
|
291 |
* Returns a shuffled version of the array.
|
|
|
292 |
*
|
|
|
293 |
* This function does not mutate the original array. It uses the
|
|
|
294 |
* Fisher–Yates algorithm, which is unbiased, together with a Mersenne
|
|
|
295 |
* twister random generator. This function is therefore more random than
|
|
|
296 |
* PHP's shuffle() function, and it is seedable.
|
|
|
297 |
*
|
|
|
298 |
* @see http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
|
|
|
299 |
*
|
|
|
300 |
* @example $faker->shuffleArray([1, 2, 3]); // [2, 1, 3]
|
|
|
301 |
*
|
|
|
302 |
* @param array $array The set to shuffle
|
|
|
303 |
*
|
|
|
304 |
* @return array The shuffled set
|
|
|
305 |
*/
|
|
|
306 |
public static function shuffleArray($array = [])
|
|
|
307 |
{
|
|
|
308 |
$shuffledArray = [];
|
|
|
309 |
$i = 0;
|
|
|
310 |
reset($array);
|
|
|
311 |
|
|
|
312 |
foreach ($array as $key => $value) {
|
|
|
313 |
if ($i == 0) {
|
|
|
314 |
$j = 0;
|
|
|
315 |
} else {
|
|
|
316 |
$j = mt_rand(0, $i);
|
|
|
317 |
}
|
|
|
318 |
|
|
|
319 |
if ($j == $i) {
|
|
|
320 |
$shuffledArray[] = $value;
|
|
|
321 |
} else {
|
|
|
322 |
$shuffledArray[] = $shuffledArray[$j];
|
|
|
323 |
$shuffledArray[$j] = $value;
|
|
|
324 |
}
|
|
|
325 |
++$i;
|
|
|
326 |
}
|
|
|
327 |
|
|
|
328 |
return $shuffledArray;
|
|
|
329 |
}
|
|
|
330 |
|
|
|
331 |
/**
|
|
|
332 |
* Returns a shuffled version of the string.
|
|
|
333 |
*
|
|
|
334 |
* This function does not mutate the original string. It uses the
|
|
|
335 |
* Fisher–Yates algorithm, which is unbiased, together with a Mersenne
|
|
|
336 |
* twister random generator. This function is therefore more random than
|
|
|
337 |
* PHP's shuffle() function, and it is seedable. Additionally, it is
|
|
|
338 |
* UTF8 safe if the mb extension is available.
|
|
|
339 |
*
|
|
|
340 |
* @see http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
|
|
|
341 |
*
|
|
|
342 |
* @example $faker->shuffleString('hello, world'); // 'rlo,h eold!lw'
|
|
|
343 |
*
|
|
|
344 |
* @param string $string The set to shuffle
|
|
|
345 |
* @param string $encoding The string encoding (defaults to UTF-8)
|
|
|
346 |
*
|
|
|
347 |
* @return string The shuffled set
|
|
|
348 |
*/
|
|
|
349 |
public static function shuffleString($string = '', $encoding = 'UTF-8')
|
|
|
350 |
{
|
|
|
351 |
if (function_exists('mb_strlen')) {
|
|
|
352 |
// UTF8-safe str_split()
|
|
|
353 |
$array = [];
|
|
|
354 |
$strlen = mb_strlen($string, $encoding);
|
|
|
355 |
|
|
|
356 |
for ($i = 0; $i < $strlen; ++$i) {
|
|
|
357 |
$array[] = mb_substr($string, $i, 1, $encoding);
|
|
|
358 |
}
|
|
|
359 |
} else {
|
|
|
360 |
$array = str_split($string, 1);
|
|
|
361 |
}
|
|
|
362 |
|
|
|
363 |
return implode('', static::shuffleArray($array));
|
|
|
364 |
}
|
|
|
365 |
|
|
|
366 |
private static function replaceWildcard($string, $wildcard, $callback)
|
|
|
367 |
{
|
|
|
368 |
if (($pos = strpos($string, $wildcard)) === false) {
|
|
|
369 |
return $string;
|
|
|
370 |
}
|
|
|
371 |
|
|
|
372 |
for ($i = $pos, $last = strrpos($string, $wildcard, $pos) + 1; $i < $last; ++$i) {
|
|
|
373 |
if ($string[$i] === $wildcard) {
|
|
|
374 |
$string[$i] = call_user_func($callback);
|
|
|
375 |
}
|
|
|
376 |
}
|
|
|
377 |
|
|
|
378 |
return $string;
|
|
|
379 |
}
|
|
|
380 |
|
|
|
381 |
/**
|
|
|
382 |
* Replaces all hash sign ('#') occurrences with a random number
|
|
|
383 |
* Replaces all percentage sign ('%') occurrences with a not null number
|
|
|
384 |
*
|
|
|
385 |
* @param string $string String that needs to bet parsed
|
|
|
386 |
*
|
|
|
387 |
* @return string
|
|
|
388 |
*/
|
|
|
389 |
public static function numerify($string = '###')
|
|
|
390 |
{
|
|
|
391 |
// instead of using randomDigit() several times, which is slow,
|
|
|
392 |
// count the number of hashes and generate once a large number
|
|
|
393 |
$toReplace = [];
|
|
|
394 |
|
|
|
395 |
if (($pos = strpos($string, '#')) !== false) {
|
|
|
396 |
for ($i = $pos, $last = strrpos($string, '#', $pos) + 1; $i < $last; ++$i) {
|
|
|
397 |
if ($string[$i] === '#') {
|
|
|
398 |
$toReplace[] = $i;
|
|
|
399 |
}
|
|
|
400 |
}
|
|
|
401 |
}
|
|
|
402 |
|
|
|
403 |
if ($nbReplacements = count($toReplace)) {
|
|
|
404 |
$maxAtOnce = strlen((string) mt_getrandmax()) - 1;
|
|
|
405 |
$numbers = '';
|
|
|
406 |
$i = 0;
|
|
|
407 |
|
|
|
408 |
while ($i < $nbReplacements) {
|
|
|
409 |
$size = min($nbReplacements - $i, $maxAtOnce);
|
|
|
410 |
$numbers .= str_pad(static::randomNumber($size), $size, '0', STR_PAD_LEFT);
|
|
|
411 |
$i += $size;
|
|
|
412 |
}
|
|
|
413 |
|
|
|
414 |
for ($i = 0; $i < $nbReplacements; ++$i) {
|
|
|
415 |
$string[$toReplace[$i]] = $numbers[$i];
|
|
|
416 |
}
|
|
|
417 |
}
|
|
|
418 |
$string = self::replaceWildcard($string, '%', [static::class, 'randomDigitNotNull']);
|
|
|
419 |
|
|
|
420 |
return $string;
|
|
|
421 |
}
|
|
|
422 |
|
|
|
423 |
/**
|
|
|
424 |
* Replaces all question mark ('?') occurrences with a random letter
|
|
|
425 |
*
|
|
|
426 |
* @param string $string String that needs to bet parsed
|
|
|
427 |
*
|
|
|
428 |
* @return string
|
|
|
429 |
*/
|
|
|
430 |
public static function lexify($string = '????')
|
|
|
431 |
{
|
|
|
432 |
return self::replaceWildcard($string, '?', [static::class, 'randomLetter']);
|
|
|
433 |
}
|
|
|
434 |
|
|
|
435 |
/**
|
|
|
436 |
* Replaces hash signs ('#') and question marks ('?') with random numbers and letters
|
|
|
437 |
* An asterisk ('*') is replaced with either a random number or a random letter
|
|
|
438 |
*
|
|
|
439 |
* @param string $string String that needs to be parsed
|
|
|
440 |
*
|
|
|
441 |
* @return string
|
|
|
442 |
*/
|
|
|
443 |
public static function bothify($string = '## ??')
|
|
|
444 |
{
|
|
|
445 |
$string = self::replaceWildcard($string, '*', static function () {
|
|
|
446 |
return mt_rand(0, 1) ? '#' : '?';
|
|
|
447 |
});
|
|
|
448 |
|
|
|
449 |
return static::lexify(static::numerify($string));
|
|
|
450 |
}
|
|
|
451 |
|
|
|
452 |
/**
|
|
|
453 |
* Replaces * signs with random numbers and letters and special characters
|
|
|
454 |
*
|
|
|
455 |
* @example $faker->asciify(''********'); // "s5'G!uC3"
|
|
|
456 |
*
|
|
|
457 |
* @param string $string String that needs to bet parsed
|
|
|
458 |
*
|
|
|
459 |
* @return string
|
|
|
460 |
*/
|
|
|
461 |
public static function asciify($string = '****')
|
|
|
462 |
{
|
|
|
463 |
return preg_replace_callback('/\*/u', [static::class, 'randomAscii'], $string);
|
|
|
464 |
}
|
|
|
465 |
|
|
|
466 |
/**
|
|
|
467 |
* Transforms a basic regular expression into a random string satisfying the expression.
|
|
|
468 |
*
|
|
|
469 |
* @example $faker->regexify('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'); // sm0@y8k96a.ej
|
|
|
470 |
*
|
|
|
471 |
* Regex delimiters '/.../' and begin/end markers '^...$' are ignored.
|
|
|
472 |
*
|
|
|
473 |
* Only supports a small subset of the regex syntax. For instance,
|
|
|
474 |
* unicode, negated classes, unbounded ranges, subpatterns, back references,
|
|
|
475 |
* assertions, recursive patterns, and comments are not supported. Escaping
|
|
|
476 |
* support is extremely fragile.
|
|
|
477 |
*
|
|
|
478 |
* This method is also VERY slow. Use it only when no other formatter
|
|
|
479 |
* can generate the fake data you want. For instance, prefer calling
|
|
|
480 |
* `$faker->email` rather than `regexify` with the previous regular
|
|
|
481 |
* expression.
|
|
|
482 |
*
|
|
|
483 |
* Also note than `bothify` can probably do most of what this method does,
|
|
|
484 |
* but much faster. For instance, for a dummy email generation, try
|
|
|
485 |
* `$faker->bothify('?????????@???.???')`.
|
|
|
486 |
*
|
|
|
487 |
* @see https://github.com/icomefromthenet/ReverseRegex for a more robust implementation
|
|
|
488 |
*
|
|
|
489 |
* @param string $regex A regular expression (delimiters are optional)
|
|
|
490 |
*
|
|
|
491 |
* @return string
|
|
|
492 |
*/
|
|
|
493 |
public static function regexify($regex = '')
|
|
|
494 |
{
|
|
|
495 |
// ditch the anchors
|
|
|
496 |
$regex = preg_replace('/^\/?\^?/', '', $regex);
|
|
|
497 |
$regex = preg_replace('/\$?\/?$/', '', $regex);
|
|
|
498 |
// All {2} become {2,2}
|
|
|
499 |
$regex = preg_replace('/\{(\d+)\}/', '{\1,\1}', $regex);
|
|
|
500 |
// Single-letter quantifiers (?, *, +) become bracket quantifiers ({0,1}, {0,rand}, {1, rand})
|
|
|
501 |
$regex = preg_replace('/(?<!\\\)\?/', '{0,1}', $regex);
|
|
|
502 |
$regex = preg_replace('/(?<!\\\)\*/', '{0,' . static::randomDigitNotNull() . '}', $regex);
|
|
|
503 |
$regex = preg_replace('/(?<!\\\)\+/', '{1,' . static::randomDigitNotNull() . '}', $regex);
|
|
|
504 |
// [12]{1,2} becomes [12] or [12][12]
|
|
|
505 |
$regex = preg_replace_callback('/(\[[^\]]+\])\{(\d+),(\d+)\}/', static function ($matches) {
|
|
|
506 |
return str_repeat($matches[1], Base::randomElement(range($matches[2], $matches[3])));
|
|
|
507 |
}, $regex);
|
|
|
508 |
// (12|34){1,2} becomes (12|34) or (12|34)(12|34)
|
|
|
509 |
$regex = preg_replace_callback('/(\([^\)]+\))\{(\d+),(\d+)\}/', static function ($matches) {
|
|
|
510 |
return str_repeat($matches[1], Base::randomElement(range($matches[2], $matches[3])));
|
|
|
511 |
}, $regex);
|
|
|
512 |
// A{1,2} becomes A or AA or \d{3} becomes \d\d\d
|
|
|
513 |
$regex = preg_replace_callback('/(\\\?.)\{(\d+),(\d+)\}/', static function ($matches) {
|
|
|
514 |
return str_repeat($matches[1], Base::randomElement(range($matches[2], $matches[3])));
|
|
|
515 |
}, $regex);
|
|
|
516 |
// (this|that) becomes 'this' or 'that'
|
|
|
517 |
$regex = preg_replace_callback('/\((.*?)\)/', static function ($matches) {
|
|
|
518 |
return Base::randomElement(explode('|', str_replace(['(', ')'], '', $matches[1])));
|
|
|
519 |
}, $regex);
|
|
|
520 |
// All A-F inside of [] become ABCDEF
|
|
|
521 |
$regex = preg_replace_callback('/\[([^\]]+)\]/', static function ($matches) {
|
|
|
522 |
return '[' . preg_replace_callback('/(\w|\d)\-(\w|\d)/', static function ($range) {
|
|
|
523 |
return implode('', range($range[1], $range[2]));
|
|
|
524 |
}, $matches[1]) . ']';
|
|
|
525 |
}, $regex);
|
|
|
526 |
// All [ABC] become B (or A or C)
|
|
|
527 |
$regex = preg_replace_callback('/\[([^\]]+)\]/', static function ($matches) {
|
|
|
528 |
// remove backslashes (that are not followed by another backslash) because they are escape characters
|
|
|
529 |
$match = preg_replace('/\\\(?!\\\)/', '', $matches[1]);
|
|
|
530 |
$randomElement = Base::randomElement(str_split($match));
|
|
|
531 |
//[.] should not be a random character, but a literal .
|
|
|
532 |
return str_replace('.', '\.', $randomElement);
|
|
|
533 |
}, $regex);
|
|
|
534 |
// replace \d with number and \w with letter and . with ascii
|
|
|
535 |
$regex = preg_replace_callback('/\\\w/', [static::class, 'randomLetter'], $regex);
|
|
|
536 |
$regex = preg_replace_callback('/\\\d/', [static::class, 'randomDigit'], $regex);
|
|
|
537 |
//replace . with ascii except backslash
|
|
|
538 |
$regex = preg_replace_callback('/(?<!\\\)\./', static function () {
|
|
|
539 |
$chr = static::asciify('*');
|
|
|
540 |
|
|
|
541 |
if ($chr === '\\') {
|
|
|
542 |
$chr .= '\\';
|
|
|
543 |
}
|
|
|
544 |
|
|
|
545 |
return $chr;
|
|
|
546 |
}, $regex);
|
|
|
547 |
// remove remaining single backslashes
|
|
|
548 |
$regex = str_replace('\\\\', '[:escaped_backslash:]', $regex);
|
|
|
549 |
$regex = str_replace('\\', '', $regex);
|
|
|
550 |
$regex = str_replace('[:escaped_backslash:]', '\\', $regex);
|
|
|
551 |
|
|
|
552 |
// phew
|
|
|
553 |
return $regex;
|
|
|
554 |
}
|
|
|
555 |
|
|
|
556 |
/**
|
|
|
557 |
* Converts string to lowercase.
|
|
|
558 |
* Uses mb_string extension if available.
|
|
|
559 |
*
|
|
|
560 |
* @param string $string String that should be converted to lowercase
|
|
|
561 |
*
|
|
|
562 |
* @return string
|
|
|
563 |
*/
|
|
|
564 |
public static function toLower($string = '')
|
|
|
565 |
{
|
|
|
566 |
return extension_loaded('mbstring') ? mb_strtolower($string, 'UTF-8') : strtolower($string);
|
|
|
567 |
}
|
|
|
568 |
|
|
|
569 |
/**
|
|
|
570 |
* Converts string to uppercase.
|
|
|
571 |
* Uses mb_string extension if available.
|
|
|
572 |
*
|
|
|
573 |
* @param string $string String that should be converted to uppercase
|
|
|
574 |
*
|
|
|
575 |
* @return string
|
|
|
576 |
*/
|
|
|
577 |
public static function toUpper($string = '')
|
|
|
578 |
{
|
|
|
579 |
return extension_loaded('mbstring') ? mb_strtoupper($string, 'UTF-8') : strtoupper($string);
|
|
|
580 |
}
|
|
|
581 |
|
|
|
582 |
/**
|
|
|
583 |
* Chainable method for making any formatter optional.
|
|
|
584 |
*
|
|
|
585 |
* @param float|int $weight Set the probability of receiving a null value.
|
|
|
586 |
* "0" will always return null, "1" will always return the generator.
|
|
|
587 |
* If $weight is an integer value, then the same system works
|
|
|
588 |
* between 0 (always get false) and 100 (always get true).
|
|
|
589 |
*
|
|
|
590 |
* @return mixed|null
|
|
|
591 |
*/
|
|
|
592 |
public function optional($weight = 0.5, $default = null)
|
|
|
593 |
{
|
|
|
594 |
// old system based on 0.1 <= $weight <= 0.9
|
|
|
595 |
// TODO: remove in v2
|
|
|
596 |
if ($weight > 0 && $weight < 1 && mt_rand() / mt_getrandmax() <= $weight) {
|
|
|
597 |
return $this->generator;
|
|
|
598 |
}
|
|
|
599 |
|
|
|
600 |
// new system with percentage
|
|
|
601 |
if (is_int($weight) && mt_rand(1, 100) <= $weight) {
|
|
|
602 |
return $this->generator;
|
|
|
603 |
}
|
|
|
604 |
|
|
|
605 |
return new DefaultGenerator($default);
|
|
|
606 |
}
|
|
|
607 |
|
|
|
608 |
/**
|
|
|
609 |
* Chainable method for making any formatter unique.
|
|
|
610 |
*
|
|
|
611 |
* <code>
|
|
|
612 |
* // will never return twice the same value
|
|
|
613 |
* $faker->unique()->randomElement(array(1, 2, 3));
|
|
|
614 |
* </code>
|
|
|
615 |
*
|
|
|
616 |
* @param bool $reset If set to true, resets the list of existing values
|
|
|
617 |
* @param int $maxRetries Maximum number of retries to find a unique value,
|
|
|
618 |
* After which an OverflowException is thrown.
|
|
|
619 |
*
|
|
|
620 |
* @throws \OverflowException When no unique value can be found by iterating $maxRetries times
|
|
|
621 |
*
|
|
|
622 |
* @return UniqueGenerator A proxy class returning only non-existing values
|
|
|
623 |
*/
|
|
|
624 |
public function unique($reset = false, $maxRetries = 10000)
|
|
|
625 |
{
|
|
|
626 |
if ($reset || !$this->unique) {
|
|
|
627 |
$this->unique = new UniqueGenerator($this->generator, $maxRetries);
|
|
|
628 |
}
|
|
|
629 |
|
|
|
630 |
return $this->unique;
|
|
|
631 |
}
|
|
|
632 |
|
|
|
633 |
/**
|
|
|
634 |
* Chainable method for forcing any formatter to return only valid values.
|
|
|
635 |
*
|
|
|
636 |
* The value validity is determined by a function passed as first argument.
|
|
|
637 |
*
|
|
|
638 |
* <code>
|
|
|
639 |
* $values = array();
|
|
|
640 |
* $evenValidator = function ($digit) {
|
|
|
641 |
* return $digit % 2 === 0;
|
|
|
642 |
* };
|
|
|
643 |
* for ($i=0; $i < 10; $i++) {
|
|
|
644 |
* $values []= $faker->valid($evenValidator)->randomDigit;
|
|
|
645 |
* }
|
|
|
646 |
* print_r($values); // [0, 4, 8, 4, 2, 6, 0, 8, 8, 6]
|
|
|
647 |
* </code>
|
|
|
648 |
*
|
|
|
649 |
* @param Closure $validator A function returning true for valid values
|
|
|
650 |
* @param int $maxRetries Maximum number of retries to find a unique value,
|
|
|
651 |
* After which an OverflowException is thrown.
|
|
|
652 |
*
|
|
|
653 |
* @throws \OverflowException When no valid value can be found by iterating $maxRetries times
|
|
|
654 |
*
|
|
|
655 |
* @return ValidGenerator A proxy class returning only valid values
|
|
|
656 |
*/
|
|
|
657 |
public function valid($validator = null, $maxRetries = 10000)
|
|
|
658 |
{
|
|
|
659 |
return new ValidGenerator($this->generator, $validator, $maxRetries);
|
|
|
660 |
}
|
|
|
661 |
}
|